diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1cd0cc9fb03..be7d2b3ed32 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -50,7 +50,7 @@ jobs: cd zip zip -r liquidbounce.zip * md5sum liquidbounce.zip - curl --connect-timeout 30 -m 300 -X POST -F "artifact=@liquidbounce.zip" -H "Authorization: ${{ secrets.NIGHTLY_PASS }}" -F "gh_id=${{ github.event.head_commit.id }}" -F "gh_ref=${{ github.ref }}" -F "gh_message=${{ github.event.head_commit.message }}" -F "gh_timestamp=${{ github.event.head_commit.timestamp }}" -F "lb_version=$LB_VERSION" -F "mc_version=$MINECRAFT_VERSION" -F "subsystem=fabric" -F "jre_version=21" -F "jre_distribution=graalvm" -F "fabric_loader_version=$LOADER_VERSION" -F "fabric_api_version=$FABRICAPI_VERSION" -F "kotlin_version=$KOTLIN_VERSION" -F "fabric_kotlin_version=$FABRIC_KOTLIN_VERSION" https://api.liquidbounce.net/api/v1/version/new + curl --connect-timeout 30 -m 300 -X POST -F "artifact=@liquidbounce.zip" -H "Authorization: ${{ secrets.NIGHTLY_PASS }}" -F "gh_id=${{ github.event.head_commit.id }}" -F "gh_ref=${{ github.ref }}" -F "gh_message=${{ github.event.head_commit.message }}" -F "gh_timestamp=${{ github.event.head_commit.timestamp }}" -F "lb_version=$LB_VERSION" -F "mc_version=$MINECRAFT_VERSION" -F "subsystem=fabric" -F "jre_version=21" -F "fabric_loader_version=$LOADER_VERSION" -F "fabric_api_version=$FABRICAPI_VERSION" -F "kotlin_version=$KOTLIN_VERSION" -F "fabric_kotlin_version=$FABRIC_KOTLIN_VERSION" https://api.liquidbounce.net/api/v1/version/new verify-pr: runs-on: ubuntu-latest diff --git a/config/detekt/baseline.xml b/config/detekt/baseline.xml index a6e68651c10..4fdb3162468 100644 --- a/config/detekt/baseline.xml +++ b/config/detekt/baseline.xml @@ -39,14 +39,11 @@ BracesOnIfStatements:ModuleTimerRange.kt$ModuleTimerRange$if BracesOnIfStatements:RenderShortcuts.kt$else BracesOnIfStatements:RenderShortcuts.kt$if - BracesOnIfStatements:SpeedGeneric.kt$SpeedBHopBase$if BracesOnIfStatements:SpeedGrimCollide.kt$SpeedGrimCollide$if - BracesOnIfStatements:SpeedHypixelBHop.kt$SpeedHypixelBHop$if BracesOnIfStatements:SpeedPreventDeadlyJump.kt$SpeedPreventDeadlyJump$if BracesOnIfStatements:TargetFinding.kt$BlockPlacementTarget$if BracesOnIfStatements:TargetRenderer.kt$WorldTargetRenderer.GlowingCircle$else BracesOnIfStatements:TargetRenderer.kt$WorldTargetRenderer.GlowingCircle$if - CognitiveComplexMethod:AStarMode.kt$AStarMode$override fun enable() CognitiveComplexMethod:AStarMode.kt$AStarMode$private fun findPath(start: Vec3i, end: Vec3i, maxCost: Int, maxIterations: Int = 500): List<Vec3i> CognitiveComplexMethod:AutoConfig.kt$AutoConfig$fun handlePossibleAutoConfig(jsonObject: JsonObject) CognitiveComplexMethod:BlockExtensions.kt$fun Block?.isInteractable(blockState: BlockState?): Boolean @@ -124,7 +121,6 @@ PrintStackTrace:CommandManager.kt$CommandManager$e ReturnCount:IntegrationListener.kt$IntegrationListener$private fun handleScreenSituation(screen: Screen?): Boolean ReturnCount:SpeedAntiCornerBump.kt$SpeedAntiCornerBump$fun getSuggestedJumpDelay( simulatedPlayer: SimulatedPlayer, n: Int = 2, ): Int? - SpreadOperator:AStarMode.kt$AStarMode$( Vec3i(-1, 0, 0), // left Vec3i(1, 0, 0), // right *(-9..9).map { Vec3i(0, it, 0) }.toTypedArray(), // up- and down Vec3i(0, 0, -1), // front Vec3i(0, 0, 1) // back ) SpreadOperator:ModuleVomit.kt$ModuleVomit$( *emptySlots.map { slot -> CreativeInventoryAction.performFillSlot(randomStack, slot) } .toTypedArray(), *emptySlots.map { slot -> ClickInventoryAction.performThrow(null, slot) } .toTypedArray() ) StringLiteralDuplication:AutoQueueGommeDuels.kt$AutoQueueGommeDuels$"AutoPlay" StringLiteralDuplication:ScriptSetting.kt$ScriptSetting$"default" diff --git a/gradle.properties b/gradle.properties index 1f0f5e452a4..99028aa7019 100644 --- a/gradle.properties +++ b/gradle.properties @@ -30,7 +30,7 @@ fabric_version=0.107.0+1.21.1 # Loom loom_version=1.8-SNAPSHOT # Mod Properties -mod_version=0.20.1 +mod_version=0.21.1 maven_group=net.ccbluex archives_base_name=liquidbounce # Kotlin diff --git a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/block/MixinAbstractBlock.java b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/block/MixinBlockCollisionSpliterator.java similarity index 62% rename from src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/block/MixinAbstractBlock.java rename to src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/block/MixinBlockCollisionSpliterator.java index 0b42588c5d1..c24d9ecb7af 100644 --- a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/block/MixinAbstractBlock.java +++ b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/block/MixinBlockCollisionSpliterator.java @@ -18,39 +18,43 @@ */ package net.ccbluex.liquidbounce.injection.mixins.minecraft.block; -import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.sugar.Local; import net.ccbluex.liquidbounce.common.ShapeFlag; import net.ccbluex.liquidbounce.event.EventManager; import net.ccbluex.liquidbounce.event.events.BlockShapeEvent; -import net.minecraft.block.AbstractBlock; import net.minecraft.block.BlockState; -import net.minecraft.block.ShapeContext; import net.minecraft.util.math.BlockPos; import net.minecraft.util.shape.VoxelShape; -import net.minecraft.world.BlockView; +import net.minecraft.world.BlockCollisionSpliterator; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; -@Mixin(AbstractBlock.class) -public class MixinAbstractBlock { +@Mixin(BlockCollisionSpliterator.class) +public class MixinBlockCollisionSpliterator { + + @Shadow + @Final + private BlockPos.Mutable pos; /** * Hook collision shape event * * @param original voxel shape - * @param state block state - * @param world block world - * @param pos block position - * @param context shape context * @return possibly modified voxel shape */ - @ModifyReturnValue(method = "getCollisionShape", at = @At("RETURN")) - private VoxelShape hookCollisionShape(VoxelShape original, BlockState state, BlockView world, BlockPos pos, ShapeContext context) { - if (pos == null || ShapeFlag.noShapeChange) { + @ModifyExpressionValue(method = "computeNext", at = @At( + value = "INVOKE", + target = "Lnet/minecraft/block/BlockState;getCollisionShape(Lnet/minecraft/world/BlockView;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/ShapeContext;)Lnet/minecraft/util/shape/VoxelShape;" + )) + private VoxelShape hookCollisionShape(VoxelShape original, @Local BlockState blockState) { + if (this.pos == null || ShapeFlag.noShapeChange) { return original; } - final BlockShapeEvent shapeEvent = EventManager.INSTANCE.callEvent(new BlockShapeEvent(state, pos, original)); + final BlockShapeEvent shapeEvent = EventManager.INSTANCE.callEvent(new BlockShapeEvent(blockState, this.pos, original)); return shapeEvent.getShape(); } diff --git a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/block/MixinCactusBlock.java b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/block/MixinCactusBlock.java deleted file mode 100644 index 0aea16d0900..00000000000 --- a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/block/MixinCactusBlock.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * This file is part of LiquidBounce (https://github.com/CCBlueX/LiquidBounce) - * - * Copyright (c) 2015 - 2024 CCBlueX - * - * LiquidBounce is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * LiquidBounce is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with LiquidBounce. If not, see . - */ -package net.ccbluex.liquidbounce.injection.mixins.minecraft.block; - -import net.ccbluex.liquidbounce.common.ShapeFlag; -import net.ccbluex.liquidbounce.event.EventManager; -import net.ccbluex.liquidbounce.event.events.BlockShapeEvent; -import net.minecraft.block.BlockState; -import net.minecraft.block.CactusBlock; -import net.minecraft.block.ShapeContext; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.shape.VoxelShape; -import net.minecraft.world.BlockView; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -@Mixin(CactusBlock.class) -public abstract class MixinCactusBlock { - - /** - * Hook collision shape event - */ - @Inject(method = "getCollisionShape", at = @At("RETURN"), cancellable = true) - private void hookCollisionShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context, CallbackInfoReturnable callback) { - if (!ShapeFlag.noShapeChange) { - final BlockShapeEvent shapeEvent = new BlockShapeEvent(state, pos, callback.getReturnValue()); - EventManager.INSTANCE.callEvent(shapeEvent); - callback.setReturnValue(shapeEvent.getShape()); - } - } - -} diff --git a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/block/MixinFluidBlock.java b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/block/MixinFluidBlock.java deleted file mode 100644 index 68fc3a2e3f1..00000000000 --- a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/block/MixinFluidBlock.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * This file is part of LiquidBounce (https://github.com/CCBlueX/LiquidBounce) - * - * Copyright (c) 2015 - 2024 CCBlueX - * - * LiquidBounce is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * LiquidBounce is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with LiquidBounce. If not, see . - */ -package net.ccbluex.liquidbounce.injection.mixins.minecraft.block; - -import com.llamalad7.mixinextras.injector.ModifyReturnValue; -import net.ccbluex.liquidbounce.common.ShapeFlag; -import net.ccbluex.liquidbounce.event.EventManager; -import net.ccbluex.liquidbounce.event.events.BlockShapeEvent; -import net.minecraft.block.BlockState; -import net.minecraft.block.FluidBlock; -import net.minecraft.block.ShapeContext; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.shape.VoxelShape; -import net.minecraft.world.BlockView; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; - -@Mixin(FluidBlock.class) -public class MixinFluidBlock { - - /** - * Hook collision shape event - * - * @param original voxel shape - * @param state block state - * @param world block world - * @param pos block position - * @param context shape context - * @return possibly modified voxel shape - */ - @ModifyReturnValue(method = "getCollisionShape", at = @At("RETURN")) - private VoxelShape hookCollisionShape(VoxelShape original, BlockState state, BlockView world, BlockPos pos, ShapeContext context) { - if (pos == null || ShapeFlag.noShapeChange) { - return original; - } - - final BlockShapeEvent shapeEvent = new BlockShapeEvent(state, pos, original); - EventManager.INSTANCE.callEvent(shapeEvent); - return shapeEvent.getShape(); - } - -} diff --git a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/block/MixinSnowBlock.java b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/block/MixinSnowBlock.java deleted file mode 100644 index c7c593750b6..00000000000 --- a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/block/MixinSnowBlock.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * This file is part of LiquidBounce (https://github.com/CCBlueX/LiquidBounce) - * - * Copyright (c) 2015 - 2024 CCBlueX - * - * LiquidBounce is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * LiquidBounce is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with LiquidBounce. If not, see . - */ -package net.ccbluex.liquidbounce.injection.mixins.minecraft.block; - -import com.llamalad7.mixinextras.injector.ModifyReturnValue; -import net.ccbluex.liquidbounce.common.ShapeFlag; -import net.ccbluex.liquidbounce.event.EventManager; -import net.ccbluex.liquidbounce.event.events.BlockShapeEvent; -import net.minecraft.block.BlockState; -import net.minecraft.block.ShapeContext; -import net.minecraft.block.SnowBlock; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.shape.VoxelShape; -import net.minecraft.world.BlockView; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; - -@Mixin(SnowBlock.class) -public abstract class MixinSnowBlock { - - /** - * Hook collision shape event - * - * @param original voxel shape - * @param state block state - * @param world block world - * @param pos block position - * @param context shape context - * @return possibly modified voxel shape - */ - @ModifyReturnValue(method = "getCollisionShape", at = @At("RETURN")) - private VoxelShape hookCollisionShape(VoxelShape original, BlockState state, BlockView world, BlockPos pos, ShapeContext context) { - if (pos == null || ShapeFlag.noShapeChange) { - return original; - } - - final BlockShapeEvent shapeEvent = new BlockShapeEvent(state, pos, original); - EventManager.INSTANCE.callEvent(shapeEvent); - return shapeEvent.getShape(); - } - -} diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/command/commands/module/CommandInvsee.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/command/commands/module/CommandInvsee.kt index 9b51929bac6..b8ffb69e9a2 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/command/commands/module/CommandInvsee.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/command/commands/module/CommandInvsee.kt @@ -23,16 +23,13 @@ import net.ccbluex.liquidbounce.features.command.Command import net.ccbluex.liquidbounce.features.command.CommandException import net.ccbluex.liquidbounce.features.command.CommandFactory import net.ccbluex.liquidbounce.features.command.builder.CommandBuilder -import net.ccbluex.liquidbounce.features.command.builder.ParameterBuilder +import net.ccbluex.liquidbounce.features.command.builder.playerParameter import net.ccbluex.liquidbounce.features.module.modules.misc.ModuleInventoryTracker import net.ccbluex.liquidbounce.utils.client.mc +import net.ccbluex.liquidbounce.utils.client.network import net.ccbluex.liquidbounce.utils.client.world -import net.minecraft.client.gui.DrawContext -import net.minecraft.client.gui.screen.ingame.InventoryScreen -import net.minecraft.client.network.AbstractClientPlayerEntity -import net.minecraft.entity.player.PlayerEntity -import net.minecraft.screen.slot.Slot -import net.minecraft.screen.slot.SlotActionType +import net.ccbluex.liquidbounce.utils.inventory.ViewedInventoryScreen +import java.util.* /** * Command Invsee @@ -43,47 +40,32 @@ import net.minecraft.screen.slot.SlotActionType */ object CommandInvsee : CommandFactory { - var viewedPlayer: AbstractClientPlayerEntity? = null + var viewedPlayer: UUID? = null override fun createCommand(): Command { return CommandBuilder .begin("invsee") .requiresIngame() .parameter( - ParameterBuilder - .begin("name") - .verifiedBy(ParameterBuilder.STRING_VALIDATOR) - .useMinecraftAutoCompletion() + playerParameter() .required() .build() ) .handler { command, args -> - val inputName = (args[0] as String) - val player = world.players.find { it.nameForScoreboard.equals(inputName, true) } - ?: throw CommandException(command.result("playerNotFound", inputName)) + val inputName = args[0] as String + val playerID = network.playerList.find { it.profile.name.equals(inputName, true) }?.profile?.id + val player = { world.getPlayerByUuid(playerID) ?: ModuleInventoryTracker.playerMap[playerID] } + + if (playerID == null || player() == null) { + throw CommandException(command.result("playerNotFound", inputName)) + } RenderSystem.recordRenderCall { - mc.setScreen(NoInteractInventory(player)) + mc.setScreen(ViewedInventoryScreen(player)) } - viewedPlayer = player + viewedPlayer = playerID } .build() } - -} - -class NoInteractInventory(private var player: PlayerEntity) : InventoryScreen(player) { - - override fun drawBackground(context: DrawContext, delta: Float, mouseX: Int, mouseY: Int) { - context.drawTexture(BACKGROUND_TEXTURE, x, y, 0, 0, backgroundWidth, backgroundHeight) - drawEntity( - context, x + 26, y + 8, x + 75, y + 78, - 30, 0.0625f, mouseX.toFloat(), mouseY.toFloat(), - player - ) - } - - @Suppress("detekt:EmptyFunctionBlock") - override fun onMouseClick(slot: Slot?, slotId: Int, button: Int, actionType: SlotActionType?) {} } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/ModuleManager.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/ModuleManager.kt index 110ebac76c4..708d20e26dd 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/ModuleManager.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/ModuleManager.kt @@ -350,6 +350,7 @@ object ModuleManager : EventListener, Iterable by modules { ModuleBedDefender, ModuleSurround, ModulePacketMine, + ModuleHoleFiller, // Client ModuleAutoConfig, diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/combat/ModuleTimerRange.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/combat/ModuleTimerRange.kt index 3d34ee6543a..935187221d1 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/combat/ModuleTimerRange.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/combat/ModuleTimerRange.kt @@ -40,12 +40,14 @@ object ModuleTimerRange : ClientModule("TimerRange", Category.COMBAT) { private val timerBalanceLimit by float("TimerBalanceLimit", 20f, 0f..50f) private val normalSpeed by float("NormalSpeed", 0.9F, 0.1F..10F) private val inRangeSpeed by float("InRangeSpeed", 0.95F, 0.1F..10F) + private val balanceLimitSpeed by float("BalanceLimitSpeed", 0.99F, 0.1F..1F) private val boostSpeed by float("BoostTimer", 2F, 0.1F..10F).apply { tagBy(this) } private val balanceRecoveryIncrement by float("BalanceRecoveryIncrement", 1f, 1f..10f) private val distanceToSpeedUp by float("DistanceToSpeedUp", 3.5f, 0f..10f) private val distanceToPause by float("DistanceToPause", 3f, 0f..10f) private val distanceToStartWorking by float("DistanceToStartWorking", 100f, 0f..500f) private val pauseOnFlag by boolean("PauseOnFlag", true) + private val onlyOnGround by boolean("OnlyOnGround", false) private var reachedTheLimit = false private var balanceTimer = 0f @@ -56,6 +58,10 @@ object ModuleTimerRange : ClientModule("TimerRange", Category.COMBAT) { } val repeatable = tickHandler { + if (onlyOnGround && !player.isOnGround) { + return@tickHandler + } + val newTimerSpeed = updateTimerSpeed() if (newTimerSpeed != null) { @@ -66,6 +72,10 @@ object ModuleTimerRange : ClientModule("TimerRange", Category.COMBAT) { if ((balanceTimer > 0 || balanceChange > 0) && (balanceTimer < timerBalanceLimit * 2 || balanceChange < 0)) balanceTimer += balanceChange + if (balanceTimer <= timerBalanceLimit) { + Timer.requestTimerSpeed(balanceLimitSpeed, Priority.IMPORTANT_FOR_USAGE_1, this@ModuleTimerRange) + } + if (balanceTimer <= 0) { reachedTheLimit = false } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/combat/criticals/modes/CriticalsJump.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/combat/criticals/modes/CriticalsJump.kt index 2f56cf61ddd..ddb09e94625 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/combat/criticals/modes/CriticalsJump.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/combat/criticals/modes/CriticalsJump.kt @@ -232,7 +232,7 @@ object CriticalsJump : Choice("Jump") { return ticksTillFall + 1.0f < nextPossibleCrit } - fun isActive(): Boolean { + private fun isActive(): Boolean { if (!ModuleCriticals.running) { return false } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/combat/tpaura/modes/AStarMode.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/combat/tpaura/modes/AStarMode.kt index 85965a831a3..8d9fd6324ba 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/combat/tpaura/modes/AStarMode.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/combat/tpaura/modes/AStarMode.kt @@ -1,10 +1,10 @@ package net.ccbluex.liquidbounce.features.module.modules.combat.tpaura.modes +import kotlinx.coroutines.Dispatchers import net.ccbluex.liquidbounce.event.events.PacketEvent import net.ccbluex.liquidbounce.event.events.WorldRenderEvent import net.ccbluex.liquidbounce.event.handler import net.ccbluex.liquidbounce.event.tickHandler -import net.ccbluex.liquidbounce.features.module.modules.combat.tpaura.ModuleTpAura import net.ccbluex.liquidbounce.features.module.modules.combat.tpaura.ModuleTpAura.clickScheduler import net.ccbluex.liquidbounce.features.module.modules.combat.tpaura.ModuleTpAura.desyncPlayerPosition import net.ccbluex.liquidbounce.features.module.modules.combat.tpaura.ModuleTpAura.stuckChronometer @@ -18,22 +18,24 @@ import net.ccbluex.liquidbounce.utils.client.chat import net.ccbluex.liquidbounce.utils.client.markAsError import net.ccbluex.liquidbounce.utils.entity.blockVecPosition import net.ccbluex.liquidbounce.utils.entity.squaredBoxedDistanceTo -import net.ccbluex.liquidbounce.utils.math.toVec3 -import net.ccbluex.liquidbounce.utils.math.toVec3d -import net.ccbluex.liquidbounce.utils.math.toVec3i +import net.ccbluex.liquidbounce.utils.kotlin.mapArray +import net.ccbluex.liquidbounce.utils.math.* import net.minecraft.entity.LivingEntity import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket.PositionAndOnGround import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket import net.minecraft.util.math.Box import net.minecraft.util.math.Vec3i -import kotlin.concurrent.thread +import java.util.TreeSet import kotlin.math.roundToInt -data class Node(val position: Vec3i, var parent: Node? = null) { +private class Node(val position: Vec3i, var parent: Node? = null) { var g = 0 var h = 0 var f = 0 + + override fun hashCode(): Int = position.hashCode() + override fun equals(other: Any?): Boolean = other is Node && other.position == this.position } object AStarMode : TpAuraChoice("AStar") { @@ -45,8 +47,8 @@ object AStarMode : TpAuraChoice("AStar") { private val stickAt by int("Stick", 5, 1..10, "ticks") + @Volatile private var pathCache: PathCache? = null - private var pathFinderThread: Thread? = null @Suppress("unused") private val tickHandler = tickHandler { @@ -63,46 +65,36 @@ object AStarMode : TpAuraChoice("AStar") { pathCache = null } - override fun enable() { - pathFinderThread = thread(name = "TpAura-AStarPathFinder") { - while (ModuleTpAura.running) { - runCatching { - val playerPosition = player.pos - - val enemies = targetTracker.enemies().sortedBy { it.squaredBoxedDistanceTo(playerPosition) } + @Suppress("unused") + private val pathFinder = tickHandler { + waitTicks(1) - for (enemy in enemies) { - if (player.distanceTo(enemy) > maximumDistance) { - continue - } + withContext(Dispatchers.Default) { + val playerPosition = player.pos - val path = findPath( - playerPosition.toVec3i(), enemy.blockVecPosition, maximumCost - ) + val maximumDistanceSq = maximumDistance.sq() - // Skip if the path is empty - if (path.isEmpty()) { - continue - } + targetTracker.enemies().filter { + it.squaredDistanceTo(playerPosition) <= maximumDistanceSq + }.sortedBy { + it.squaredBoxedDistanceTo(playerPosition) + }.forEach { enemy -> + val path = findPath(playerPosition.toVec3i(), enemy.blockVecPosition, maximumCost) - pathCache = PathCache(enemy, path) - } + // Skip if the path is empty + if (path.isEmpty()) { + return@forEach } - try { - Thread.sleep(50) - } catch (e: InterruptedException) { - break - } + pathCache = PathCache(enemy, path) + + // Stop searching when the pathCache is ready + return@withContext } } - - super.enable() } override fun disable() { - pathFinderThread?.interrupt() - pathFinderThread = null desyncPlayerPosition = null pathCache = null super.disable() @@ -115,7 +107,9 @@ object AStarMode : TpAuraChoice("AStar") { renderEnvironmentForWorld(matrixStack) { withColor(Color4b.WHITE) { - drawLineStrip(path.map { relativeToCamera(it.toVec3d().add(0.5, 0.5, 0.5)).toVec3() }) + drawLineStrip(positions = path.mapArray { + relativeToCamera(it.toVec3d(0.5, 0.5, 0.5)).toVec3() + }) } } } @@ -148,8 +142,8 @@ object AStarMode : TpAuraChoice("AStar") { for (chunk in pathChunks) { // Check if the path is clear, this can be done by raycasting the start and end position of the chunk. - val start = chunk.first().toVec3d().add(0.5, 0.5, 0.5) - val end = chunk.last().toVec3d().add(0.5, 0.5, 0.5) + val start = chunk.first().toVec3d(0.5, 0.5, 0.5) + val end = chunk.last().toVec3d(0.5, 0.5, 0.5) if (world.getBlockCollisions(player, Box(start, end)).any()) { // If the path is not clear, we need to go one by one. @@ -175,12 +169,12 @@ object AStarMode : TpAuraChoice("AStar") { private fun findPath(start: Vec3i, end: Vec3i, maxCost: Int, maxIterations: Int = 500): List { if (start == end) return listOf(end) - val openList = mutableListOf() - val closedList = mutableListOf() val startNode = Node(start) val endNode = Node(end) - openList.add(startNode) + // Node::f won't be modified after added + val openList = TreeSet(Comparator.comparingInt(Node::f).thenComparing(Node::position)).apply { add(startNode) } + val closedList = hashSetOf() var iterations = 0 while (openList.isNotEmpty()) { @@ -189,16 +183,14 @@ object AStarMode : TpAuraChoice("AStar") { break } - val currentNode = openList.minByOrNull { it.f } ?: break - openList.remove(currentNode) + val currentNode = openList.removeFirst() closedList.add(currentNode) if (currentNode.position.isWithinDistance(endNode.position, 2.0)) { return constructPath(currentNode) } - val adjacentNodes = getAdjacentNodes(currentNode) - for (node in adjacentNodes) { + for (node in getAdjacentNodes(currentNode)) { if (node in closedList || !isPassable(node.position)) continue val tentativeG = currentNode.g + distanceBetween(currentNode.position, node.position) @@ -210,9 +202,7 @@ object AStarMode : TpAuraChoice("AStar") { node.h = distanceBetween(node.position, endNode.position) node.f = node.g + node.h - if (node !in openList) { - openList.add(node) - } + openList.add(node) } } } @@ -224,63 +214,59 @@ object AStarMode : TpAuraChoice("AStar") { val path = mutableListOf() var currentNode = node while (currentNode.parent != null) { - path.add(0, currentNode.position) + path.add(currentNode.position) currentNode = currentNode.parent!! } + path.reverse() return path } - private fun getAdjacentNodes(node: Node): List { - val adjacentNodes = mutableListOf() + private val directions = buildList(22) { + add(Vec3i(-1, 0, 0)) // left + add(Vec3i(1, 0, 0)) // right + (-9..-1).mapTo(this) { Vec3i(0, it, 0) } // down + (1..9).mapTo(this) { Vec3i(0, it, 0) } // up + add(Vec3i(0, 0, -1)) // front + add(Vec3i(0, 0, 1)) // back + } - val directions = listOf( - Vec3i(-1, 0, 0), // left - Vec3i(1, 0, 0), // right - *(-9..9).map { Vec3i(0, it, 0) }.toTypedArray(), // up- and down - Vec3i(0, 0, -1), // front - Vec3i(0, 0, 1) // back - ) + private val diagonalDirections = arrayOf( + Vec3i(-1, 0, -1), // left front + Vec3i(1, 0, -1), // right front + Vec3i(-1, 0, 1), // left back + Vec3i(1, 0, 1) // right back + ) + @Suppress("detekt:CognitiveComplexMethod") + private fun getAdjacentNodes(node: Node): List = buildList { for (direction in directions) { - val adjacentPosition = Vec3i( - node.position.x + direction.x, node.position.y + direction.y, node.position.z + direction.z - ) + val adjacentPosition = node.position + direction if (isPassable(adjacentPosition)) { - adjacentNodes.add(Node(adjacentPosition, node)) + add(Node(adjacentPosition, node)) } } - if (allowDiagonal) { - val diagonalDirections = listOf( - Vec3i(-1, 0, -1), // left front - Vec3i(1, 0, -1), // right front - Vec3i(-1, 0, 1), // left back - Vec3i(1, 0, 1) // right back - ) - - for (direction in diagonalDirections) { - val adjacentPosition = Vec3i( - node.position.x + direction.x, node.position.y + direction.y, node.position.z + direction.z - ) - val intermediatePosition1 = Vec3i(node.position.x + direction.x, node.position.y, node.position.z) - val intermediatePosition2 = Vec3i(node.position.x, node.position.y, node.position.z + direction.z) - if (isPassable(adjacentPosition) && isPassable(intermediatePosition1) && isPassable( - intermediatePosition2 - ) - ) { - adjacentNodes.add(Node(adjacentPosition, node)) - } - } + if (!allowDiagonal) { + return@buildList } - return adjacentNodes + for (direction in diagonalDirections) { + val adjacentPosition = node.position + direction + if (!isPassable(adjacentPosition)) { + continue + } + + if (isPassable(node.position.add(direction.x, 0, 0)) && isPassable(node.position.add(0, 0, direction.z))) { + add(Node(adjacentPosition, node)) + } + } } private fun isPassable(position: Vec3i): Boolean { - val collisions = world.getBlockCollisions(player, Box( - position.toVec3d(), - position.toVec3d().add(1.0, 2.0, 1.0) - )) + val start = position.toVec3d() + val end = start.add(1.0, 2.0, 1.0) + + val collisions = world.getBlockCollisions(player, Box(start, end)) return collisions.none() } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/misc/ModuleInventoryTracker.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/misc/ModuleInventoryTracker.kt index 0c088e01424..4c549a5083d 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/misc/ModuleInventoryTracker.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/misc/ModuleInventoryTracker.kt @@ -24,18 +24,18 @@ import net.ccbluex.liquidbounce.event.events.PlayerEquipmentChangeEvent import net.ccbluex.liquidbounce.event.events.WorldChangeEvent import net.ccbluex.liquidbounce.event.handler import net.ccbluex.liquidbounce.features.command.commands.module.CommandInvsee -import net.ccbluex.liquidbounce.features.command.commands.module.NoInteractInventory import net.ccbluex.liquidbounce.features.module.Category import net.ccbluex.liquidbounce.features.module.ClientModule import net.ccbluex.liquidbounce.features.module.modules.misc.antibot.ModuleAntiBot import net.ccbluex.liquidbounce.utils.client.asText +import net.ccbluex.liquidbounce.utils.inventory.ViewedInventoryScreen import net.minecraft.client.network.OtherClientPlayerEntity import net.minecraft.entity.EquipmentSlot import net.minecraft.entity.EquipmentSlot.MAINHAND import net.minecraft.entity.EquipmentSlot.OFFHAND import net.minecraft.entity.EquipmentSlot.Type.* +import net.minecraft.entity.player.PlayerEntity import net.minecraft.item.ItemStack -import net.minecraft.text.Text import net.minecraft.util.Formatting import java.util.* @@ -48,33 +48,37 @@ import java.util.* */ object ModuleInventoryTracker : ClientModule("InventoryTracker", Category.MISC) { - private val playerMap = HashMap() + /** Saves the non-persistent player object associated with the uuid. + * This makes it possible to look up inventories of players which aren't in + * the render distance. */ + private val savePlayers by boolean("SavePlayers", false).onChanged { playerMap.clear() } + + private val inventoryMap = HashMap() + val playerMap = HashMap() @Suppress("unused") val playerEquipmentChangeHandler = handler { event -> val player = event.player - if (player !is OtherClientPlayerEntity || ModuleAntiBot.isBot(player)) { - return@handler - } + if (player !is OtherClientPlayerEntity || ModuleAntiBot.isBot(player)) return@handler val updatedSlot = event.equipmentSlot - if (updatedSlot.type == ANIMAL_ARMOR) { - return@handler - } + if (updatedSlot.type == ANIMAL_ARMOR) return@handler val newItemStack = event.itemStack val mainHandStack = if (updatedSlot == MAINHAND) newItemStack else player.mainHandStack val offHandStack = if (updatedSlot == OFFHAND) newItemStack else player.offHandStack - val trackedInventory = playerMap.getOrPut(player.uuid) { TrackedInventory() } + val trackedInventory = inventoryMap.getOrPut(player.uuid) { TrackedInventory() } + if (savePlayers) { + playerMap[player.uuid] = player + } when (updatedSlot.type) { HAND -> { trackedInventory.update(offHandStack, OFFHAND) trackedInventory.update(mainHandStack, MAINHAND) } - HUMANOID_ARMOR -> trackedInventory.update(newItemStack, updatedSlot) else -> {} } @@ -93,34 +97,27 @@ object ModuleInventoryTracker : ClientModule("InventoryTracker", Category.MISC) override fun disable() = reset() - val worldChangeHandler = handler { - reset() - } + val worldChangeHandler = handler { reset() } private fun reset() { - playerMap.keys.forEach { uuid -> + inventoryMap.keys.forEach { uuid -> val player = world.players.find { it.uuid == uuid } ?: return@forEach for (i in 1 until player.inventory.main.size) { player.inventory.main[i] = ItemStack.EMPTY } } - + inventoryMap.clear() playerMap.clear() } @Suppress("unused") val itemLoreQueryHandler = handler { event -> - if (!running || mc.currentScreen !is NoInteractInventory) { - return@handler - } - - val player = CommandInvsee.viewedPlayer ?: return@handler - val timeStamp = playerMap[player.uuid]?.timeMap?.getLong(event.itemStack)?.takeIf { it != 0L } ?: return@handler + if (mc.currentScreen !is ViewedInventoryScreen) return@handler + val player = CommandInvsee.viewedPlayer + val timeStamp = inventoryMap[player]?.timeMap?.getLong(event.itemStack)?.takeIf { it != 0L } ?: return@handler val lastSeen = System.currentTimeMillis() - timeStamp event.lore.add( - Text.empty().styled { it.withFormatting(Formatting.RESET) }.append( - "Last Seen: ${toMinutesSeconds(lastSeen)}".asText().styled { it.withFormatting(Formatting.GRAY) } - ) + "Last Seen: ${toMinutesSeconds(lastSeen)}".asText().styled { it.withFormatting(Formatting.GRAY) } ) } @@ -143,9 +140,7 @@ class TrackedInventory { */ fun update(newItemStack: ItemStack, updatedSlot: EquipmentSlot) { items.removeIf { it.count == 0 } - if (newItemStack.isEmpty) { - return - } + if (newItemStack.isEmpty) return items.removeIf { newItemStack.item == it.item && newItemStack.enchantments == it.enchantments } if (updatedSlot.type == HAND) { @@ -157,5 +152,4 @@ class TrackedInventory { } } } - } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/misc/ModulePacketLogger.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/misc/ModulePacketLogger.kt index 11c2a1f12b1..2cbc7072f73 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/misc/ModulePacketLogger.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/misc/ModulePacketLogger.kt @@ -21,6 +21,7 @@ package net.ccbluex.liquidbounce.features.module.modules.misc import net.ccbluex.liquidbounce.event.events.PacketEvent import net.ccbluex.liquidbounce.event.events.TransferOrigin import net.ccbluex.liquidbounce.event.handler +import net.ccbluex.liquidbounce.features.misc.HideAppearance.isDestructed import net.ccbluex.liquidbounce.features.module.Category import net.ccbluex.liquidbounce.features.module.ClientModule import net.ccbluex.liquidbounce.utils.client.MessageMetadata @@ -159,4 +160,7 @@ object ModulePacketLogger : ClientModule("PacketLogger", Category.MISC) { } } + override val running: Boolean + get() = !isDestructed && enabled + } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/ModuleSpeed.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/ModuleSpeed.kt index 78a30804065..23696490c44 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/ModuleSpeed.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/ModuleSpeed.kt @@ -103,9 +103,12 @@ object ModuleSpeed : ClientModule("Speed", Category.MOVEMENT) { private val notDuringScaffold by boolean("NotDuringScaffold", true) private val notWhileSneaking by boolean("NotWhileSneaking", false) + private val avoidEdgeBump by boolean("AvoidEdgeBump", true) + init { tree(OnlyInCombat) tree(OnlyOnPotionEffect) + tree(SpeedYawOffset) } override val running: Boolean @@ -133,9 +136,6 @@ object ModuleSpeed : ClientModule("Speed", Category.MOVEMENT) { else -> true } - fun shouldDelayJump() = !mc.options.jumpKey.isPressed && (SpeedAntiCornerBump.shouldDelayJump() - || CriticalsJump.shouldWaitForJump()) - private object OnlyInCombat : ToggleableConfigurable(this, "OnlyInCombat", false) { val modes = choices(this, "Mode", { it.choices[0] }, @@ -184,4 +184,16 @@ object ModuleSpeed : ClientModule("Speed", Category.MOVEMENT) { abstract fun checkPotionEffects(): Boolean } + internal fun doOptimizationsPreventJump(): Boolean { + if (CriticalsJump.running && CriticalsJump.shouldWaitForJump(0.42f)) { + return true + } + + if (avoidEdgeBump && SpeedAntiCornerBump.shouldDelayJump()) { + return true + } + + return false + } + } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/SpeedYawOffset.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/SpeedYawOffset.kt new file mode 100644 index 00000000000..8ec4158cb38 --- /dev/null +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/SpeedYawOffset.kt @@ -0,0 +1,93 @@ +/* + * This file is part of LiquidBounce (https://github.com/CCBlueX/LiquidBounce) + * + * Copyright (c) 2015 - 2024 CCBlueX + * + * LiquidBounce is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LiquidBounce is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LiquidBounce. If not, see . + */ +package net.ccbluex.liquidbounce.features.module.modules.movement.speed + +import net.ccbluex.liquidbounce.config.types.NamedChoice +import net.ccbluex.liquidbounce.config.types.ToggleableConfigurable +import net.ccbluex.liquidbounce.event.events.GameTickEvent +import net.ccbluex.liquidbounce.event.handler +import net.ccbluex.liquidbounce.utils.aiming.Rotation +import net.ccbluex.liquidbounce.utils.aiming.RotationManager +import net.ccbluex.liquidbounce.utils.aiming.RotationsConfigurable +import net.ccbluex.liquidbounce.utils.kotlin.Priority + +/** + * Makes you go faster by strafing 45deg + */ +object SpeedYawOffset : ToggleableConfigurable(ModuleSpeed, "YawOffset", false) { + + private val yawOffsetMode by enumChoice("YawOffsetMode", YawOffsetMode.AIR) + private val rotationsConfigurable = RotationsConfigurable(this) + + private var yaw = 0f + + @Suppress("unused") + private val yawOffsetHandler = handler { + when (yawOffsetMode) { + YawOffsetMode.GROUND -> groundYawOffset() // makes you strafe more on ground + YawOffsetMode.AIR -> airYawOffset() // 45deg strafe on air + YawOffsetMode.NONE -> return@handler + } + + val rotation = Rotation(player.yaw - yaw, player.pitch) + + RotationManager.aimAt( + rotationsConfigurable.toAimPlan(rotation), Priority.NOT_IMPORTANT, + ModuleSpeed + ) + } + + private fun groundYawOffset(): Float { + yaw = if (player.isOnGround) { + when { + mc.options.forwardKey.isPressed && mc.options.leftKey.isPressed -> 45f + mc.options.forwardKey.isPressed && mc.options.rightKey.isPressed -> -45f + mc.options.backKey.isPressed && mc.options.leftKey.isPressed -> 135f + mc.options.backKey.isPressed && mc.options.rightKey.isPressed -> -135f + mc.options.backKey.isPressed -> 180f + mc.options.leftKey.isPressed -> 90f + mc.options.rightKey.isPressed -> -90f + else -> 0f + } + } else { + 0f + } + return 0f + } + + private fun airYawOffset(): Float { + yaw = when { + !player.isOnGround && + mc.options.forwardKey.isPressed && + !mc.options.leftKey.isPressed && + !mc.options.rightKey.isPressed + -> -45f + + else -> 0f + } + return 0f + } + + private enum class YawOffsetMode(override val choiceName: String) : NamedChoice { + GROUND("Ground"), + AIR("Air"), + NONE("None") + } + +} diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/SpeedCustom.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/SpeedCustom.kt index d6608428736..1853556b55c 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/SpeedCustom.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/SpeedCustom.kt @@ -18,20 +18,16 @@ */ package net.ccbluex.liquidbounce.features.module.modules.movement.speed.modes -import net.ccbluex.liquidbounce.config.types.Choice import net.ccbluex.liquidbounce.config.types.ChoiceConfigurable import net.ccbluex.liquidbounce.config.types.ToggleableConfigurable import net.ccbluex.liquidbounce.event.EventListener -import net.ccbluex.liquidbounce.event.events.MovementInputEvent import net.ccbluex.liquidbounce.event.events.PacketEvent import net.ccbluex.liquidbounce.event.events.PlayerAfterJumpEvent import net.ccbluex.liquidbounce.event.events.PlayerJumpEvent import net.ccbluex.liquidbounce.event.handler import net.ccbluex.liquidbounce.event.sequenceHandler import net.ccbluex.liquidbounce.event.tickHandler -import net.ccbluex.liquidbounce.features.module.modules.combat.criticals.modes.CriticalsJump import net.ccbluex.liquidbounce.features.module.modules.movement.speed.ModuleSpeed -import net.ccbluex.liquidbounce.features.module.modules.movement.speed.SpeedAntiCornerBump import net.ccbluex.liquidbounce.utils.client.Timer import net.ccbluex.liquidbounce.utils.entity.moving import net.ccbluex.liquidbounce.utils.entity.sqrtSpeed @@ -54,7 +50,7 @@ import net.minecraft.network.packet.s2c.play.EntityVelocityUpdateS2CPacket * - Avoid edge bump * */ -class SpeedCustom(override val parent: ChoiceConfigurable<*>) : Choice("Custom") { +class SpeedCustom(override val parent: ChoiceConfigurable<*>) : SpeedBHopBase("Custom", parent) { private class HorizontalModification(parent: EventListener?) : ToggleableConfigurable(parent, "HorizontalModification", true) { @@ -67,7 +63,8 @@ class SpeedCustom(override val parent: ChoiceConfigurable<*>) : Choice("Custom") */ private val ticksToBoostOff by int("TicksToBoostOff", 0, 0..20, "ticks") - val repeatable = tickHandler { + @Suppress("unused") + private val tickHandler = tickHandler { if (!player.moving) { return@tickHandler } @@ -78,7 +75,8 @@ class SpeedCustom(override val parent: ChoiceConfigurable<*>) : Choice("Custom") } } - val onJump = sequenceHandler { + @Suppress("unused") + private val jumpHandler = sequenceHandler { if (horizontalJumpOffModifier != 0f) { waitTicks(ticksToBoostOff) @@ -97,7 +95,8 @@ class SpeedCustom(override val parent: ChoiceConfigurable<*>) : Choice("Custom") private val pullDown by float("Pulldown", 0f, 0f..1f) private val pullDownDuringFall by float("PullDownDuringFall", 0f, 0f..1f) - val repeatable = tickHandler { + @Suppress("unused") + private val tickHandler = tickHandler { if (!player.moving) { return@tickHandler } @@ -106,9 +105,10 @@ class SpeedCustom(override val parent: ChoiceConfigurable<*>) : Choice("Custom") player.velocity.y -= pullDown } - val onJump = handler { + @Suppress("unused") + private val jumpHandler = handler { event -> if (jumpHeight != 0.42f) { - it.motion = jumpHeight + event.motion = jumpHeight } } @@ -143,7 +143,8 @@ class SpeedCustom(override val parent: ChoiceConfigurable<*>) : Choice("Custom") } } - val packetHandler = sequenceHandler { + @Suppress("unused") + private val packetHandler = sequenceHandler { val packet = it.packet if (packet is EntityVelocityUpdateS2CPacket && packet.entityId == player.id) { @@ -176,9 +177,6 @@ class SpeedCustom(override val parent: ChoiceConfigurable<*>) : Choice("Custom") private val timerSpeed by float("TimerSpeed", 1f, 0.1f..10f) - private val optimizeForCriticals by boolean("OptimizeForCriticals", true) - private val avoidEdgeBump by boolean("AvoidEdgeBump", true) - init { tree(Strafe(this)) } @@ -194,25 +192,4 @@ class SpeedCustom(override val parent: ChoiceConfigurable<*>) : Choice("Custom") } } - @Suppress("unused") - private val handleJump = handler { - if (!player.moving || doOptimizationsPreventJump()) { - return@handler - } - - it.jumping = true - } - - private fun doOptimizationsPreventJump(): Boolean { - if (optimizeForCriticals && CriticalsJump.shouldWaitForJump(0.42f)) { - return true - } - - if (avoidEdgeBump && SpeedAntiCornerBump.shouldDelayJump()) { - return true - } - - return false - } - } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/SpeedGeneric.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/SpeedGeneric.kt index e70117eb128..40cf37b3911 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/SpeedGeneric.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/SpeedGeneric.kt @@ -23,7 +23,7 @@ import net.ccbluex.liquidbounce.config.types.ChoiceConfigurable import net.ccbluex.liquidbounce.event.events.MovementInputEvent import net.ccbluex.liquidbounce.event.handler import net.ccbluex.liquidbounce.event.tickHandler -import net.ccbluex.liquidbounce.features.module.modules.movement.speed.ModuleSpeed +import net.ccbluex.liquidbounce.features.module.modules.movement.speed.ModuleSpeed.doOptimizationsPreventJump import net.ccbluex.liquidbounce.utils.entity.downwards import net.ccbluex.liquidbounce.utils.entity.moving import net.ccbluex.liquidbounce.utils.entity.strafe @@ -47,16 +47,16 @@ class SpeedLegitHop(override val parent: ChoiceConfigurable<*>) : SpeedBHopBase( open class SpeedBHopBase(name: String, override val parent: ChoiceConfigurable<*>) : Choice(name) { @Suppress("unused") - val handleMovementInput = handler { - if (!player.isOnGround || !player.moving) { + private val handleMovementInput = handler { event -> + if (!player.isOnGround || !event.directionalInput.isMoving) { return@handler } - // We want the player to be able to jump if he wants to - if (!mc.options.jumpKey.isPressed && ModuleSpeed.shouldDelayJump()) + if (doOptimizationsPreventJump()) { return@handler + } - it.jumping = true + event.jumping = true } } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/blocksmc/SpeedBlocksMC.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/blocksmc/SpeedBlocksMC.kt index 9d2ca400f60..f3fcd044fe3 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/blocksmc/SpeedBlocksMC.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/blocksmc/SpeedBlocksMC.kt @@ -65,8 +65,8 @@ class SpeedBlocksMC(override val parent: ChoiceConfigurable<*>) : Choice("Blocks player.strafe(speed = 0.0) } - val repeatable = tickHandler { - + @Suppress("unused") + private val tickHandler = tickHandler { if (player.isOnGround) { airTicks = 0 canSpeed = true @@ -133,7 +133,8 @@ class SpeedBlocksMC(override val parent: ChoiceConfigurable<*>) : Choice("Blocks } - val jumpEvent = handler { + @Suppress("unused") + private val jumpHandler = handler { val atLeast = 0.281 + 0.2 * (player.getStatusEffect(StatusEffects.SPEED)?.amplifier ?: 0) if (!canSpeed) { return@handler @@ -146,9 +147,10 @@ class SpeedBlocksMC(override val parent: ChoiceConfigurable<*>) : Choice("Blocks player.strafe(speed = player.sqrtSpeed.coerceAtLeast(atLeast) - 0.01) } - val movementInputEvent = handler { - if (player.moving) { - it.jumping = true + @Suppress("unused") + private val movementInputHandler = handler { event -> + if (event.directionalInput.isMoving) { + event.jumping = true } } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/grim/SpeedGrimCollide.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/grim/SpeedGrimCollide.kt index 4201af03047..32607ab4f4e 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/grim/SpeedGrimCollide.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/grim/SpeedGrimCollide.kt @@ -24,7 +24,8 @@ class SpeedGrimCollide(override val parent: ChoiceConfigurable<*>) : Choice("Gri * * This only works on client version being 1.9+. */ - val tickHandler = handler { + @Suppress("unused") + private val tickHandler = handler { if (player.input.movementForward == 0.0f && player.input.movementSideways == 0.0f) { return@handler } var collisions = 0 val box = player.boundingBox.expand(1.0) diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/hylex/SpeedHylexGround.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/hylex/SpeedHylexGround.kt index 220a872ae26..14b9bdb39bd 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/hylex/SpeedHylexGround.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/hylex/SpeedHylexGround.kt @@ -38,7 +38,8 @@ class SpeedHylexGround(override val parent: ChoiceConfigurable<*>) : Choice("Hyl super.enable() } - val repeatable = tickHandler { + @Suppress("unused") + private val tickHandler = tickHandler { if (!player.isOnGround) { groundTicks = 0 return@tickHandler diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/hylex/SpeedHylexLowHop.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/hylex/SpeedHylexLowHop.kt index 70312f0760b..5fe065d56d1 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/hylex/SpeedHylexLowHop.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/hylex/SpeedHylexLowHop.kt @@ -34,8 +34,10 @@ import net.ccbluex.liquidbounce.utils.entity.sqrtSpeed */ class SpeedHylexLowHop(override val parent: ChoiceConfigurable<*>) : SpeedBHopBase("HylexLowHop", parent) { - var airTicks = 0 - val repeatable = tickHandler { + private var airTicks = 0 + + @Suppress("unused") + private val tickHandler = tickHandler { if (player.isOnGround) { airTicks = 0 if (player.moving && player.sqrtSpeed < 0.32) { @@ -82,8 +84,8 @@ class SpeedHylexLowHop(override val parent: ChoiceConfigurable<*>) : SpeedBHopBa } @Suppress("unused") - private val jumpHandler = handler { - it.motion = 0.33f + private val jumpHandler = handler { event -> + event.motion = 0.33f } } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/intave/SpeedIntave14.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/intave/SpeedIntave14.kt index 1a0e3cdc969..62e726c75b1 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/intave/SpeedIntave14.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/intave/SpeedIntave14.kt @@ -20,22 +20,15 @@ package net.ccbluex.liquidbounce.features.module.modules.movement.speed.modes.intave import net.ccbluex.liquidbounce.config.types.ChoiceConfigurable -import net.ccbluex.liquidbounce.config.types.NamedChoice import net.ccbluex.liquidbounce.config.types.ToggleableConfigurable import net.ccbluex.liquidbounce.event.EventListener -import net.ccbluex.liquidbounce.event.events.GameTickEvent import net.ccbluex.liquidbounce.event.events.PlayerJumpEvent import net.ccbluex.liquidbounce.event.events.PlayerMoveEvent import net.ccbluex.liquidbounce.event.handler import net.ccbluex.liquidbounce.event.tickHandler -import net.ccbluex.liquidbounce.features.module.modules.movement.speed.ModuleSpeed import net.ccbluex.liquidbounce.features.module.modules.movement.speed.modes.SpeedBHopBase -import net.ccbluex.liquidbounce.utils.aiming.Rotation -import net.ccbluex.liquidbounce.utils.aiming.RotationManager -import net.ccbluex.liquidbounce.utils.aiming.RotationsConfigurable import net.ccbluex.liquidbounce.utils.entity.directionYaw import net.ccbluex.liquidbounce.utils.entity.strafe -import net.ccbluex.liquidbounce.utils.kotlin.Priority import net.minecraft.entity.MovementType /** @@ -45,7 +38,6 @@ import net.minecraft.entity.MovementType */ class SpeedIntave14(override val parent: ChoiceConfigurable<*>) : SpeedBHopBase("Intave14", parent) { - private val yawOffsetMode by enumChoice("YawOffsetMode", YawOffsetMode.AIR) companion object { private const val BOOST_CONSTANT = 0.003 @@ -92,8 +84,6 @@ class SpeedIntave14(override val parent: ChoiceConfigurable<*>) : SpeedBHopBase( */ private val lowHop by boolean("LowHop", true) - private val rotationsConfigurable = RotationsConfigurable(this) - @Suppress("unused") private val jumpHandler = handler { event -> if (lowHop) { @@ -101,58 +91,4 @@ class SpeedIntave14(override val parent: ChoiceConfigurable<*>) : SpeedBHopBase( } } - private var yaw = 0f - - @Suppress("unused") - private val yawOffsetHandler = handler { - when (yawOffsetMode) { - YawOffsetMode.GROUND -> groundYawOffset() // makes you strafe more on ground - YawOffsetMode.AIR -> airYawOffset() // 45deg strafe on air - YawOffsetMode.NONE -> return@handler - } - - val rotation = Rotation(player.yaw - yaw, player.pitch) - - RotationManager.aimAt( - rotationsConfigurable.toAimPlan(rotation), Priority.NOT_IMPORTANT, - ModuleSpeed - ) - } - - private fun groundYawOffset(): Float { - yaw = if (player.isOnGround) { - when { - mc.options.forwardKey.isPressed && mc.options.leftKey.isPressed -> 45f - mc.options.forwardKey.isPressed && mc.options.rightKey.isPressed -> -45f - mc.options.backKey.isPressed && mc.options.leftKey.isPressed -> 135f - mc.options.backKey.isPressed && mc.options.rightKey.isPressed -> -135f - mc.options.backKey.isPressed -> 180f - mc.options.leftKey.isPressed -> 90f - mc.options.rightKey.isPressed -> -90f - else -> 0f - } - } else { - 0f - } - return 0f - } - - private fun airYawOffset(): Float { - yaw = when { - !player.isOnGround && - mc.options.forwardKey.isPressed && - !mc.options.leftKey.isPressed && - !mc.options.rightKey.isPressed - -> -45f - - else -> 0f - } - return 0f - } - - private enum class YawOffsetMode(override val choiceName: String) : NamedChoice { - GROUND("Ground"), - AIR("Air"), - NONE("None") - } } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/ncp/SpeedNCP.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/ncp/SpeedNCP.kt index 55b72b3c431..88671c5fb0c 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/ncp/SpeedNCP.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/ncp/SpeedNCP.kt @@ -51,7 +51,7 @@ class SpeedNCP(override val parent: ChoiceConfigurable<*>) : SpeedBHopBase("NCP" private var ticksInAir = 0 @Suppress("unused") - private val repeatable = tickHandler { + private val tickHandler = tickHandler { if (player.isOnGround) { ticksInAir = 0 return@tickHandler @@ -74,10 +74,11 @@ class SpeedNCP(override val parent: ChoiceConfigurable<*>) : SpeedBHopBase("NCP" } private inner class Boost(parent: EventListener?) : ToggleableConfigurable(parent, "Boost", true) { - private val initialBoostMultiplier by float("InitialBoostMultiplier", 1f, 0.01f..10f) + private val initialBoostMultiplier by float("InitialBoostMultiplier", 1f, + 0.01f..10f) @Suppress("unused") - val repeatable = tickHandler { + private val tickHandler = tickHandler { if (player.moving) { player.velocity.x *= 1f + (BOOST_CONSTANT * initialBoostMultiplier.toDouble()) player.velocity.z *= 1f + (BOOST_CONSTANT * initialBoostMultiplier.toDouble()) @@ -102,7 +103,7 @@ class SpeedNCP(override val parent: ChoiceConfigurable<*>) : SpeedBHopBase("NCP" } @Suppress("unused") - private val repeatable = tickHandler { + private val tickHandler = tickHandler { val speedMultiplier = player.getStatusEffect(StatusEffects.SPEED)?.amplifier ?: 0 if (player.moving) { @@ -126,9 +127,9 @@ class SpeedNCP(override val parent: ChoiceConfigurable<*>) : SpeedBHopBase("NCP" } @Suppress("unused") - private val jumpHandler = handler { + private val jumpHandler = handler { event -> if (shouldLowHop) { - it.motion = 0.4f + event.motion = 0.4f } } } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/sentinel/SpeedSentinelDamage.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/sentinel/SpeedSentinelDamage.kt index e00f6cc2592..72c3251752e 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/sentinel/SpeedSentinelDamage.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/sentinel/SpeedSentinelDamage.kt @@ -112,9 +112,9 @@ class SpeedSentinelDamage(override val parent: ChoiceConfigurable<*>) : Choice(" } @Suppress("unused") - private val movementInputHandler = handler { - if (player.moving && hasBeenHurt) { - it.jumping = true + private val movementInputHandler = handler { event -> + if (event.directionalInput.isMoving && hasBeenHurt) { + event.jumping = true } } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/spartan/SpeedSpartan524.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/spartan/SpeedSpartan524.kt index c50970c9233..d9249a6f8a5 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/spartan/SpeedSpartan524.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/spartan/SpeedSpartan524.kt @@ -42,7 +42,8 @@ import net.ccbluex.liquidbounce.utils.movement.zeroXZ */ class SpeedSpartan524(override val parent: ChoiceConfigurable<*>) : Choice("Spartan524") { - val repeatable = tickHandler { + @Suppress("unused") + private val tickHandler = tickHandler { if (!player.moving) { return@tickHandler } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/verus/SpeedVerusB3882.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/verus/SpeedVerusB3882.kt index 7b30868e87d..1956145c9e4 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/verus/SpeedVerusB3882.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/verus/SpeedVerusB3882.kt @@ -20,14 +20,13 @@ */ package net.ccbluex.liquidbounce.features.module.modules.movement.speed.modes.verus -import net.ccbluex.liquidbounce.config.types.Choice import net.ccbluex.liquidbounce.config.types.ChoiceConfigurable -import net.ccbluex.liquidbounce.event.events.MovementInputEvent import net.ccbluex.liquidbounce.event.events.PlayerAfterJumpEvent import net.ccbluex.liquidbounce.event.events.PlayerMoveEvent import net.ccbluex.liquidbounce.event.handler import net.ccbluex.liquidbounce.event.tickHandler import net.ccbluex.liquidbounce.features.module.modules.movement.speed.ModuleSpeed +import net.ccbluex.liquidbounce.features.module.modules.movement.speed.modes.SpeedBHopBase import net.ccbluex.liquidbounce.utils.client.Timer import net.ccbluex.liquidbounce.utils.entity.directionYaw import net.ccbluex.liquidbounce.utils.entity.moving @@ -40,20 +39,16 @@ import net.minecraft.entity.MovementType * @anticheatVersion b3882 * @testedOn eu.anticheat-test.com */ -class SpeedVerusB3882(override val parent: ChoiceConfigurable<*>) : Choice("VerusB3882") { +class SpeedVerusB3882(override val parent: ChoiceConfigurable<*>) : SpeedBHopBase("VerusB3882", parent) { - val movementInputEvent = handler { - if (player.moving) { - it.jumping = true - } - } - - val afterJumpEvent = handler { + @Suppress("unused") + private val afterJumpHandler = handler { player.velocity.x *= 1.1 player.velocity.z *= 1.1 } - val moveHandler = handler { event -> + @Suppress("unused") + private val moveHandler = handler { event -> // Might just strafe when player controls itself if (event.type == MovementType.SELF && player.moving) { val movement = event.movement @@ -61,8 +56,10 @@ class SpeedVerusB3882(override val parent: ChoiceConfigurable<*>) : Choice("Veru } } - val timerRepeatable = tickHandler { + @Suppress("unused") + private val timerHandler = tickHandler { Timer.requestTimerSpeed(2.0F, Priority.IMPORTANT_FOR_USAGE_1, ModuleSpeed) waitTicks(101) } + } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/vulcan/SpeedVulcan286.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/vulcan/SpeedVulcan286.kt index 065e418afdf..e17d92c4be0 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/vulcan/SpeedVulcan286.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/vulcan/SpeedVulcan286.kt @@ -39,7 +39,8 @@ class SpeedVulcan286(override val parent: ChoiceConfigurable<*>) : SpeedBHopBase private inline val goingSideways: Boolean get() = player.input.movementSideways != 0f - val afterJumpEvent = sequenceHandler { + @Suppress("unused") + private val afterJumpHandler = sequenceHandler { // We might lose the effect during runtime of the sequence, // but we don't care, since it is Vulcan. val speedLevel = (player.getStatusEffect(StatusEffects.SPEED)?.amplifier ?: 0) diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/vulcan/SpeedVulcan288.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/vulcan/SpeedVulcan288.kt index 50f1132f6ea..c2164d12b2f 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/vulcan/SpeedVulcan288.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/vulcan/SpeedVulcan288.kt @@ -38,7 +38,9 @@ import kotlin.math.abs * Tested on both anticheat-test.com and loyisa.cn */ class SpeedVulcan288(override val parent: ChoiceConfigurable<*>) : SpeedBHopBase("Vulcan288", parent) { - val afterJumpEvent = sequenceHandler { + + @Suppress("unused") + private val afterJumpHandler = sequenceHandler { val hasSpeed = (player.getStatusEffect(StatusEffects.SPEED)?.amplifier ?: 0) != 0 player.strafe(speed = if (hasSpeed) 0.771 else 0.5) @@ -53,7 +55,9 @@ class SpeedVulcan288(override val parent: ChoiceConfigurable<*>) : SpeedBHopBase waitTicks(1) player.strafe(speed = if (hasSpeed) 0.595 else 0.28) } - val repeatable = tickHandler { + + @Suppress("unused") + private val tickHandler = tickHandler { val hasSpeed = (player.getStatusEffect(StatusEffects.SPEED)?.amplifier ?: 0) != 0 if (!player.isOnGround) { if (abs(player.fallDistance) > 0 && hasSpeed) { @@ -62,10 +66,13 @@ class SpeedVulcan288(override val parent: ChoiceConfigurable<*>) : SpeedBHopBase } } } - val packetHandler = handler { event -> + + @Suppress("unused") + private val packetHandler = handler { event -> val packet = event.packet if (packet is PlayerMoveC2SPacket && player.velocity.y < 0) { packet.onGround = true } } + } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/vulcan/SpeedVulcanGround286.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/vulcan/SpeedVulcanGround286.kt index 5050fd4a1db..7ec57a943cf 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/vulcan/SpeedVulcanGround286.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/vulcan/SpeedVulcanGround286.kt @@ -39,7 +39,8 @@ import net.minecraft.util.shape.VoxelShapes */ class SpeedVulcanGround286(override val parent: ChoiceConfigurable<*>) : SpeedBHopBase("VulcanGround286", parent) { - val repeatable = tickHandler { + @Suppress("unused") + private val afterJumpHandler = tickHandler { if (player.moving && collidesBottomVertical()) { val speedEffect = player.getStatusEffect(StatusEffects.SPEED) val isAffectedBySpeed = speedEffect != null && speedEffect.amplifier > 0 diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/watchdog/SpeedHypixelBHop.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/watchdog/SpeedHypixelBHop.kt index 7349e83a207..1d7d15114aa 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/watchdog/SpeedHypixelBHop.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/watchdog/SpeedHypixelBHop.kt @@ -20,16 +20,13 @@ */ package net.ccbluex.liquidbounce.features.module.modules.movement.speed.modes.watchdog -import net.ccbluex.liquidbounce.config.types.Choice import net.ccbluex.liquidbounce.config.types.ChoiceConfigurable -import net.ccbluex.liquidbounce.event.events.MovementInputEvent import net.ccbluex.liquidbounce.event.events.PacketEvent import net.ccbluex.liquidbounce.event.events.PlayerJumpEvent import net.ccbluex.liquidbounce.event.handler import net.ccbluex.liquidbounce.event.sequenceHandler import net.ccbluex.liquidbounce.event.tickHandler -import net.ccbluex.liquidbounce.features.module.modules.movement.speed.ModuleSpeed -import net.ccbluex.liquidbounce.utils.entity.moving +import net.ccbluex.liquidbounce.features.module.modules.movement.speed.modes.SpeedBHopBase import net.ccbluex.liquidbounce.utils.entity.sqrtSpeed import net.ccbluex.liquidbounce.utils.entity.strafe import net.ccbluex.liquidbounce.utils.kotlin.EventPriorityConvention @@ -42,7 +39,7 @@ import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket * @anticheatVersion 12.12.2023 * @testedOn hypixel.net */ -class SpeedHypixelBHop(override val parent: ChoiceConfigurable<*>) : Choice("HypixelBHop") { +class SpeedHypixelBHop(override val parent: ChoiceConfigurable<*>) : SpeedBHopBase("HypixelBHop", parent) { private val horizontalAcceleration by boolean("HorizontalAcceleration", true) private val verticalAcceleration by boolean("VerticalAcceleration", true) @@ -105,17 +102,6 @@ class SpeedHypixelBHop(override val parent: ChoiceConfigurable<*>) : Choice("Hyp player.strafe(speed = player.sqrtSpeed.coerceAtLeast(atLeast)) } - val moveHandler = handler { - if (!player.isOnGround || !player.moving) { - return@handler - } - - if (ModuleSpeed.shouldDelayJump()) - return@handler - - it.jumping = true - } - /** * Damage Boost */ diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/watchdog/SpeedHypixelLowHop.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/watchdog/SpeedHypixelLowHop.kt index d00e43e9be3..77c6f435a33 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/watchdog/SpeedHypixelLowHop.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/speed/modes/watchdog/SpeedHypixelLowHop.kt @@ -20,14 +20,11 @@ */ package net.ccbluex.liquidbounce.features.module.modules.movement.speed.modes.watchdog -import net.ccbluex.liquidbounce.config.types.Choice import net.ccbluex.liquidbounce.config.types.ChoiceConfigurable -import net.ccbluex.liquidbounce.event.events.MovementInputEvent import net.ccbluex.liquidbounce.event.events.PlayerJumpEvent import net.ccbluex.liquidbounce.event.handler import net.ccbluex.liquidbounce.event.tickHandler -import net.ccbluex.liquidbounce.features.module.modules.movement.speed.ModuleSpeed -import net.ccbluex.liquidbounce.utils.entity.moving +import net.ccbluex.liquidbounce.features.module.modules.movement.speed.modes.SpeedBHopBase import net.ccbluex.liquidbounce.utils.entity.sqrtSpeed import net.ccbluex.liquidbounce.utils.entity.strafe import net.minecraft.entity.effect.StatusEffects @@ -37,17 +34,17 @@ import net.minecraft.entity.effect.StatusEffects * @anticheatVersion 01.10.24 * @testedOn hypixel.net */ -class SpeedHypixelLowHop(override val parent: ChoiceConfigurable<*>) : Choice("HypixelLowHop") { +class SpeedHypixelLowHop(override val parent: ChoiceConfigurable<*>) : SpeedBHopBase("HypixelLowHop", parent) { companion object { var shouldStrafe = false } private var glide by boolean("Glide", true) - private var airTicks = 0 + @Suppress("unused") - val repeatable = tickHandler { + val tickHandler = tickHandler { shouldStrafe = false if (player.isOnGround) { @@ -87,24 +84,13 @@ class SpeedHypixelLowHop(override val parent: ChoiceConfigurable<*>) : Choice("H } } - val jumpEvent = handler { + @Suppress("unused") + private val jumpHandler = handler { val atLeast = 0.281 + 0.13 * (player.getStatusEffect(StatusEffects.SPEED)?.amplifier ?: 0) player.strafe(speed = player.sqrtSpeed.coerceAtLeast(atLeast)) } - val moveHandler = handler { - if (!player.isOnGround || !player.moving) { - return@handler - } - - if (ModuleSpeed.shouldDelayJump()) { - return@handler - } - - it.jumping = true - } - override fun disable() { airTicks = 0 } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/player/ModuleAutoWalk.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/player/ModuleAutoWalk.kt index 7a3889d5a48..f842d5ba724 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/player/ModuleAutoWalk.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/player/ModuleAutoWalk.kt @@ -31,8 +31,8 @@ import net.ccbluex.liquidbounce.features.module.ClientModule object ModuleAutoWalk : ClientModule("AutoWalk", Category.PLAYER) { @Suppress("unused") - val moveInputHandler = handler(priority = 1000) { - it.directionalInput = it.directionalInput.copy(forwards = true) + private val moveInputHandler = handler(priority = 1000) { event -> + event.directionalInput = event.directionalInput.copy(forwards = true) } } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/player/antivoid/ModuleAntiVoid.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/player/antivoid/ModuleAntiVoid.kt index f7ac34d6f27..5fe41583b75 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/player/antivoid/ModuleAntiVoid.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/player/antivoid/ModuleAntiVoid.kt @@ -20,6 +20,7 @@ */ package net.ccbluex.liquidbounce.features.module.modules.player.antivoid +import net.ccbluex.liquidbounce.common.ShapeFlag import net.ccbluex.liquidbounce.event.events.MovementInputEvent import net.ccbluex.liquidbounce.event.events.NotificationEvent import net.ccbluex.liquidbounce.event.handler @@ -52,7 +53,6 @@ object ModuleAntiVoid : ClientModule("AntiVoid", Category.PLAYER) { // Flags indicating if an action has been already taken or needs to be taken. var isLikelyFalling = false - var isTestingCollision = false // How many future ticks to simulate to ensure safety. private const val SAFE_TICKS_THRESHOLD = 10 @@ -73,10 +73,10 @@ object ModuleAntiVoid : ClientModule("AntiVoid", Category.PLAYER) { // Analyzes if the player might be falling into the void soon. try { - isTestingCollision = true + ShapeFlag.noShapeChange = true isLikelyFalling = isLikelyFalling(simulatedPlayer) } finally { - isTestingCollision = false + ShapeFlag.noShapeChange = false } } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/player/antivoid/mode/AntiVoidGhostBlockMode.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/player/antivoid/mode/AntiVoidGhostBlockMode.kt index 9dd91d74251..3edd561ee0b 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/player/antivoid/mode/AntiVoidGhostBlockMode.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/player/antivoid/mode/AntiVoidGhostBlockMode.kt @@ -25,7 +25,6 @@ import net.ccbluex.liquidbounce.event.events.BlockShapeEvent import net.ccbluex.liquidbounce.event.handler import net.ccbluex.liquidbounce.features.module.modules.player.antivoid.ModuleAntiVoid import net.ccbluex.liquidbounce.features.module.modules.player.antivoid.ModuleAntiVoid.isLikelyFalling -import net.ccbluex.liquidbounce.features.module.modules.player.antivoid.ModuleAntiVoid.isTestingCollision import net.minecraft.util.shape.VoxelShapes object AntiVoidGhostBlockMode : AntiVoidMode("GhostBlock") { @@ -35,7 +34,7 @@ object AntiVoidGhostBlockMode : AntiVoidMode("GhostBlock") { @Suppress("unused") private val handleBlockShape = handler { event -> - if (isTestingCollision || !isLikelyFalling || isExempt) { + if (!isLikelyFalling || isExempt) { return@handler } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/player/autobuff/features/Pot.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/player/autobuff/features/Pot.kt index 4c6e1452e1c..24431dfabc1 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/player/autobuff/features/Pot.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/player/autobuff/features/Pot.kt @@ -104,6 +104,7 @@ object Pot : Buff("Pot", isValidItem = { stack, forUse -> isPotion(stack, forUse private val strengthPotion by boolean("StrengthPotion", true) private val speedPotion by boolean("SpeedPotion", true) + private val fireResistancePotion by boolean("FireResistancePotion", true) private val tillGroundDistance by float("TillGroundDistance", 2f, 1f..5f) private val doNotBenefitOthers by boolean("DoNotBenefitOthers", true) @@ -190,6 +191,8 @@ object Pot : Buff("Pot", isValidItem = { stack, forUse -> isPotion(stack, forUse && !player.hasStatusEffect(StatusEffects.REGENERATION) StatusEffects.STRENGTH -> strengthPotion && !player.hasStatusEffect(StatusEffects.STRENGTH) StatusEffects.SPEED -> speedPotion && !player.hasStatusEffect(StatusEffects.SPEED) + StatusEffects.FIRE_RESISTANCE -> fireResistancePotion && + !player.hasStatusEffect(StatusEffects.FIRE_RESISTANCE) else -> false } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/ModuleCombineMobs.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/ModuleCombineMobs.kt index e9424077367..03f88fcab79 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/ModuleCombineMobs.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/ModuleCombineMobs.kt @@ -18,6 +18,7 @@ */ package net.ccbluex.liquidbounce.features.module.modules.render +import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap import net.ccbluex.liquidbounce.event.events.GameRenderEvent import net.ccbluex.liquidbounce.event.handler import net.ccbluex.liquidbounce.features.module.Category @@ -25,7 +26,6 @@ import net.ccbluex.liquidbounce.features.module.ClientModule import net.minecraft.entity.Entity import net.minecraft.entity.EntityType import net.minecraft.entity.mob.MobEntity -import net.minecraft.util.math.BlockPos /** * Combine Mobs @@ -39,7 +39,10 @@ import net.minecraft.util.math.BlockPos */ object ModuleCombineMobs : ClientModule("CombineMobs", Category.RENDER) { - private val trackedEntitySinceRender = mutableMapOf, MutableList>() + /** + * Key: type Value: position->count + */ + private val trackedEntitySinceRender = hashMapOf, Long2IntOpenHashMap>() /** * As soon we disable the module, we want to clear the tracked entities @@ -57,20 +60,19 @@ object ModuleCombineMobs : ClientModule("CombineMobs", Category.RENDER) { } fun trackEntity(entity: Entity): Boolean { - val entityType = entity.type - if (entity !is MobEntity) { return false } - val pos = entity.blockPos + val entityType = entity.type + + val pos = entity.blockPos.asLong() - val trackedEntities = trackedEntitySinceRender.getOrPut(entityType) { mutableListOf() } - val countOf = trackedEntities.count { it == pos } - trackedEntities += pos - trackedEntitySinceRender[entityType] = trackedEntities + val trackedEntities = trackedEntitySinceRender.getOrPut(entityType, ::Long2IntOpenHashMap) + val count = trackedEntities.getOrDefault(pos, 0) + trackedEntities.put(pos, count + 1) - return countOf > 0 + return count > 0 } } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/ModuleHoleESP.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/ModuleHoleESP.kt index 01f6689c784..a5e98f65046 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/ModuleHoleESP.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/ModuleHoleESP.kt @@ -18,47 +18,31 @@ */ package net.ccbluex.liquidbounce.features.module.modules.render -import it.unimi.dsi.fastutil.longs.Long2ByteMap -import it.unimi.dsi.fastutil.longs.Long2ByteOpenHashMap import net.ccbluex.liquidbounce.config.types.Choice import net.ccbluex.liquidbounce.config.types.ChoiceConfigurable -import net.ccbluex.liquidbounce.event.events.PlayerPostTickEvent import net.ccbluex.liquidbounce.event.events.WorldRenderEvent import net.ccbluex.liquidbounce.event.handler import net.ccbluex.liquidbounce.features.module.Category import net.ccbluex.liquidbounce.features.module.ClientModule import net.ccbluex.liquidbounce.render.* import net.ccbluex.liquidbounce.render.engine.Color4b -import net.ccbluex.liquidbounce.utils.block.ChunkScanner -import net.ccbluex.liquidbounce.utils.block.MovableRegionScanner -import net.ccbluex.liquidbounce.utils.block.Region import net.ccbluex.liquidbounce.utils.block.Region.Companion.getBox -import net.ccbluex.liquidbounce.utils.kotlin.getValue -import net.ccbluex.liquidbounce.utils.kotlin.isEmpty +import net.ccbluex.liquidbounce.utils.block.hole.Hole +import net.ccbluex.liquidbounce.utils.block.hole.HoleManager +import net.ccbluex.liquidbounce.utils.block.hole.HoleManagerSubscriber +import net.ccbluex.liquidbounce.utils.block.hole.HoleTracker import net.ccbluex.liquidbounce.utils.math.toVec3d -import net.minecraft.block.Block -import net.minecraft.block.BlockState -import net.minecraft.registry.Registries import net.minecraft.util.math.BlockPos import net.minecraft.util.math.Direction import net.minecraft.util.math.Vec3d -import net.minecraft.world.chunk.Chunk -import java.util.concurrent.ConcurrentSkipListSet +import kotlin.math.abs import kotlin.math.max -private const val UNBREAKABLE = (-1).toByte() -private const val AIR = 0.toByte() -private const val BREAKABLE = 1.toByte() - -// BlockState types -typealias State = Byte - /** * HoleESP module * * Detects and displays safe spots for Crystal PvP. */ - object ModuleHoleESP : ClientModule("HoleESP", Category.RENDER) { private val modes = choices("Mode", GlowingPlane, arrayOf(BoxChoice, GlowingPlane)) @@ -72,20 +56,12 @@ object ModuleHoleESP : ClientModule("HoleESP", Category.RENDER) { private val color1by2 by color("1x2", Color4b(0x35bacc)) private val color2by2 by color("2x2", Color4b(0xf7381b)) - private val movableRegionScanner = MovableRegionScanner() - - private val UNBREAKABLE_BLOCKS: Set by lazy { - Registries.BLOCK.filterTo(hashSetOf()) { it.blastResistance >= 600 } + override fun enable() { + HoleManager.subscribe(this, HoleManagerSubscriber({ horizontalDistance }, { verticalDistance })) } override fun disable() { - ChunkScanner.unsubscribe(HoleTracker) - movableRegionScanner.clearRegion() - } - - override fun enable() { - ChunkScanner.subscribe(HoleTracker) - mc.player?.blockPos?.let(::updateScanRegion) + HoleManager.unsubscribe(this) } private object BoxChoice : Choice("Box") { @@ -97,14 +73,23 @@ object ModuleHoleESP : ClientModule("HoleESP", Category.RENDER) { @Suppress("unused") val renderHandler = handler { event -> + val pos = player.blockPos + val vDistance = verticalDistance + val hDistance = horizontalDistance + renderEnvironmentForWorld(event.matrixStack) { HoleTracker.holes.forEach { val (type, positions) = it - val fade = calculateFade(positions.from) + val valOutOfRange = abs(pos.y - positions.from.y) > vDistance + val xzOutOfRange = abs(pos.x - positions.from.x) > hDistance || + abs(pos.z - positions.from.z) > hDistance + if (valOutOfRange || xzOutOfRange) { + return@forEach + } + val fade = calculateFade(positions.from) val baseColor = type.color().alpha(50).fade(fade) - val box = positions.getBox() withPositionRelativeToCamera(positions.from.toVec3d()) { withColor(baseColor) { @@ -135,17 +120,25 @@ object ModuleHoleESP : ClientModule("HoleESP", Category.RENDER) { @Suppress("unused") val renderHandler = handler { event -> val glowHeight = glowHeightSetting.toDouble() + val pos = player.blockPos + val vDistance = verticalDistance + val hDistance = horizontalDistance renderEnvironmentForWorld(event.matrixStack) { withDisabledCull { HoleTracker.holes.forEach { val (type, positions) = it - val fade = calculateFade(positions.from) + val valOutOfRange = abs(pos.y - positions.from.y) > vDistance + val xzOutOfRange = abs(pos.x - positions.from.x) > hDistance || + abs(pos.z - positions.from.z) > hDistance + if (valOutOfRange || xzOutOfRange) { + return@forEach + } + val fade = calculateFade(positions.from) val baseColor = type.color().alpha(50).fade(fade) val transparentColor = baseColor.alpha(0) - val box = positions.getBox() withPositionRelativeToCamera(positions.from.toVec3d()) { withColor(baseColor) { @@ -167,42 +160,11 @@ object ModuleHoleESP : ClientModule("HoleESP", Category.RENDER) { } } - private val playerPos = BlockPos.Mutable() - - @Suppress("unused") - val movementHandler = handler { - val currentPos = player.blockPos - - if (playerPos.getManhattanDistance(currentPos) >= 4) { - updateScanRegion(currentPos) - } - } - - private fun updateScanRegion(newPlayerPos: BlockPos) { - playerPos.set(newPlayerPos) - - val changedAreas = movableRegionScanner.moveTo( - Region.quadAround( - playerPos, - horizontalDistance, - verticalDistance - ) - ) - - if (changedAreas.isEmpty()) { - return - } - - val region = movableRegionScanner.currentRegion - - with(HoleTracker) { - // Remove blocks out of the area - holes.removeIf { !it.positions.intersects(region) } - - // Update new area - changedAreas.forEach { - it.cachedUpdate() - } + private fun Hole.Type.color(): Color4b { + return when (this) { + Hole.Type.ONE_ONE -> color1by1 + Hole.Type.ONE_TWO -> color1by2 + Hole.Type.TWO_TWO -> color2by2 } } @@ -219,191 +181,4 @@ object ModuleHoleESP : ClientModule("HoleESP", Category.RENDER) { return fade.coerceIn(0.0, 1.0).toFloat() } - @JvmRecord - private data class Hole( - val type: Type, - val positions: Region, - val blockInvalidators: Region = Region(positions.from, positions.to.up(2)), - ) : Comparable { - override fun compareTo(other: Hole): Int = - compareValuesBy(this, other) { it.positions.from } - - operator fun contains(pos: BlockPos): Boolean = pos in positions - - enum class Type(val size: Int, val color: () -> Color4b) { - ONE_ONE(1, { color1by1 }), - ONE_TWO(2, { color1by2 }), - TWO_TWO(4, { color2by2 }), - } - } - - private object HoleTracker : ChunkScanner.BlockChangeSubscriber { - val holes = ConcurrentSkipListSet() - - private val mutable by ThreadLocal.withInitial(BlockPos::Mutable) - - private val fullSurroundings = setOf(Direction.EAST, Direction.WEST, Direction.SOUTH, Direction.NORTH) - - override val shouldCallRecordBlockOnChunkUpdate: Boolean - get() = false - - override fun recordBlock(pos: BlockPos, state: BlockState, cleared: Boolean) { - // Invalidate old ones - if (state.isAir) { - // if one of the neighbor blocks becomes air, invalidate the hole - holes.removeIf { it.positions.any { p -> p.getManhattanDistance(pos) == 1 } } - } else { - holes.removeIf { pos in it.blockInvalidators } - } - - // Check new ones - val region = Region(pos.add(-2, -3, -2), pos.add(2, 3, 2)) - invalidate(region) - region.cachedUpdate() - } - - private fun invalidate(region: Region) { - holes.removeIf { it.positions.intersects(region) } - } - - @Suppress("detekt:CognitiveComplexMethod") - fun Region.cachedUpdate(chunk: Chunk? = null) { - val buffer = Long2ByteOpenHashMap(volume) - - // Only check positions in this chunk (pos is BlockPos.Mutable) - forEach { pos -> - if (chunk != null && (pos.y <= chunk.bottomY || pos.y - 1 >= chunk.topY)) { - return@forEach - } - - if (holes.any { pos in it } || !buffer.checkSameXZ(pos)) { - return@forEach - } - - val surroundings = fullSurroundings.filterTo(HashSet(4, 1.0F)) { direction -> - buffer.cache(mutable.set(pos, direction)) == UNBREAKABLE - } - - when (surroundings.size) { - // 1*1 - 4 -> holes += Hole( - Hole.Type.ONE_ONE, - Region.from(pos), - ) - // 1*2 - 3 -> { - val airDirection = fullSurroundings.first { it !in surroundings } - val another = pos.offset(airDirection) - - if (!buffer.checkSameXZ(another)) { - return@forEach - } - - val airOpposite = airDirection.opposite - val checkDirections = with(fullSurroundings.iterator()) { - Array(3) { - val value = next() - if (value == airOpposite) next() else value - } - } - - if (buffer.checkSurroundings(another, checkDirections)) { - holes += Hole( - Hole.Type.ONE_TWO, - Region(pos, another), - ) - } - } - // 2*2 - 2 -> { - val (direction1, direction2) = fullSurroundings.filterTo(ArrayList(2)) { it !in surroundings } - - val mutableLocal = BlockPos.Mutable() - - if (!buffer.checkState(mutableLocal.set(pos, direction1), direction1, direction2.opposite)) { - return@forEach - } - - if (!buffer.checkState(mutableLocal.set(pos, direction2), direction2, direction1.opposite)) { - return@forEach - } - - if (!buffer.checkState(mutableLocal.move(direction1), direction1, direction2)) { - return@forEach - } - - holes += Hole( - Hole.Type.TWO_TWO, - Region(pos, mutableLocal), - ) - } - } - } - } - - private fun Long2ByteMap.cache(blockPos: BlockPos): State { - val longValue = blockPos.asLong() - if (containsKey(longValue)) { - return get(longValue) - } else { - val state = mc.world?.getBlockState(blockPos) ?: return AIR - val result = when { - state.isAir -> AIR - state.block in UNBREAKABLE_BLOCKS -> UNBREAKABLE - else -> BREAKABLE - } - put(longValue, result) - return result - } - } - - private fun Long2ByteMap.checkSameXZ(blockPos: BlockPos): Boolean { - mutable.set(blockPos.x, blockPos.y - 1, blockPos.z) - if (cache(mutable) != UNBREAKABLE) { - return false - } - - repeat(3) { - mutable.y++ - if (cache(mutable) != AIR) { - return false - } - } - - return true - } - - private fun Long2ByteMap.checkSurroundings( - blockPos: BlockPos, - directions: Array - ): Boolean { - return directions.all { cache(mutable.set(blockPos, it)) == UNBREAKABLE } - } - - private fun Long2ByteMap.checkState( - blockPos: BlockPos, - vararg directions: Direction - ): Boolean { - return checkSameXZ(blockPos) && checkSurroundings(blockPos, directions) - } - - override fun chunkUpdate(x: Int, z: Int) { - val chunk = mc.world?.getChunk(x, z) ?: return - val region = Region.from(chunk) - if (region.intersects(movableRegionScanner.currentRegion)) { - invalidate(region) - region.cachedUpdate(chunk) - } - } - - override fun clearChunk(x: Int, z: Int) { - invalidate(Region.fromChunkPos(x, z)) - } - - override fun clearAllChunks() { - holes.clear() - } - - } - } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/ModuleProphuntESP.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/ModuleProphuntESP.kt index 1a94d9fa627..fd23a49ddcc 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/ModuleProphuntESP.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/ModuleProphuntESP.kt @@ -1,250 +1,47 @@ package net.ccbluex.liquidbounce.features.module.modules.render -import net.ccbluex.liquidbounce.config.types.Choice -import net.ccbluex.liquidbounce.config.types.ChoiceConfigurable -import net.ccbluex.liquidbounce.event.events.DrawOutlinesEvent import net.ccbluex.liquidbounce.event.events.PacketEvent -import net.ccbluex.liquidbounce.event.events.WorldRenderEvent import net.ccbluex.liquidbounce.event.handler import net.ccbluex.liquidbounce.event.tickHandler import net.ccbluex.liquidbounce.features.module.Category import net.ccbluex.liquidbounce.features.module.ClientModule -import net.ccbluex.liquidbounce.render.* import net.ccbluex.liquidbounce.render.engine.Color4b -import net.ccbluex.liquidbounce.render.utils.interpolateHue -import net.ccbluex.liquidbounce.utils.block.getState -import net.ccbluex.liquidbounce.utils.block.toBlockPos -import net.ccbluex.liquidbounce.utils.entity.interpolateCurrentPosition -import net.ccbluex.liquidbounce.utils.math.toBlockPos -import net.minecraft.client.util.math.MatrixStack +import net.ccbluex.liquidbounce.utils.render.placement.PlacementRenderer import net.minecraft.entity.FallingBlockEntity import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket -import net.minecraft.util.math.BlockPos -import net.minecraft.util.math.Box -import net.minecraft.util.math.Vec3d -import java.util.concurrent.PriorityBlockingQueue +import net.minecraft.network.packet.s2c.play.ChunkDeltaUpdateS2CPacket object ModuleProphuntESP : ClientModule("ProphuntESP", Category.RENDER, aliases = arrayOf("BlockUpdateDetector", "FallingBlockESP")) { - private val modes = choices( - "Mode", Glow, arrayOf( - Box, Glow, Outline - ) + private val renderer = PlacementRenderer("RenderBlockUpdates", true, this, + defaultColor = Color4b(255, 179, 72, 90), keep = false ) - private val colorMode = choices("ColorMode", 0) { - arrayOf( - ExpirationColor, - GenericStaticColorMode(it, Color4b(255, 179, 72, 150)), - GenericRainbowColorMode(it) - ) + init { + tree(renderer) } - private object ExpirationColor : GenericColorMode("Expiration") { - private val freshColor by color("FreshColor", Color4b(50, 200, 50, 255)) - private val expireColor by color("ExpireColor", Color4b(200, 50, 50, 255)) - - override fun getColor(param: Any): Color4b = - if (param is TrackedBlock) { - interpolateHue(freshColor, expireColor, param.expirationProgress()) - } else { - freshColor - } - - override val parent: ChoiceConfigurable<*> - get() = modes + override fun disable() { + renderer.clearSilently() } - private val renderBlockUpdates by boolean("RenderBlockUpdates", true) - private val renderFallingBlockEntity by boolean("RenderFallingBlockEntity", true) - - @JvmRecord - private data class TrackedBlock(val pos: BlockPos, val expirationTime: Long) : Comparable { - override fun compareTo(other: TrackedBlock) = - expirationTime.compareTo(other.expirationTime) - - fun expirationProgress() = Math.clamp( - 1 - (expirationTime - (mc.world?.time ?: 0)).toFloat() / renderTicks, - 0f, - 1f - ) - } - - private val trackedBlocks = PriorityBlockingQueue() - private val renderTicks by float("RenderTicks", 60f, 0f..600f) - @Suppress("unused") - private val gameHandler = tickHandler { - while (trackedBlocks.isNotEmpty() && trackedBlocks.peek().expirationTime <= world.time) { - trackedBlocks.poll() - } - - waitTicks(1) - } - - private object Box : Choice("Box") { - override val parent: ChoiceConfigurable - get() = modes - - private val outline by boolean("Outline", true) - - @Suppress("unused") - private val renderHandler = handler { event -> - drawBoxMode(event.matrixStack, this.outline, false) - - renderEnvironmentForWorld(event.matrixStack) { - drawEntities(this, event.partialTicks, colorMode.activeChoice, true) - } - } - } - - private fun drawBoxMode(matrixStack: MatrixStack, drawOutline: Boolean, fullAlpha: Boolean): Boolean { - val colorMode = colorMode.activeChoice - - var dirty = false - - renderEnvironmentForWorld(matrixStack) { - dirty = drawBlocks(this, trackedBlocks, colorMode, fullAlpha, drawOutline) || dirty - } - - return dirty - } - - private fun WorldRenderEnvironment.drawEntities( - env: WorldRenderEnvironment, - partialTicks: Float, - colorMode: GenericColorMode, - drawOutline: Boolean - ): Boolean { - var dirty = false - - if (renderFallingBlockEntity) { - BoxRenderer.drawWith(env) { - mc.world?.entities?.filterIsInstance()?.map { - val dimension = it.getDimensions(it.pose) - val width = dimension.width.toDouble() / 2.0 - it to Box(-width, 0.0, -width, width, dimension.height.toDouble(), width) - }?.forEach { (entity, box) -> - val pos = entity.interpolateCurrentPosition(partialTicks) - val color = colorMode.getColor(entity as Any) // which doesn't matter - - val baseColor = color.alpha(50) - val outlineColor = color.alpha(100) - - withPositionRelativeToCamera(pos) { - drawBox( - box, - baseColor, - outlineColor.takeIf { drawOutline } - ) - } - - dirty = true - } - } - } - - return dirty - } - - private fun WorldRenderEnvironment.drawBlocks( - env: WorldRenderEnvironment, - blocks: Iterable, - colorMode: GenericColorMode, - fullAlpha: Boolean, - drawOutline: Boolean - ): Boolean { - var dirty = false - - BoxRenderer.drawWith(env) { - - if (renderBlockUpdates) { - for (block in blocks) { - val pos = block.pos - - val vec3d = Vec3d(pos.x.toDouble(), pos.y.toDouble(), pos.z.toDouble()) - - val blockPos = vec3d.toBlockPos().toBlockPos() - val blockState = blockPos.getState() ?: continue - - val outlineShape = blockState.getOutlineShape(world, blockPos) - val boundingBox = if (outlineShape.isEmpty) { - FULL_BOX - } else { - outlineShape.boundingBox - } - - val color = colorMode.getColor(block) - - if (fullAlpha) { - color.alpha(255) - } - - withPositionRelativeToCamera(vec3d) { - drawBox( - boundingBox, - faceColor = color, - outlineColor = color.alpha(150).takeIf { drawOutline } - ) - } - - dirty = true - } - } - } - - return dirty - } - - private object Glow : Choice("Glow") { - override val parent: ChoiceConfigurable - get() = modes - - @Suppress("unused") - private val renderHandler = handler { event -> - if (event.type != DrawOutlinesEvent.OutlineType.MINECRAFT_GLOW) { - return@handler - } - - var dirty = drawBoxMode(event.matrixStack, drawOutline = false, fullAlpha = true) - - renderEnvironmentForWorld(event.matrixStack) { - dirty = drawEntities(this, event.partialTicks, colorMode.activeChoice, true) || dirty - } - - if (dirty) { - event.markDirty() - } - } - } - - private object Outline : Choice("Outline") { - override val parent: ChoiceConfigurable - get() = modes - - @Suppress("unused") - private val renderHandler = handler { event -> - if (event.type != DrawOutlinesEvent.OutlineType.INBUILT_OUTLINE) { - return@handler - } - - var dirty = drawBoxMode(event.matrixStack, drawOutline = false, fullAlpha = true) - - renderEnvironmentForWorld(event.matrixStack) { - dirty = drawEntities(this, event.partialTicks, colorMode.activeChoice, true) || dirty - } - - if (dirty) { - event.markDirty() - } + private val tickHandler = tickHandler { + world.entities.filterIsInstance().forEach { + renderer.addBlock(it.blockPos) } } @Suppress("unused") private val networkHandler = handler { event -> - if (event.packet is BlockUpdateS2CPacket) { - trackedBlocks.offer(TrackedBlock(event.packet.pos, world.time + renderTicks.toLong())) + when (val packet = event.packet) { + is BlockUpdateS2CPacket -> mc.renderTaskQueue.add { + renderer.addBlock(packet.pos) + } + is ChunkDeltaUpdateS2CPacket -> mc.renderTaskQueue.add { + packet.visitUpdates { pos, _ -> renderer.addBlock(pos.toImmutable()) } + } } } } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/world/ModuleExtinguish.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/world/ModuleExtinguish.kt index f414bdb1f2d..64bd7cca58d 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/world/ModuleExtinguish.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/world/ModuleExtinguish.kt @@ -22,6 +22,7 @@ import net.ccbluex.liquidbounce.utils.entity.PlayerSimulationCache import net.ccbluex.liquidbounce.utils.inventory.Hotbar import net.ccbluex.liquidbounce.utils.kotlin.Priority import net.ccbluex.liquidbounce.utils.math.toBlockPos +import net.minecraft.entity.effect.StatusEffects import net.minecraft.item.Items import net.minecraft.util.math.BlockPos import net.minecraft.util.math.Vec3i @@ -70,7 +71,8 @@ object ModuleExtinguish: ClientModule("Extinguish", Category.WORLD) { if (lastExtinguishPos != null && lastAttemptTimer.hasElapsed(pickupSpanEnd)) { lastExtinguishPos = null } - if (notDuringCombat && CombatManager.isInCombat) { + + if (player.hasStatusEffect(StatusEffects.FIRE_RESISTANCE) || (notDuringCombat && CombatManager.isInCombat)) { return null } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/world/ModuleHoleFiller.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/world/ModuleHoleFiller.kt new file mode 100644 index 00000000000..e687b6c6f3d --- /dev/null +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/world/ModuleHoleFiller.kt @@ -0,0 +1,286 @@ +/* + * This file is part of LiquidBounce (https://github.com/CCBlueX/LiquidBounce) + * + * Copyright (c) 2015 - 2024 CCBlueX + * + * LiquidBounce is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LiquidBounce is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LiquidBounce. If not, see . + */ +package net.ccbluex.liquidbounce.features.module.modules.world + +import it.unimi.dsi.fastutil.booleans.BooleanDoubleImmutablePair +import it.unimi.dsi.fastutil.objects.ObjectDoubleImmutablePair +import net.ccbluex.liquidbounce.event.events.SimulatedTickEvent +import net.ccbluex.liquidbounce.event.handler +import net.ccbluex.liquidbounce.features.module.Category +import net.ccbluex.liquidbounce.features.module.ClientModule +import net.ccbluex.liquidbounce.utils.block.Region +import net.ccbluex.liquidbounce.utils.block.hole.Hole +import net.ccbluex.liquidbounce.utils.block.hole.HoleManager +import net.ccbluex.liquidbounce.utils.block.hole.HoleManagerSubscriber +import net.ccbluex.liquidbounce.utils.block.hole.HoleTracker +import net.ccbluex.liquidbounce.utils.block.placer.BlockPlacer +import net.ccbluex.liquidbounce.utils.collection.Filter +import net.ccbluex.liquidbounce.utils.collection.getSlot +import net.ccbluex.liquidbounce.utils.combat.shouldBeAttacked +import net.ccbluex.liquidbounce.utils.inventory.HOTBAR_SLOTS +import net.ccbluex.liquidbounce.utils.item.getBlock +import net.ccbluex.liquidbounce.utils.kotlin.Priority +import net.ccbluex.liquidbounce.utils.math.sq +import net.minecraft.block.Blocks +import net.minecraft.entity.Entity +import net.minecraft.util.math.BlockPos +import org.joml.Vector2d +import kotlin.math.acos +import kotlin.math.ceil +import kotlin.math.max + +/** + * Module HoleFiller + * + * Automatically fills holes. + * + * @author ccetl + */ +object ModuleHoleFiller : ClientModule("HolesFiller", Category.WORLD) { + + /** + * When enabled, only places when entities are about to enter a hole, otherwise fills all holes. + */ + private val smart by boolean("Smart", true) + + /** + * Prevents the module from filling the hole you want to enter. + * The criteria to allow filling are: + * The hole is higher than you, the hole doesn't intersect your own fill area, or you are already in a hole. + */ + private val preventSelfFill by boolean("PreventSelfFill", true) + + /** + * Only operate when you're in a hole yourself. + */ + private val onlyWhenSelfInHole by boolean("OnlyWhenSelfInHole", false) + + /** + * The area around entities' feet that will be checked for holes. + */ + private val fillArea by int("Area", 2, 1..5) + + /** + * Checks the movement angle. Won't fill holes that lie further away than 30° from the entities' velocity direction. + * Only applies when smart is enabled. + */ + private val checkMovement by boolean("CheckMovement", true) + + /** + * Only fills 1x1 holes - ignores 2x2 and 2x1 holes. + */ + private val only1by1 by boolean("Only1x1", false) + + /** + * How the blocklist is used. + */ + private val filter by enumChoice("Filter", Filter.WHITELIST) + + /** + * Blocks that are used to fill holes, by default just obsidian. + */ + private val blocks by blocks("Blocks", hashSetOf(Blocks.OBSIDIAN)) + + /** + * The core of the module, the placer. + */ + private val placer = tree(BlockPlacer( + "Placing", + this, + Priority.NORMAL, + { filter.getSlot(blocks) }, + allowSupportPlacements = false + )) + + override fun enable() { + val range = ceil(max(placer.range, placer.wallRange)).toInt() + HoleManager.subscribe(this, HoleManagerSubscriber({ range }, { range })) + } + + override fun disable() { + HoleManager.unsubscribe(this) + } + + @Suppress("unused") + private val targetUpdater = handler { + // all holes, if required 1x1 holes filtered out + val holes = HoleTracker.holes.filter { !only1by1 || it.type == Hole.Type.ONE_ONE } + + val blockPos = player.blockPos + val selfInHole = holes.any { it.contains(blockPos) } + if (onlyWhenSelfInHole && !selfInHole) { + return@handler + } + + val selfRegion = Region.quadAround(blockPos, fillArea, fillArea) + + val blocks = linkedSetOf() + val holeContext = HoleContext(holes, selfInHole, selfRegion, blocks) + + if (!smart) { + collectHolesSimple(holeContext) + } else { + val availableItems = getAvailableItemsCount() + if (availableItems == 0) { + return@handler + } + + // the range in which entities are considered as a target + val range = ceil(max(placer.range, placer.wallRange)).toInt().sq() + 10.0 + collectHolesSmart(range, holeContext, availableItems) + } + + placer.update(blocks) + } + + private fun getAvailableItemsCount(): Int { + var itemCount = 0 + HOTBAR_SLOTS.forEach { slot -> + val block = slot.itemStack.getBlock() ?: return@forEach + if (filter(block, blocks)) { + itemCount += slot.itemStack.count + } + } + + return itemCount + } + + private fun collectHolesSimple(holeContext: HoleContext) { + holeContext.holes.forEach { hole -> + val y = hole.positions.from.y + 1.0 + if (!preventSelfFill || + y > player.y || + holeContext.selfInHole || + !hole.positions.intersects(holeContext.selfRegion) + ) { + BlockPos.iterate(hole.positions.from, hole.positions.to).forEach { + holeContext.blocks += it.toImmutable() + } + } + } + } + + private fun collectHolesSmart(range: Double, holeContext: HoleContext, availableItems: Int) { + val checkedHoles = hashSetOf() + var remainingItems = availableItems + + world.entities.forEach { entity -> + if (entity.squaredDistanceTo(player) > range || entity == player || !entity.shouldBeAttacked()) { + return@forEach + } + + val found = hashSetOf>() + remainingItems = iterateHoles( + holeContext, + checkedHoles, + entity, + remainingItems, + found + ) + + holeContext.blocks += found.sortedByDescending { it.rightDouble() }.map { it.left() } + if (remainingItems <= 0) { + return + } + } + } + + private fun iterateHoles( + holeContext: HoleContext, + checkedHoles: HashSet, + entity: Entity, + remainingItems: Int, + found: HashSet> + ): Int { + var remainingItems1 = remainingItems + val region = Region.quadAround(entity.blockPos, fillArea, fillArea) + + holeContext.holes.forEach { hole -> + if (hole in checkedHoles) { + return@forEach + } + + val valid = isValidHole(hole, entity, region, holeContext.selfInHole, holeContext.selfRegion) + if (!valid.firstBoolean()) { + return@forEach + } + + val holeSize = hole.type.size + remainingItems1 -= holeSize + if (remainingItems1 < 0 && !player.abilities.creativeMode) { + remainingItems1 += holeSize + return@forEach + } + + checkedHoles += hole + BlockPos.iterate(hole.positions.from, hole.positions.to).forEach { + found += ObjectDoubleImmutablePair(it.toImmutable(), valid.rightDouble()) + } + + if (remainingItems1 == 0 && !player.abilities.creativeMode) { + return 0 + } + } + + return remainingItems + } + + private fun isValidHole( + hole: Hole, + entity: Entity, + region: Region, + selfInHole: Boolean, + selfRegion: Region + ) : BooleanDoubleImmutablePair { + val y = hole.positions.from.y + 1.0 + val movingTowardsHole = isMovingTowardsHole(hole, entity) + val requirementsMet = movingTowardsHole.firstBoolean() && hole.positions.intersects(region) && y <= entity.y + val noSelfFillViolation = !preventSelfFill || + y > player.y || + selfInHole || + !hole.positions.intersects(selfRegion) + + return BooleanDoubleImmutablePair(requirementsMet && noSelfFillViolation, movingTowardsHole.rightDouble()) + } + + private fun isMovingTowardsHole(hole: Hole, entity: Entity): BooleanDoubleImmutablePair { + val holePos = hole.positions.from.toCenterPos() + val velocity = entity.pos.subtract(entity.prevX, entity.prevY, entity.prevZ) + val playerPos = entity.pos + + val normalizedVelocity = Vector2d(velocity.x, velocity.z).normalize() + val normalizedDelta = Vector2d(holePos.x - playerPos.x, holePos.z - playerPos.z).normalize() + val angle = acos(normalizedDelta.dot(normalizedVelocity)) + + if (!checkMovement) { + return BooleanDoubleImmutablePair(true, angle) + } + + // cos(30°) = 0.866 + return BooleanDoubleImmutablePair(angle >= 0.866, angle) + } + + data class HoleContext( + val holes: List, + val selfInHole: Boolean, + val selfRegion: Region, + val blocks: MutableSet + ) + +} diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/render/RenderShortcuts.kt b/src/main/kotlin/net/ccbluex/liquidbounce/render/RenderShortcuts.kt index 14e6b56f8fd..e65b555270e 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/render/RenderShortcuts.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/render/RenderShortcuts.kt @@ -203,7 +203,7 @@ inline fun RenderEnvironment.withDisabledCull(draw: RenderEnvironment.() -> Unit */ fun RenderEnvironment.drawLines(vararg lines: Vec3) { - drawLines(*lines, mode = DrawMode.DEBUG_LINES) + drawLines(lines, mode = DrawMode.DEBUG_LINES) } /** @@ -212,11 +212,11 @@ fun RenderEnvironment.drawLines(vararg lines: Vec3) { * @param positions The vectors representing the line strip. */ fun RenderEnvironment.drawLineStrip(vararg positions: Vec3) { - drawLines(*positions, mode = DrawMode.DEBUG_LINE_STRIP) + drawLines(positions, mode = DrawMode.DEBUG_LINE_STRIP) } -@Suppress("SpreadOperator") + fun RenderEnvironment.drawLineStrip(positions: List) { - drawLines(*positions.toTypedArray(), mode = DrawMode.DEBUG_LINE_STRIP) + drawLines(positions.toTypedArray(), mode = DrawMode.DEBUG_LINE_STRIP) } /** @@ -225,7 +225,7 @@ fun RenderEnvironment.drawLineStrip(positions: List) { * @param lines The vectors representing the lines. * @param mode The draw mode for the lines. */ -private fun RenderEnvironment.drawLines(vararg lines: Vec3, mode: DrawMode = DrawMode.DEBUG_LINES) { +private fun RenderEnvironment.drawLines(lines: Array, mode: DrawMode = DrawMode.DEBUG_LINES) { // If the array of lines is empty, we don't need to draw anything if (lines.isEmpty()) { return diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/utils/block/hole/Hole.kt b/src/main/kotlin/net/ccbluex/liquidbounce/utils/block/hole/Hole.kt new file mode 100644 index 00000000000..00c575d7099 --- /dev/null +++ b/src/main/kotlin/net/ccbluex/liquidbounce/utils/block/hole/Hole.kt @@ -0,0 +1,42 @@ +/* + * This file is part of LiquidBounce (https://github.com/CCBlueX/LiquidBounce) + * + * Copyright (c) 2015 - 2024 CCBlueX + * + * LiquidBounce is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LiquidBounce is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LiquidBounce. If not, see . + */ +package net.ccbluex.liquidbounce.utils.block.hole + +import net.ccbluex.liquidbounce.utils.block.Region +import net.minecraft.util.math.BlockPos + +@JvmRecord +data class Hole( + val type: Type, + val positions: Region, + val blockInvalidators: Region = Region(positions.from, positions.to.up(2)), +) : Comparable { + + override fun compareTo(other: Hole): Int = + compareValuesBy(this, other) { it.positions.from } + + operator fun contains(pos: BlockPos): Boolean = pos in positions + + enum class Type(val size: Int) { + ONE_ONE(1), + ONE_TWO(2), + TWO_TWO(4), + } + +} diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/utils/block/hole/HoleManager.kt b/src/main/kotlin/net/ccbluex/liquidbounce/utils/block/hole/HoleManager.kt new file mode 100644 index 00000000000..58229efa980 --- /dev/null +++ b/src/main/kotlin/net/ccbluex/liquidbounce/utils/block/hole/HoleManager.kt @@ -0,0 +1,96 @@ +/* + * This file is part of LiquidBounce (https://github.com/CCBlueX/LiquidBounce) + * + * Copyright (c) 2015 - 2024 CCBlueX + * + * LiquidBounce is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LiquidBounce is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LiquidBounce. If not, see . + */ +package net.ccbluex.liquidbounce.utils.block.hole + +import net.ccbluex.liquidbounce.event.EventListener +import net.ccbluex.liquidbounce.event.events.PlayerPostTickEvent +import net.ccbluex.liquidbounce.event.handler +import net.ccbluex.liquidbounce.features.module.ClientModule +import net.ccbluex.liquidbounce.features.module.modules.render.ModuleHoleESP.mc +import net.ccbluex.liquidbounce.utils.block.ChunkScanner +import net.ccbluex.liquidbounce.utils.block.MovableRegionScanner +import net.ccbluex.liquidbounce.utils.block.Region +import net.ccbluex.liquidbounce.utils.client.player +import net.ccbluex.liquidbounce.utils.kotlin.isEmpty +import net.minecraft.util.math.BlockPos + +object HoleManager : EventListener { + + val movableRegionScanner = MovableRegionScanner() + private val activeModules = hashMapOf() + private val playerPos = BlockPos.Mutable() + + fun subscribe(module: ClientModule, subscriber: HoleManagerSubscriber) { + activeModules[module] = subscriber + if (activeModules.size == 1) { + ChunkScanner.subscribe(HoleTracker) + mc.player?.blockPos?.let(::updateScanRegion) + } + } + + fun unsubscribe(module: ClientModule) { + activeModules.remove(module) + if (activeModules.isEmpty()) { + ChunkScanner.unsubscribe(HoleTracker) + movableRegionScanner.clearRegion() + } + } + + @Suppress("unused") + private val movementHandler = handler { + val currentPos = player.blockPos + + if (playerPos.getManhattanDistance(currentPos) >= 4) { + updateScanRegion(currentPos) + } + } + + private fun updateScanRegion(newPlayerPos: BlockPos) { + playerPos.set(newPlayerPos) + + val horizontalDistance = activeModules.values.maxOf { it.horizontalDistance() } + val verticalDistance = activeModules.values.maxOf { it.verticalDistance() } + val changedAreas = movableRegionScanner.moveTo( + Region.quadAround( + playerPos, + horizontalDistance, + verticalDistance + ) + ) + + if (changedAreas.isEmpty()) { + return + } + + val region = movableRegionScanner.currentRegion + + with(HoleTracker) { + // Remove blocks out of the area + holes.removeIf { !it.positions.intersects(region) } + + // Update new area + changedAreas.forEach { + it.cachedUpdate() + } + } + } + +} + +class HoleManagerSubscriber(val horizontalDistance: () -> Int, val verticalDistance: () -> Int) diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/utils/block/hole/HoleTracker.kt b/src/main/kotlin/net/ccbluex/liquidbounce/utils/block/hole/HoleTracker.kt new file mode 100644 index 00000000000..279e24ccf57 --- /dev/null +++ b/src/main/kotlin/net/ccbluex/liquidbounce/utils/block/hole/HoleTracker.kt @@ -0,0 +1,211 @@ +/* + * This file is part of LiquidBounce (https://github.com/CCBlueX/LiquidBounce) + * + * Copyright (c) 2015 - 2024 CCBlueX + * + * LiquidBounce is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LiquidBounce is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LiquidBounce. If not, see . + */ +package net.ccbluex.liquidbounce.utils.block.hole + +import it.unimi.dsi.fastutil.longs.Long2ByteMap +import it.unimi.dsi.fastutil.longs.Long2ByteOpenHashMap +import net.ccbluex.liquidbounce.utils.block.ChunkScanner +import net.ccbluex.liquidbounce.utils.block.Region +import net.ccbluex.liquidbounce.utils.client.mc +import net.ccbluex.liquidbounce.utils.kotlin.getValue +import net.minecraft.block.Block +import net.minecraft.block.BlockState +import net.minecraft.registry.Registries +import net.minecraft.util.math.BlockPos +import net.minecraft.util.math.Direction +import net.minecraft.world.chunk.Chunk +import java.util.concurrent.ConcurrentSkipListSet + +private const val UNBREAKABLE = (-1).toByte() +private const val AIR = 0.toByte() +private const val BREAKABLE = 1.toByte() + +// BlockState types +typealias State = Byte + +object HoleTracker : ChunkScanner.BlockChangeSubscriber { + + val holes = ConcurrentSkipListSet() + private val mutable by ThreadLocal.withInitial(BlockPos::Mutable) + private val fullSurroundings = setOf(Direction.EAST, Direction.WEST, Direction.SOUTH, Direction.NORTH) + private val UNBREAKABLE_BLOCKS: Set by lazy { + Registries.BLOCK.filterTo(hashSetOf()) { it.blastResistance >= 600 } + } + + override val shouldCallRecordBlockOnChunkUpdate: Boolean + get() = false + + override fun recordBlock(pos: BlockPos, state: BlockState, cleared: Boolean) { + // Invalidate old ones + if (state.isAir) { + // if one of the neighbor blocks becomes air, invalidate the hole + holes.removeIf { it.positions.any { p -> p.getManhattanDistance(pos) == 1 } } + } else { + holes.removeIf { pos in it.blockInvalidators } + } + + // Check new ones + val region = Region(pos.add(-2, -3, -2), pos.add(2, 3, 2)) + invalidate(region) + region.cachedUpdate() + } + + private fun invalidate(region: Region) { + holes.removeIf { it.positions.intersects(region) } + } + + @Suppress("detekt:CognitiveComplexMethod") + fun Region.cachedUpdate(chunk: Chunk? = null) { + val buffer = Long2ByteOpenHashMap(volume) + + // Only check positions in this chunk (pos is BlockPos.Mutable) + forEach { pos -> + if (chunk != null && (pos.y <= chunk.bottomY || pos.y - 1 >= chunk.topY)) { + return@forEach + } + + if (holes.any { pos in it } || !buffer.checkSameXZ(pos)) { + return@forEach + } + + val surroundings = fullSurroundings.filterTo(HashSet(4, 1.0F)) { direction -> + buffer.cache(mutable.set(pos, direction)) == UNBREAKABLE + } + + when (surroundings.size) { + // 1*1 + 4 -> holes += Hole( + Hole.Type.ONE_ONE, + Region.from(pos), + ) + // 1*2 + 3 -> { + val airDirection = fullSurroundings.first { it !in surroundings } + val another = pos.offset(airDirection) + + if (!buffer.checkSameXZ(another)) { + return@forEach + } + + val airOpposite = airDirection.opposite + val checkDirections = with(fullSurroundings.iterator()) { + Array(3) { + val value = next() + if (value == airOpposite) next() else value + } + } + + if (buffer.checkSurroundings(another, checkDirections)) { + holes += Hole( + Hole.Type.ONE_TWO, + Region(pos, another), + ) + } + } + // 2*2 + 2 -> { + val (direction1, direction2) = fullSurroundings.filterTo(ArrayList(2)) { it !in surroundings } + + val mutableLocal = BlockPos.Mutable() + + if (!buffer.checkState(mutableLocal.set(pos, direction1), direction1, direction2.opposite)) { + return@forEach + } + + if (!buffer.checkState(mutableLocal.set(pos, direction2), direction2, direction1.opposite)) { + return@forEach + } + + if (!buffer.checkState(mutableLocal.move(direction1), direction1, direction2)) { + return@forEach + } + + holes += Hole( + Hole.Type.TWO_TWO, + Region(pos, mutableLocal), + ) + } + } + } + } + + private fun Long2ByteMap.cache(blockPos: BlockPos): State { + val longValue = blockPos.asLong() + if (containsKey(longValue)) { + return get(longValue) + } else { + val state = mc.world?.getBlockState(blockPos) ?: return AIR + val result = when { + state.isAir -> AIR + state.block in UNBREAKABLE_BLOCKS -> UNBREAKABLE + else -> BREAKABLE + } + put(longValue, result) + return result + } + } + + private fun Long2ByteMap.checkSameXZ(blockPos: BlockPos): Boolean { + mutable.set(blockPos.x, blockPos.y - 1, blockPos.z) + if (cache(mutable) != UNBREAKABLE) { + return false + } + + repeat(3) { + mutable.y++ + if (cache(mutable) != AIR) { + return false + } + } + + return true + } + + private fun Long2ByteMap.checkSurroundings( + blockPos: BlockPos, + directions: Array + ): Boolean { + return directions.all { cache(mutable.set(blockPos, it)) == UNBREAKABLE } + } + + private fun Long2ByteMap.checkState( + blockPos: BlockPos, + vararg directions: Direction + ): Boolean { + return checkSameXZ(blockPos) && checkSurroundings(blockPos, directions) + } + + override fun chunkUpdate(x: Int, z: Int) { + val chunk = mc.world?.getChunk(x, z) ?: return + val region = Region.from(chunk) + if (region.intersects(HoleManager.movableRegionScanner.currentRegion)) { + invalidate(region) + region.cachedUpdate(chunk) + } + } + + override fun clearChunk(x: Int, z: Int) { + invalidate(Region.fromChunkPos(x, z)) + } + + override fun clearAllChunks() { + holes.clear() + } + +} diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/utils/combat/TargetTracker.kt b/src/main/kotlin/net/ccbluex/liquidbounce/utils/combat/TargetTracker.kt index ffae7170b24..e66e6b5c717 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/utils/combat/TargetTracker.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/utils/combat/TargetTracker.kt @@ -62,7 +62,7 @@ open class TargetTracker( * Update should be called to always pick the best target out of the current world context */ fun enemies(): List { - var entities = world.entities + val entities = world.entities .asSequence() .filterIsInstance() .filter(this::validate) @@ -70,33 +70,36 @@ open class TargetTracker( .filter { it.second <= range } // Sort by distance (closest first) - in case of tie at priority level .sortedBy { it.second } - .map { it.first } - // Sort by entity type - .sortedBy { entity -> - when (entity) { - is PlayerEntity -> 0 - is HostileEntity -> 1 - else -> 2 - } + .mapTo(mutableListOf()) { it.first } + + if (entities.isEmpty()) { + return entities + } + + // Sort by entity type + entities.sortWith(Comparator.comparingInt { entity -> + when (entity) { + is PlayerEntity -> 0 + is HostileEntity -> 1 + else -> 2 } - .toList() + }) - entities = when (priority) { + when (priority) { // Lowest health first - PriorityEnum.HEALTH -> entities.sortedBy { it.getActualHealth() } + PriorityEnum.HEALTH -> entities.sortBy { it.getActualHealth() } // Closest to your crosshair first - PriorityEnum.DIRECTION -> entities.sortedBy { RotationManager.rotationDifference(it) } + PriorityEnum.DIRECTION -> entities.sortBy { RotationManager.rotationDifference(it) } // Oldest entity first - PriorityEnum.AGE -> entities.sortedBy { -it.age } + PriorityEnum.AGE -> entities.sortByDescending { it.age } // With the lowest hurt time first - PriorityEnum.HURT_TIME -> entities.sortedBy { it.hurtTime } // Sort by hurt time + PriorityEnum.HURT_TIME -> entities.sortBy { it.hurtTime } // Sort by hurt time // Closest to you first - else -> entities + else -> {} // Do nothing } // Update max distance squared - entities.minByOrNull { it.squaredBoxedDistanceTo(player) } - ?.let { maximumDistance = it.squaredBoxedDistanceTo(player) } + maximumDistance = entities.minOf { it.squaredBoxedDistanceTo(player) } return entities } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/utils/inventory/ViewedInventoryScreen.kt b/src/main/kotlin/net/ccbluex/liquidbounce/utils/inventory/ViewedInventoryScreen.kt new file mode 100644 index 00000000000..08869b4bba9 --- /dev/null +++ b/src/main/kotlin/net/ccbluex/liquidbounce/utils/inventory/ViewedInventoryScreen.kt @@ -0,0 +1,172 @@ +/* + * This file is part of LiquidBounce (https://github.com/CCBlueX/LiquidBounce) + * + * Copyright (c) 2015 - 2024 CCBlueX + * + * LiquidBounce is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LiquidBounce is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LiquidBounce. If not, see . + */ +package net.ccbluex.liquidbounce.utils.inventory + +import com.mojang.blaze3d.systems.RenderSystem +import net.ccbluex.liquidbounce.utils.client.mc +import net.minecraft.client.gui.DrawContext +import net.minecraft.client.gui.screen.Screen +import net.minecraft.client.gui.screen.ingame.InventoryScreen.drawEntity +import net.minecraft.client.render.RenderLayer +import net.minecraft.client.texture.Sprite +import net.minecraft.entity.player.PlayerEntity +import net.minecraft.item.ItemStack +import net.minecraft.screen.PlayerScreenHandler +import net.minecraft.screen.slot.Slot +import net.minecraft.text.Text +import net.minecraft.util.Identifier + +class ViewedInventoryScreen(private val player: () -> PlayerEntity?) : Screen(Text.empty()) { + + val handler: PlayerScreenHandler? + get() = player()?.playerScreenHandler + + private val backgroundWidth: Int = 176 + private val backgroundHeight: Int = 166 + private var x: Int = (width - backgroundWidth) / 2 + private var y: Int = (height - backgroundHeight) / 2 + + override fun init() { + x = (width - backgroundWidth) / 2 + y = (height - backgroundHeight) / 2 + } + + override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) { + super.render(context, mouseX, mouseY, delta) + + val handler = handler ?: return + RenderSystem.disableDepthTest() + context.matrices.push() + context.matrices.translate(x.toFloat(), y.toFloat(), 0.0f) + var hoveredSlot: Slot? = null + + for (slot in handler.slots) { + if (slot.isEnabled) { + drawSlot(context, slot) + } + + if (isPointOverSlot(slot, mouseX.toDouble(), mouseY.toDouble()) && slot.isEnabled) { + hoveredSlot = slot + if (slot.canBeHighlighted()) { + // draw slot highlight + context.fillGradient( + RenderLayer.getGuiOverlay(), + slot.x, slot.y, slot.x + 16, slot.y + 16, + -2130706433, -2130706433, 0 + ) + } + } + } + + val cursorStack = handler.cursorStack + if (!cursorStack.isEmpty) { + drawItem(context, cursorStack, mouseX - x - 8, mouseY - y - 8) + } + + context.matrices.pop() + RenderSystem.enableDepthTest() + + if (cursorStack.isEmpty && hoveredSlot != null && hoveredSlot.hasStack()) { + val hoveredItemStack = hoveredSlot.stack + context.drawTooltip( + textRenderer, getTooltipFromItem(mc, hoveredItemStack), + hoveredItemStack.tooltipData, mouseX, mouseY + ) + } + } + + override fun renderBackground(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) { + renderInGameBackground(context) + drawBackground(context, mouseX, mouseY) + } + + private fun drawItem(context: DrawContext, stack: ItemStack, x: Int, y: Int) { + context.matrices.push() + context.matrices.translate(0f, 0f, 232f) + context.drawItem(stack, x, y) + context.drawItemInSlot(textRenderer, stack, x, y, null) + context.matrices.pop() + } + + private fun drawBackground(context: DrawContext, mouseX: Int, mouseY: Int) { + val backgroundTexture = Identifier.ofVanilla("textures/gui/container/inventory.png") + context.drawTexture(backgroundTexture, x, y, 0, 0, backgroundWidth, backgroundHeight) + player()?.let { player -> + drawEntity( + context, x + 26, y + 8, x + 75, y + 78, + 30, 0.0625f, mouseX.toFloat(), mouseY.toFloat(), player + ) + } + } + + private fun drawSlot(context: DrawContext, slot: Slot) { + var spriteDrawn = false + + context.matrices.push() + context.matrices.translate(0f, 0f, 100f) + if (slot.stack.isEmpty && slot.isEnabled) { + val pair = slot.backgroundSprite + if (pair != null) { + val sprite = mc.getSpriteAtlas(pair.first).apply(pair.second) as Sprite + context.drawSprite(slot.x, slot.y, 0, 16, 16, sprite) + spriteDrawn = true + } + } + + if (!spriteDrawn) { + val seed = slot.x + slot.y * backgroundWidth + if (slot.disablesDynamicDisplay()) { + context.drawItemWithoutEntity(slot.stack, slot.x, slot.y, seed) + } else { + context.drawItem(slot.stack, slot.x, slot.y, seed) + } + + context.drawItemInSlot(textRenderer, slot.stack, slot.x, slot.y, null) + } + + context.matrices.pop() + } + + private fun isPointOverSlot(slot: Slot, pointX: Double, pointY: Double): Boolean { + val width = 16 + val height = 16 + val pX = pointX - x + val pY = pointY - y + return pX >= slot.x - 1 && pX < slot.x + width + 1 + && pY >= slot.y - 1 && pY < slot.y + height + 1 + } + + override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean { + super.keyPressed(keyCode, scanCode, modifiers) + + if (mc.options.inventoryKey.matchesKey(keyCode, scanCode)) { + close() + } + + return true + } + + override fun shouldPause() = false + + override fun tick() { + if (handler == null) { + close() + } + } +} diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/utils/math/MinecraftVectorExtensions.kt b/src/main/kotlin/net/ccbluex/liquidbounce/utils/math/MinecraftVectorExtensions.kt index 14d1679a06d..9ee71957cd8 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/utils/math/MinecraftVectorExtensions.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/utils/math/MinecraftVectorExtensions.kt @@ -35,6 +35,18 @@ inline operator fun Vec3i.component3() = this.z inline fun BlockPos.copy(x: Int = this.x, y: Int = this.y, z: Int = this.z) = BlockPos(x, y, z) +inline operator fun Vec3i.plus(other: Vec3i): Vec3i { + return this.add(other) +} + +inline operator fun Vec3i.minus(other: Vec3i): Vec3i { + return this.subtract(other) +} + +inline operator fun Vec3i.times(scalar: Int): Vec3i { + return this.multiply(scalar) +} + inline operator fun Vec3d.plus(other: Vec3d): Vec3d { return this.add(other) } @@ -46,6 +58,7 @@ inline operator fun Vec3d.minus(other: Vec3d): Vec3d { inline operator fun Vec3d.times(scalar: Double): Vec3d { return this.multiply(scalar) } + inline operator fun Vec3d.component1(): Double = this.x inline operator fun Vec3d.component2(): Double = this.y inline operator fun Vec3d.component3(): Double = this.z @@ -99,6 +112,12 @@ value class Double3Region private constructor(val init: Array) { operator fun Vec3d.rangeTo(other: Vec3d) = Double3Region(this, other) fun Vec3i.toVec3d(): Vec3d = Vec3d.of(this) +fun Vec3i.toVec3d( + xOffset: Double = 0.0, + yOffset: Double = 0.0, + zOffset: Double = 0.0, +): Vec3d = Vec3d(x + xOffset, y + yOffset, z + zOffset) + fun Vec3d.toVec3() = Vec3(this.x, this.y, this.z) fun Vec3d.toVec3i() = Vec3i(this.x.toInt(), this.y.toInt(), this.z.toInt()) diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/utils/movement/MovementUtils.kt b/src/main/kotlin/net/ccbluex/liquidbounce/utils/movement/MovementUtils.kt index 04f2a62e514..42ad4b10d81 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/utils/movement/MovementUtils.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/utils/movement/MovementUtils.kt @@ -59,9 +59,8 @@ data class DirectionalInput( return result } - fun isMoving(): Boolean { - return forwards || backwards || left || right - } + val isMoving: Boolean + get() = forwards || backwards || left || right companion object { val NONE = DirectionalInput(forwards = false, backwards = false, left = false, right = false) diff --git a/src/main/resources/assets/liquidbounce/lang/en_us.json b/src/main/resources/assets/liquidbounce/lang/en_us.json index 326f54a0410..6ccde95780c 100644 --- a/src/main/resources/assets/liquidbounce/lang/en_us.json +++ b/src/main/resources/assets/liquidbounce/lang/en_us.json @@ -475,6 +475,7 @@ "liquidbounce.module.highJump.description": "Allows you to jump higher.", "liquidbounce.module.hitbox.description": "Enlarges the hit box of targets.", "liquidbounce.module.holeESP.description": "Detects and displays safe spots for crystal PvP.", + "liquidbounce.module.holeFiller.description": "Automatically fills safe spots for crystal PvP.", "liquidbounce.module.hud.description": "Shows an in-game overlay with various useful tools.", "liquidbounce.module.hud.messages.hidingAppearance": "The client appearance is currently hidden. Use '.client appearance show' to re-enable it.", "liquidbounce.module.autoTrap.description": "Automatically sets targets on fire or traps them.", diff --git a/src/main/resources/liquidbounce.mixins.json b/src/main/resources/liquidbounce.mixins.json index e3a04ec2df2..cc94b011e8e 100644 --- a/src/main/resources/liquidbounce.mixins.json +++ b/src/main/resources/liquidbounce.mixins.json @@ -7,15 +7,12 @@ "mixinPriority": 1337, "client": [ "authlib.MixinMinecraftClient", - "minecraft.block.MixinAbstractBlock", "minecraft.block.MixinBlock", + "minecraft.block.MixinBlockCollisionSpliterator", "minecraft.block.MixinBlockView", - "minecraft.block.MixinCactusBlock", "minecraft.block.MixinCobwebBlock", - "minecraft.block.MixinFluidBlock", "minecraft.block.MixinPowderSnowBlock", "minecraft.block.MixinSlimeBlock", - "minecraft.block.MixinSnowBlock", "minecraft.client.MixinClientWorld", "minecraft.client.MixinClientWorldProperties", "minecraft.client.MixinGameMode",