From e6d1bef14b4db4a5cbaea916fbed2a532437147e Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Sat, 23 May 2026 21:10:07 +0300 Subject: [PATCH 01/13] (feat) Animations: add SwingAnimations --- .../minecraft/entity/MixinLivingEntity.java | 2 +- .../item/MixinItemInHandRenderer.java | 2 +- .../render/MixinSwingAnimationRenderer.java | 44 ++++ .../features/module/ModuleManager.kt | 2 +- .../{ => animations}/ModuleAnimations.kt | 10 +- .../render/animations/SwingAnimations.kt | 188 ++++++++++++++++++ src/main/resources/liquidbounce.mixins.json | 1 + 7 files changed, 243 insertions(+), 6 deletions(-) create mode 100644 src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/render/MixinSwingAnimationRenderer.java rename src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/{ => animations}/ModuleAnimations.kt (96%) create mode 100644 src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/SwingAnimations.kt diff --git a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/entity/MixinLivingEntity.java b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/entity/MixinLivingEntity.java index eaebdfdc03e..f465a2c5085 100644 --- a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/entity/MixinLivingEntity.java +++ b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/entity/MixinLivingEntity.java @@ -28,7 +28,7 @@ import net.ccbluex.liquidbounce.features.module.modules.combat.elytratarget.ModuleElytraTarget; import net.ccbluex.liquidbounce.features.module.modules.movement.*; import net.ccbluex.liquidbounce.features.module.modules.render.DoRender; -import net.ccbluex.liquidbounce.features.module.modules.render.ModuleAnimations; +import net.ccbluex.liquidbounce.features.module.modules.render.animations.ModuleAnimations; import net.ccbluex.liquidbounce.features.module.modules.render.ModuleAntiBlind; import net.ccbluex.liquidbounce.features.module.modules.render.hitfx.ModuleHitFX; import net.ccbluex.liquidbounce.features.module.modules.world.scaffold.ModuleScaffold; diff --git a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/item/MixinItemInHandRenderer.java b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/item/MixinItemInHandRenderer.java index 150fceac3ff..7d69a554cee 100644 --- a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/item/MixinItemInHandRenderer.java +++ b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/item/MixinItemInHandRenderer.java @@ -25,7 +25,7 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; import net.ccbluex.liquidbounce.features.module.modules.combat.ModuleSwordBlock; -import net.ccbluex.liquidbounce.features.module.modules.render.ModuleAnimations; +import net.ccbluex.liquidbounce.features.module.modules.render.animations.ModuleAnimations; import net.ccbluex.liquidbounce.features.module.modules.render.ModuleSilentHotbar; import net.ccbluex.liquidbounce.utils.client.SilentHotbar; import net.ccbluex.liquidbounce.utils.item.ItemCategorizationsKt; diff --git a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/render/MixinSwingAnimationRenderer.java b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/render/MixinSwingAnimationRenderer.java new file mode 100644 index 00000000000..1870e9793a1 --- /dev/null +++ b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/render/MixinSwingAnimationRenderer.java @@ -0,0 +1,44 @@ +package net.ccbluex.liquidbounce.injection.mixins.minecraft.render; + +import com.mojang.blaze3d.vertex.PoseStack; +import net.ccbluex.liquidbounce.features.module.modules.render.animations.ModuleAnimations; +import net.minecraft.client.player.AbstractClientPlayer; +import net.minecraft.client.renderer.ItemInHandRenderer; +import net.minecraft.client.renderer.SubmitNodeCollector; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.item.ItemDisplayContext; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.entity.HumanoidArm; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ItemInHandRenderer.class) +public abstract class MixinSwingAnimationRenderer { + + @Shadow + public abstract void renderItem(net.minecraft.world.entity.LivingEntity entity, ItemStack stack, ItemDisplayContext displayContext, PoseStack poseStack, SubmitNodeCollector nodeCollector, int packedLight); + + @Inject( + method = "renderArmWithItem", + at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/ItemInHandRenderer;applyItemArmTransform(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/world/entity/HumanoidArm;F)V"), + cancellable = true + ) + private void onRenderArmWithItem(AbstractClientPlayer player, float partialTick, float pitch, InteractionHand hand, float swingProgress, ItemStack item, float equippedProgress, PoseStack poseStack, SubmitNodeCollector nodeCollector, int packedLight, CallbackInfo ci) { + if (ModuleAnimations.INSTANCE.getEnabled() && ModuleAnimations.INSTANCE.getSwingAnimation().getEnabled() && hand == InteractionHand.MAIN_HAND) { + + ModuleAnimations.INSTANCE.getSwingAnimation().onRenderItem(player, hand, swingProgress, equippedProgress, poseStack); + + boolean isMainHand = hand == InteractionHand.MAIN_HAND; + HumanoidArm arm = isMainHand ? player.getMainArm() : player.getMainArm().getOpposite(); + ItemDisplayContext context = (arm == HumanoidArm.RIGHT) ? ItemDisplayContext.FIRST_PERSON_RIGHT_HAND : ItemDisplayContext.FIRST_PERSON_LEFT_HAND; + + this.renderItem(player, item, context, poseStack, nodeCollector, packedLight); + + poseStack.popPose(); + ci.cancel(); + } + } +} 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 5e4a9f3bec6..741e090f6e2 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/ModuleManager.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/ModuleManager.kt @@ -181,7 +181,7 @@ import net.ccbluex.liquidbounce.features.module.modules.player.cheststealer.Modu import net.ccbluex.liquidbounce.features.module.modules.player.invcleaner.ModuleInventoryCleaner import net.ccbluex.liquidbounce.features.module.modules.player.nofall.ModuleNoFall import net.ccbluex.liquidbounce.features.module.modules.player.offhand.ModuleOffhand -import net.ccbluex.liquidbounce.features.module.modules.render.ModuleAnimations +import net.ccbluex.liquidbounce.features.module.modules.render.animations.ModuleAnimations import net.ccbluex.liquidbounce.features.module.modules.render.ModuleAntiBlind import net.ccbluex.liquidbounce.features.module.modules.render.ModuleAspect import net.ccbluex.liquidbounce.features.module.modules.render.ModuleAutoF5 diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/ModuleAnimations.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/ModuleAnimations.kt similarity index 96% rename from src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/ModuleAnimations.kt rename to src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/ModuleAnimations.kt index 046ad5e59d8..dd07298ccc4 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/ModuleAnimations.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/ModuleAnimations.kt @@ -16,7 +16,8 @@ * 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.render + +package net.ccbluex.liquidbounce.features.module.modules.render.animations import com.mojang.blaze3d.vertex.PoseStack import com.mojang.math.Axis @@ -28,7 +29,6 @@ import net.ccbluex.liquidbounce.event.events.PlayerStrideEvent import net.ccbluex.liquidbounce.event.handler import net.ccbluex.liquidbounce.features.module.ClientModule import net.ccbluex.liquidbounce.features.module.ModuleCategories -import net.ccbluex.liquidbounce.features.module.modules.combat.ModuleSwordBlock import net.minecraft.util.Mth import net.minecraft.world.entity.HumanoidArm @@ -48,6 +48,7 @@ object ModuleAnimations : ClientModule("Animations", ModuleCategories.RENDER, al tree(MainHand) tree(OffHand) tree(EquipOffset) + tree(SwingAnimations) } object MainHand : ToggleableValueGroup(this, "MainHand", false) { @@ -73,8 +74,9 @@ object ModuleAnimations : ClientModule("Animations", ModuleCategories.RENDER, al /** * A choice that allows the user to choose the animation that will be used during the blocking * of a sword. - * This choice is only used when the [ModuleSwordBlock] module is enabled. + * This choice is only used when the [net.ccbluex.liquidbounce.features.module.modules.combat.ModuleSwordBlock] module is enabled. */ + val swingAnimation = SwingAnimations val blockAnimationChoice = choices( "BlockingAnimation", OneSevenAnimation, arrayOf( OneSevenAnimation, @@ -116,6 +118,8 @@ object ModuleAnimations : ClientModule("Animations", ModuleCategories.RENDER, al /** * A choice that aims to transform the held item transformation during the swing progress. */ + + abstract class AnimationMode(name: String) : Mode(name) { override val parent: ModeValueGroup<*> diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/SwingAnimations.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/SwingAnimations.kt new file mode 100644 index 00000000000..3c9eeb07ee1 --- /dev/null +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/SwingAnimations.kt @@ -0,0 +1,188 @@ +/* + * This file is part of LiquidBounce (https://github.com/CCBlueX/LiquidBounce) + * + * Copyright (c) 2015 - 2026 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.render.animations + +import com.mojang.blaze3d.vertex.PoseStack +import com.mojang.math.Axis +import net.ccbluex.liquidbounce.config.types.group.ToggleableValueGroup +import net.ccbluex.liquidbounce.config.types.list.Tagged +import net.minecraft.client.player.AbstractClientPlayer +import net.minecraft.util.Mth +import net.minecraft.world.InteractionHand +import net.minecraft.world.entity.HumanoidArm + +object SwingAnimations : ToggleableValueGroup(ModuleAnimations, "SwingAnimations", false) { + + val mode by enumChoice("Mode", Mode.One) + + enum class Mode(override val tag: String) : Tagged { + One("Jump"), Two("Swipe"), Three("Bounce"), Four("Tilt"), + Five("Pulse"), Six("Spin"), Seven("Hook"), Eight("Dash"), Nine("Tap"), + Ten("Inject"), Eleven("Slap"), Twelve("Akrien"), + Thirteen("Smooth"), Fourteen("Power"), Fifteen("Feast") + } + + private fun fSin(v: Float) = Mth.sin(v.toDouble()) + private fun fSqrt(v: Float) = Mth.sqrt(v) + private const val PI = Math.PI.toFloat() + + fun onRenderItem(player: AbstractClientPlayer, + hand: InteractionHand, + swingProgress: Float, + equipProgress: Float, + poseStack: PoseStack + ) { + val isMainHand = hand == InteractionHand.MAIN_HAND + val arm = if (isMainHand) player.mainArm else player.mainArm.opposite + + applySwing(poseStack, swingProgress, equipProgress, arm) + } + + @Suppress("LongMethod") + private fun applySwing(poseStack: PoseStack, + swing: Float, + equip: Float, + arm: HumanoidArm + ) { + val i = if (arm == HumanoidArm.RIGHT) 1 else -1 + val fSqrt = fSqrt(swing) + val g = fSin(fSqrt * PI) + val n = -0.4f * g + val sin1 = fSin(swing * swing * PI) + val sin2 = fSin(fSqrt(swing) * PI) + val sinSmooth = (fSin(swing * PI) * 0.5f) + + when (mode) { + Mode.One -> applyEquipOffset(poseStack, arm, 0.2f * fSin(fSqrt * PI * 2f)) + Mode.Two -> { + applyEquipOffset(poseStack, arm, n) + poseStack.mulPose(Axis.YP.rotationDegrees(i * (45.0f + swing * -20.0f))) + poseStack.mulPose(Axis.ZP.rotationDegrees(i * g * -70.0f)) + poseStack.mulPose(Axis.XP.rotationDegrees(-70f)) + poseStack.mulPose(Axis.YP.rotationDegrees(i * -45.0f)) + } + Mode.Three -> { + applyEquipOffset(poseStack, arm, 0f) + if (swing > 0) poseStack.mulPose(Axis.XP.rotationDegrees(-fSin(swing * 13f) * 37f)) + } + Mode.Four -> { + applyEquipOffset(poseStack, arm, 0f) + poseStack.mulPose(Axis.ZP.rotationDegrees(i * g * -20.0f)) + } + Mode.Five -> { + applyEquipOffset(poseStack, arm, equip) + val scale = -fSin(swing * 3f) / 2f + 1f + poseStack.scale(scale, scale, scale) + } + Mode.Six -> { + applyEquipOffset(poseStack, arm, equip) + poseStack.mulPose(Axis.XP.rotationDegrees(swing * -360f)) + } + Mode.Seven -> { + applyEquipOffset(poseStack, arm, 0f) + poseStack.mulPose(Axis.XP.rotationDegrees(50f)) + poseStack.mulPose(Axis.YP.rotationDegrees(i * (-30f * (1f - g) - 30f))) + poseStack.mulPose(Axis.ZP.rotationDegrees(i * 110f)) + } + Mode.Eight -> { + applyEquipOffset(poseStack, arm, 0f) + poseStack.mulPose(Axis.XP.rotationDegrees(50f)) + poseStack.mulPose(Axis.YP.rotationDegrees(i * (-60f * g - 50f))) + poseStack.mulPose(Axis.ZP.rotationDegrees(i * 110f)) + } + Mode.Nine -> { + applyEquipOffset(poseStack, arm, 0f) + poseStack.mulPose(Axis.XP.rotationDegrees(50f)) + poseStack.mulPose(Axis.YP.rotationDegrees(i * -60f)) + poseStack.mulPose(Axis.ZP.rotationDegrees(i * (110f + 20f * g))) + } + Mode.Ten -> { + applyEquipOffset(poseStack, arm, 0f) + poseStack.translate(0.0, 0.0, (-g / 4.0)) + poseStack.mulPose(Axis.XP.rotationDegrees(-120f)) + } + Mode.Eleven -> { + applyEquipOffset(poseStack, arm, 0f) + poseStack.mulPose(Axis.XP.rotationDegrees(-fSin(swing * 3f) * 60f)) + poseStack.mulPose(Axis.ZP.rotationDegrees(i * -60f * g)) + } + Mode.Twelve -> { + if (swing > 0) { + poseStack.translate(i * 0.56, (equip * -0.2f) - 0.5, -0.7) + poseStack.mulPose(Axis.YP.rotationDegrees(i * 45f)) + poseStack.mulPose(Axis.XP.rotationDegrees(g * -85.0f)) + poseStack.translate(i * -0.1, 0.28, 0.2) + poseStack.mulPose(Axis.XP.rotationDegrees(-85.0f)) + } else { + val m = 0.2f * fSin(fSqrt * PI * 2f) + val f2 = -0.2f * fSin(swing * PI) + poseStack.translate(i * n.toDouble(), m.toDouble(), f2.toDouble()) + applyEquipOffset(poseStack, arm, equip) + applySwingOffset(poseStack, arm, swing) + } + } + + Mode.Thirteen -> { + poseStack.translate(i * 0.56, -0.42, -0.72) + poseStack.mulPose(Axis.YP.rotationDegrees(i * (45.0f + sin1 * -20.0f))) + poseStack.mulPose(Axis.ZP.rotationDegrees(i * sin2 * -20.0f)) + poseStack.mulPose(Axis.XP.rotationDegrees(sin2 * -80.0f)) + poseStack.mulPose(Axis.YP.rotationDegrees(i * -45.0f)) + poseStack.translate(0.0, -0.1, 0.0) + } + + Mode.Fourteen -> { + poseStack.translate(i * 0.56, -0.32, -0.72) + poseStack.translate((-sinSmooth * sinSmooth * sin1 * i).toDouble(), 0.0, 0.0) + poseStack.mulPose(Axis.YP.rotationDegrees(i * 61f)) + poseStack.mulPose(Axis.ZP.rotationDegrees(sin2)) + poseStack.mulPose(Axis.YP.rotationDegrees(sin2 * sin1 * -5.0f)) + poseStack.mulPose(Axis.XP.rotationDegrees(sin2 * sin1 * -30.0f)) + poseStack.mulPose(Axis.XP.rotationDegrees(-60.0f)) + poseStack.mulPose(Axis.XP.rotationDegrees(sinSmooth * -60.0f)) + } + + Mode.Fifteen -> { + poseStack.translate(i * 0.56, -0.32, -0.72) + poseStack.mulPose(Axis.YP.rotationDegrees(i * 30f)) + poseStack.mulPose(Axis.YP.rotationDegrees(sin2 * 75.0f * i)) + poseStack.mulPose(Axis.XP.rotationDegrees(sin2 * -45.0f)) + poseStack.mulPose(Axis.YP.rotationDegrees(i * 30f)) + poseStack.mulPose(Axis.XP.rotationDegrees(-80.0f)) + poseStack.mulPose(Axis.YP.rotationDegrees(i * 35f)) + } + } + } + + private fun applyEquipOffset(poseStack: PoseStack, arm: HumanoidArm, equip: Float) { + val i = if (arm == HumanoidArm.RIGHT) 1 else -1 + poseStack.translate(i * 0.56, -0.52 + equip * -0.6, -0.72) + } + + private fun applySwingOffset(poseStack: PoseStack, arm: HumanoidArm, swing: Float) { + val i = if (arm == HumanoidArm.RIGHT) 1 else -1 + val f1 = fSin(swing * swing * PI) + poseStack.mulPose(Axis.YP.rotationDegrees(i * (45.0f + f1 * -20.0f))) + val g = fSin(fSqrt(swing) * PI) + poseStack.mulPose(Axis.ZP.rotationDegrees(i * g * -20.0f)) + poseStack.mulPose(Axis.XP.rotationDegrees(g * -80.0f)) + poseStack.mulPose(Axis.YP.rotationDegrees(i * -45.0f)) + } +} diff --git a/src/main/resources/liquidbounce.mixins.json b/src/main/resources/liquidbounce.mixins.json index 4e773fbf81a..94b3c06d021 100644 --- a/src/main/resources/liquidbounce.mixins.json +++ b/src/main/resources/liquidbounce.mixins.json @@ -149,6 +149,7 @@ "minecraft.render.fog.MixinBlindnessFogEnvironment", "minecraft.render.fog.MixinFogRenderer", "minecraft.render.special.MixinShieldSpecialRenderer", + "minecraft.render.MixinSwingAnimationRenderer", "minecraft.text.MixinGuiMessage", "minecraft.text.MixinGuiMessageLineVisible", "minecraft.text.MixinMutableComponent", From 7d9d0d144749bd30f6d8fad6ccd988b4acf7c193 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Sat, 23 May 2026 21:52:18 +0300 Subject: [PATCH 02/13] fix(Animations): drop hand on swing --- .../module/modules/render/animations/SwingAnimations.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/SwingAnimations.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/SwingAnimations.kt index 3c9eeb07ee1..61c1e33ad03 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/SwingAnimations.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/SwingAnimations.kt @@ -87,12 +87,12 @@ object SwingAnimations : ToggleableValueGroup(ModuleAnimations, "SwingAnimations poseStack.mulPose(Axis.ZP.rotationDegrees(i * g * -20.0f)) } Mode.Five -> { - applyEquipOffset(poseStack, arm, equip) + applyEquipOffset(poseStack, arm, 0f) val scale = -fSin(swing * 3f) / 2f + 1f poseStack.scale(scale, scale, scale) } Mode.Six -> { - applyEquipOffset(poseStack, arm, equip) + applyEquipOffset(poseStack, arm, 0f) poseStack.mulPose(Axis.XP.rotationDegrees(swing * -360f)) } Mode.Seven -> { From 101efaa2f2b0efd3db1105fcecf246da7239dbd3 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Sat, 23 May 2026 22:11:12 +0300 Subject: [PATCH 03/13] =?UTF-8?q?fix(Animations):=20restore=20block=20anim?= =?UTF-8?q?ation=20=F0=9F=92=80=F0=9F=94=A5=E2=9C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../render/MixinSwingAnimationRenderer.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/render/MixinSwingAnimationRenderer.java b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/render/MixinSwingAnimationRenderer.java index 1870e9793a1..d9316de69dc 100644 --- a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/render/MixinSwingAnimationRenderer.java +++ b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/render/MixinSwingAnimationRenderer.java @@ -1,6 +1,7 @@ package net.ccbluex.liquidbounce.injection.mixins.minecraft.render; import com.mojang.blaze3d.vertex.PoseStack; +import net.ccbluex.liquidbounce.features.module.modules.combat.ModuleSwordBlock; import net.ccbluex.liquidbounce.features.module.modules.render.animations.ModuleAnimations; import net.minecraft.client.player.AbstractClientPlayer; import net.minecraft.client.renderer.ItemInHandRenderer; @@ -28,17 +29,20 @@ public abstract class MixinSwingAnimationRenderer { ) private void onRenderArmWithItem(AbstractClientPlayer player, float partialTick, float pitch, InteractionHand hand, float swingProgress, ItemStack item, float equippedProgress, PoseStack poseStack, SubmitNodeCollector nodeCollector, int packedLight, CallbackInfo ci) { if (ModuleAnimations.INSTANCE.getEnabled() && ModuleAnimations.INSTANCE.getSwingAnimation().getEnabled() && hand == InteractionHand.MAIN_HAND) { + if (ModuleSwordBlock.INSTANCE.getEnabled() && !ModuleSwordBlock.shouldAnimateSwordBlock(player)) { - ModuleAnimations.INSTANCE.getSwingAnimation().onRenderItem(player, hand, swingProgress, equippedProgress, poseStack); + ModuleAnimations.INSTANCE.getSwingAnimation().onRenderItem(player, hand, swingProgress, equippedProgress, poseStack); - boolean isMainHand = hand == InteractionHand.MAIN_HAND; - HumanoidArm arm = isMainHand ? player.getMainArm() : player.getMainArm().getOpposite(); - ItemDisplayContext context = (arm == HumanoidArm.RIGHT) ? ItemDisplayContext.FIRST_PERSON_RIGHT_HAND : ItemDisplayContext.FIRST_PERSON_LEFT_HAND; + boolean isMainHand = hand == InteractionHand.MAIN_HAND; + HumanoidArm arm = isMainHand ? player.getMainArm() : player.getMainArm().getOpposite(); + ItemDisplayContext context = (arm == HumanoidArm.RIGHT) ? ItemDisplayContext.FIRST_PERSON_RIGHT_HAND : ItemDisplayContext.FIRST_PERSON_LEFT_HAND; - this.renderItem(player, item, context, poseStack, nodeCollector, packedLight); + this.renderItem(player, item, context, poseStack, nodeCollector, packedLight); - poseStack.popPose(); - ci.cancel(); + poseStack.popPose(); + ci.cancel(); + + } } } } From 81b20ea4eb38842d11ba8fe2837bff38ec0ea729 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Sat, 23 May 2026 23:39:24 +0300 Subject: [PATCH 04/13] fix(Animations): correct item use, shield rendering, and hand drop on Akrien animation --- .../render/MixinSwingAnimationRenderer.java | 22 +++++++++++++------ .../render/animations/SwingAnimations.kt | 4 ++-- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/render/MixinSwingAnimationRenderer.java b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/render/MixinSwingAnimationRenderer.java index d9316de69dc..4968bd83539 100644 --- a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/render/MixinSwingAnimationRenderer.java +++ b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/render/MixinSwingAnimationRenderer.java @@ -10,18 +10,24 @@ import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.ItemStack; import net.minecraft.world.entity.HumanoidArm; +import net.minecraft.world.item.Items; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import static net.minecraft.world.item.Items.SHIELD; + @Mixin(ItemInHandRenderer.class) public abstract class MixinSwingAnimationRenderer { @Shadow public abstract void renderItem(net.minecraft.world.entity.LivingEntity entity, ItemStack stack, ItemDisplayContext displayContext, PoseStack poseStack, SubmitNodeCollector nodeCollector, int packedLight); + @Shadow + private ItemStack mainHandItem; + @Inject( method = "renderArmWithItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/ItemInHandRenderer;applyItemArmTransform(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/world/entity/HumanoidArm;F)V"), @@ -30,18 +36,20 @@ public abstract class MixinSwingAnimationRenderer { private void onRenderArmWithItem(AbstractClientPlayer player, float partialTick, float pitch, InteractionHand hand, float swingProgress, ItemStack item, float equippedProgress, PoseStack poseStack, SubmitNodeCollector nodeCollector, int packedLight, CallbackInfo ci) { if (ModuleAnimations.INSTANCE.getEnabled() && ModuleAnimations.INSTANCE.getSwingAnimation().getEnabled() && hand == InteractionHand.MAIN_HAND) { if (ModuleSwordBlock.INSTANCE.getEnabled() && !ModuleSwordBlock.shouldAnimateSwordBlock(player)) { + if (!player.isUsingItem() && player.getItemInHand(InteractionHand.MAIN_HAND).getItem() != SHIELD) { - ModuleAnimations.INSTANCE.getSwingAnimation().onRenderItem(player, hand, swingProgress, equippedProgress, poseStack); + ModuleAnimations.INSTANCE.getSwingAnimation().onRenderItem(player, hand, swingProgress, equippedProgress, poseStack); - boolean isMainHand = hand == InteractionHand.MAIN_HAND; - HumanoidArm arm = isMainHand ? player.getMainArm() : player.getMainArm().getOpposite(); - ItemDisplayContext context = (arm == HumanoidArm.RIGHT) ? ItemDisplayContext.FIRST_PERSON_RIGHT_HAND : ItemDisplayContext.FIRST_PERSON_LEFT_HAND; + boolean isMainHand = hand == InteractionHand.MAIN_HAND; + HumanoidArm arm = isMainHand ? player.getMainArm() : player.getMainArm().getOpposite(); + ItemDisplayContext context = (arm == HumanoidArm.RIGHT) ? ItemDisplayContext.FIRST_PERSON_RIGHT_HAND : ItemDisplayContext.FIRST_PERSON_LEFT_HAND; - this.renderItem(player, item, context, poseStack, nodeCollector, packedLight); + this.renderItem(player, item, context, poseStack, nodeCollector, packedLight); - poseStack.popPose(); - ci.cancel(); + poseStack.popPose(); + ci.cancel(); + } } } } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/SwingAnimations.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/SwingAnimations.kt index 61c1e33ad03..560de8904d7 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/SwingAnimations.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/SwingAnimations.kt @@ -30,7 +30,7 @@ import net.minecraft.world.entity.HumanoidArm object SwingAnimations : ToggleableValueGroup(ModuleAnimations, "SwingAnimations", false) { - val mode by enumChoice("Mode", Mode.One) + val mode by enumChoice("Mode", Mode.Fourteen) enum class Mode(override val tag: String) : Tagged { One("Jump"), Two("Swipe"), Three("Bounce"), Four("Tilt"), @@ -134,7 +134,7 @@ object SwingAnimations : ToggleableValueGroup(ModuleAnimations, "SwingAnimations val m = 0.2f * fSin(fSqrt * PI * 2f) val f2 = -0.2f * fSin(swing * PI) poseStack.translate(i * n.toDouble(), m.toDouble(), f2.toDouble()) - applyEquipOffset(poseStack, arm, equip) + applyEquipOffset(poseStack, arm, 0f) applySwingOffset(poseStack, arm, swing) } } From a3b9151bfe380a5fd275df10238a7345c0e950b8 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Sat, 23 May 2026 23:48:55 +0300 Subject: [PATCH 05/13] style(animations): reduce line 77 to satisfy detekt "[net.ccbluex.liquidbounce.features.module.modules.combat.ModuleSwordBlock]" too long for detekt --- .../module/modules/render/animations/ModuleAnimations.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/ModuleAnimations.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/ModuleAnimations.kt index dd07298ccc4..994aebfdf9f 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/ModuleAnimations.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/ModuleAnimations.kt @@ -74,8 +74,9 @@ object ModuleAnimations : ClientModule("Animations", ModuleCategories.RENDER, al /** * A choice that allows the user to choose the animation that will be used during the blocking * of a sword. - * This choice is only used when the [net.ccbluex.liquidbounce.features.module.modules.combat.ModuleSwordBlock] module is enabled. + * This choice is only used when the [ModuleSwordBlock] module is enabled. */ + val swingAnimation = SwingAnimations val blockAnimationChoice = choices( "BlockingAnimation", OneSevenAnimation, arrayOf( From c2077764ad45d830c8a44f16876fb9a6102bf981 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Sun, 24 May 2026 22:02:23 +0300 Subject: [PATCH 06/13] feat(Animation): add more blocking animations --- .../render/animations/ModuleAnimations.kt | 166 +++++++++++++++++- 1 file changed, 165 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/ModuleAnimations.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/ModuleAnimations.kt index 994aebfdf9f..7aa3fdab796 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/ModuleAnimations.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/ModuleAnimations.kt @@ -29,8 +29,10 @@ import net.ccbluex.liquidbounce.event.events.PlayerStrideEvent import net.ccbluex.liquidbounce.event.handler import net.ccbluex.liquidbounce.features.module.ClientModule import net.ccbluex.liquidbounce.features.module.ModuleCategories +import net.ccbluex.liquidbounce.utils.math.toRadians import net.minecraft.util.Mth import net.minecraft.world.entity.HumanoidArm +import org.joml.Quaternionf /** * Animations module @@ -81,7 +83,11 @@ object ModuleAnimations : ClientModule("Animations", ModuleCategories.RENDER, al val blockAnimationChoice = choices( "BlockingAnimation", OneSevenAnimation, arrayOf( OneSevenAnimation, - PushdownAnimation + PushdownAnimation, + SigmaAnimation, + ExhibitionAnimation, + AvatarAnimation, + DortwareAnimation ) ) @@ -181,4 +187,162 @@ object ModuleAnimations : ClientModule("Animations", ModuleCategories.RENDER, al } + object SigmaAnimation : AnimationMode("Sigma") { + + private val translateY by float("Y", 0.1f, 0.05f..0.3f) + + override fun transform(matrices: PoseStack, arm: HumanoidArm, equipProgress: Float, swingProgress: Float) { + + val sine = Mth.sin(Mth.sqrt(swingProgress) * Math.PI) + val sideM = if (arm == HumanoidArm.RIGHT) 1.0f else -1.0f + + val rot1 = Quaternionf().rotationAxis( + (-sine * 27.5f * sideM).toRadians(), + -8.0f * sideM, + 0.0f, + 9.0f + ) + matrices.mulPose(rot1) + + val rot2 = Quaternionf().rotationAxis( + (-sine * 45.0f * sideM).toRadians(), + 1.0f * sideM, + sine / 2.0f, + 0.0f + ) + matrices.mulPose(rot2) + + matrices.translate(0.0f, translateY, 0.0f) + applySwingOffset(matrices, arm, 0f) + } + } + + object ExhibitionAnimation : AnimationMode("Exhibition") { + + private val translateY by float("Y", 0.1f, 0.05f..0.3f) + + override fun transform(matrices: PoseStack, arm: HumanoidArm, equipProgress: Float, swingProgress: Float) { + + val sine = Mth.sin(Mth.sqrt(swingProgress) * Math.PI) + val sideM = if (arm == HumanoidArm.RIGHT) 1.0f else -1.0f + + matrices.translate(0.0, -0.1, 0.0) + + applySwingOffset(matrices, arm, 0f) + + matrices.translate(0.1F, 0.4F, -0.1F) + + val rot1 = Quaternionf().rotationAxis( + (-sine * 30.0F * sideM).toRadians(), + sine.div(2F), + 0.0F, + 9.0F + ) + matrices.mulPose(rot1) + + val rot2 = Quaternionf().rotationAxis( + (-sine * 50.0F * sideM).toRadians(), + 0.8F * sideM, + sine.div(2F), + 0F + ) + + matrices.mulPose(rot2) + + matrices.translate(0.0f, translateY - 0.2f, 0.0f) + + } + + } + + object AvatarAnimation : AnimationMode("Avatar") { + + private val translateY by float("Y", 0.1f, 0.05f..0.3f) + + override fun transform(matrices: PoseStack, arm: HumanoidArm, equipProgress: Float, swingProgress: Float) { + + val sine = Mth.sin(Mth.sqrt(swingProgress) * Math.PI) + val sine1 = Mth.sin(swingProgress * swingProgress * Math.PI) + val sideM = if (arm == HumanoidArm.RIGHT) 1.0f else -1.0f + + matrices.translate(0F, translateY, 0F) + + val rot1 = Quaternionf().rotationAxis( + (0.0F * sideM).toRadians(), + 0.0F, + 1.0F, + 0.0F + ) + matrices.mulPose(rot1) + + val rot2 = Quaternionf().rotationAxis( + (sine1 * -20.0F * sideM).toRadians(), + 0.0F, + 1.0F, + 0.0F + ) + matrices.mulPose(rot2) + + val rot3 = Quaternionf().rotationAxis( + (sine * -20.0F * sideM).toRadians(), + 0.0F, + 0.0F, + 1.0F + ) + matrices.mulPose(rot3) + + val rot4 = Quaternionf().rotationAxis( + (sine * -40.0F * sideM).toRadians(), + 1.0F * sideM, + 0.0F, + 0.0F + ) + matrices.mulPose(rot4) + + applySwingOffset(matrices, arm, 0f) + } + } + + object DortwareAnimation : AnimationMode("Dortware") { + + private val translateY by float("Y", 0.1f, 0.05f..0.3f) + + override fun transform(matrices: PoseStack, arm: HumanoidArm, equipProgress: Float, swingProgress: Float) { + + val sine = Mth.sin(Mth.sqrt(swingProgress) * Math.PI) + val sqrtSwing = Mth.sqrt(swingProgress) + val altSine = Mth.sin(sqrtSwing * Math.PI - 3) + val sideM = if (arm == HumanoidArm.RIGHT) 1.0f else -1.0f + + val rot1 = Quaternionf().rotationAxis( + (-sine * 10).toRadians(), + 0.0f, + 15.0f, + 200.0f + ) + matrices.mulPose(rot1) + + val rot2 = Quaternionf().rotationAxis( + (-sine * 10f).toRadians(), + 300.0f, + sine.div(2f), + 1.0f + ) + matrices.mulPose(rot2) + matrices.translate(3.4, 0.3, -0.4) + matrices.translate(-2.10f, -0.2f, 0.1f) + + val rot3 = Quaternionf().rotationAxis( + (altSine * 13.0f).toRadians(), + -10.0f, + -1.4f, + -10.0f + ) + matrices.mulPose(rot3) + + matrices.translate(if(arm == HumanoidArm.RIGHT) -1f else -2f, translateY, 0f) + + applySwingOffset(matrices, arm, 0f) + } + } } From 10aa2ba4cde194c603a5f6889fed46cd42a45dc8 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Sun, 24 May 2026 22:03:21 +0300 Subject: [PATCH 07/13] fix: set "exploit preventer" version from 1.0.6+ to 1.0.6+26.1 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5eb3cdcd0b2..0866940cfa8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -32,7 +32,7 @@ fastutil4k = "0.2.8" # Recommended mods modmenu = "18.0.0-alpha.7" exploit_preventer_api = "1.0.0" -exploit_preventer_mod = "1.0.6+" +exploit_preventer_mod = "1.0.6+26.1" sodium = "mc26.1.2-0.8.12-fabric" lithium = "mc26.1.2-0.24.2-fabric" viafabricplus = "4.5.3" From d52128d1d089534572665e9e2e9ffe85715649da Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Sun, 24 May 2026 22:10:16 +0300 Subject: [PATCH 08/13] fix(Build): fix exploit preventer version resolving to incompatible build --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5eb3cdcd0b2..0866940cfa8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -32,7 +32,7 @@ fastutil4k = "0.2.8" # Recommended mods modmenu = "18.0.0-alpha.7" exploit_preventer_api = "1.0.0" -exploit_preventer_mod = "1.0.6+" +exploit_preventer_mod = "1.0.6+26.1" sodium = "mc26.1.2-0.8.12-fabric" lithium = "mc26.1.2-0.24.2-fabric" viafabricplus = "4.5.3" From 26555345cc41afb711a23f59a5755ef0edfe000c Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Sun, 24 May 2026 22:10:43 +0300 Subject: [PATCH 09/13] fix(Animation): remove swordblock dependency from swing animation --- .../mixins/minecraft/render/MixinSwingAnimationRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/render/MixinSwingAnimationRenderer.java b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/render/MixinSwingAnimationRenderer.java index 4968bd83539..7b41f0e20e5 100644 --- a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/render/MixinSwingAnimationRenderer.java +++ b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/render/MixinSwingAnimationRenderer.java @@ -35,7 +35,7 @@ public abstract class MixinSwingAnimationRenderer { ) private void onRenderArmWithItem(AbstractClientPlayer player, float partialTick, float pitch, InteractionHand hand, float swingProgress, ItemStack item, float equippedProgress, PoseStack poseStack, SubmitNodeCollector nodeCollector, int packedLight, CallbackInfo ci) { if (ModuleAnimations.INSTANCE.getEnabled() && ModuleAnimations.INSTANCE.getSwingAnimation().getEnabled() && hand == InteractionHand.MAIN_HAND) { - if (ModuleSwordBlock.INSTANCE.getEnabled() && !ModuleSwordBlock.shouldAnimateSwordBlock(player)) { + if (!ModuleSwordBlock.shouldAnimateSwordBlock(player)) { if (!player.isUsingItem() && player.getItemInHand(InteractionHand.MAIN_HAND).getItem() != SHIELD) { ModuleAnimations.INSTANCE.getSwingAnimation().onRenderItem(player, hand, swingProgress, equippedProgress, poseStack); From 758bdc1b2159d7a571ee63803f9e81935a1d96d5 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Sun, 24 May 2026 22:32:02 +0300 Subject: [PATCH 10/13] fix(Animation): remove swordblock dependency from swing animation --- .../mixins/minecraft/render/MixinSwingAnimationRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/render/MixinSwingAnimationRenderer.java b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/render/MixinSwingAnimationRenderer.java index 4968bd83539..7b41f0e20e5 100644 --- a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/render/MixinSwingAnimationRenderer.java +++ b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/render/MixinSwingAnimationRenderer.java @@ -35,7 +35,7 @@ public abstract class MixinSwingAnimationRenderer { ) private void onRenderArmWithItem(AbstractClientPlayer player, float partialTick, float pitch, InteractionHand hand, float swingProgress, ItemStack item, float equippedProgress, PoseStack poseStack, SubmitNodeCollector nodeCollector, int packedLight, CallbackInfo ci) { if (ModuleAnimations.INSTANCE.getEnabled() && ModuleAnimations.INSTANCE.getSwingAnimation().getEnabled() && hand == InteractionHand.MAIN_HAND) { - if (ModuleSwordBlock.INSTANCE.getEnabled() && !ModuleSwordBlock.shouldAnimateSwordBlock(player)) { + if (!ModuleSwordBlock.shouldAnimateSwordBlock(player)) { if (!player.isUsingItem() && player.getItemInHand(InteractionHand.MAIN_HAND).getItem() != SHIELD) { ModuleAnimations.INSTANCE.getSwingAnimation().onRenderItem(player, hand, swingProgress, equippedProgress, poseStack); From 3baf6c9017a632411947c57ea62cace0c7f6bcbe Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Sun, 24 May 2026 23:18:31 +0300 Subject: [PATCH 11/13] refactor(Animations): adjust Avatar X-position --- .../module/modules/render/animations/ModuleAnimations.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/ModuleAnimations.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/ModuleAnimations.kt index 7aa3fdab796..a495528d11d 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/ModuleAnimations.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/ModuleAnimations.kt @@ -265,7 +265,7 @@ object ModuleAnimations : ClientModule("Animations", ModuleCategories.RENDER, al val sine1 = Mth.sin(swingProgress * swingProgress * Math.PI) val sideM = if (arm == HumanoidArm.RIGHT) 1.0f else -1.0f - matrices.translate(0F, translateY, 0F) + matrices.translate(0.2F * sideM, translateY, 0F) val rot1 = Quaternionf().rotationAxis( (0.0F * sideM).toRadians(), From 5c48ba12f29124071170b959579adc8a8425ba04 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Mon, 25 May 2026 21:18:52 +0300 Subject: [PATCH 12/13] refactor(Animations): optimize blocking animations code --- .../render/animations/ModuleAnimations.kt | 64 ++++++------------- 1 file changed, 19 insertions(+), 45 deletions(-) diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/ModuleAnimations.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/ModuleAnimations.kt index a495528d11d..fe8013a39ca 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/ModuleAnimations.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/ModuleAnimations.kt @@ -196,21 +196,18 @@ object ModuleAnimations : ClientModule("Animations", ModuleCategories.RENDER, al val sine = Mth.sin(Mth.sqrt(swingProgress) * Math.PI) val sideM = if (arm == HumanoidArm.RIGHT) 1.0f else -1.0f - val rot1 = Quaternionf().rotationAxis( + val rot = Quaternionf().rotationAxis( (-sine * 27.5f * sideM).toRadians(), -8.0f * sideM, 0.0f, 9.0f - ) - matrices.mulPose(rot1) - - val rot2 = Quaternionf().rotationAxis( + ).rotateAxis( (-sine * 45.0f * sideM).toRadians(), 1.0f * sideM, sine / 2.0f, 0.0f ) - matrices.mulPose(rot2) + matrices.mulPose(rot) matrices.translate(0.0f, translateY, 0.0f) applySwingOffset(matrices, arm, 0f) @@ -232,22 +229,18 @@ object ModuleAnimations : ClientModule("Animations", ModuleCategories.RENDER, al matrices.translate(0.1F, 0.4F, -0.1F) - val rot1 = Quaternionf().rotationAxis( + val rot = Quaternionf().rotationAxis( (-sine * 30.0F * sideM).toRadians(), sine.div(2F), 0.0F, 9.0F - ) - matrices.mulPose(rot1) - - val rot2 = Quaternionf().rotationAxis( + ).rotateAxis( (-sine * 50.0F * sideM).toRadians(), 0.8F * sideM, sine.div(2F), 0F ) - - matrices.mulPose(rot2) + matrices.mulPose(rot) matrices.translate(0.0f, translateY - 0.2f, 0.0f) @@ -267,37 +260,22 @@ object ModuleAnimations : ClientModule("Animations", ModuleCategories.RENDER, al matrices.translate(0.2F * sideM, translateY, 0F) - val rot1 = Quaternionf().rotationAxis( + val rot = Quaternionf().rotationAxis( (0.0F * sideM).toRadians(), 0.0F, 1.0F, 0.0F - ) - matrices.mulPose(rot1) - - val rot2 = Quaternionf().rotationAxis( - (sine1 * -20.0F * sideM).toRadians(), - 0.0F, - 1.0F, - 0.0F - ) - matrices.mulPose(rot2) - - val rot3 = Quaternionf().rotationAxis( - (sine * -20.0F * sideM).toRadians(), - 0.0F, - 0.0F, - 1.0F - ) - matrices.mulPose(rot3) - - val rot4 = Quaternionf().rotationAxis( + ).rotateY( + (sine1 * -20.0F * sideM).toRadians() + ).rotateZ( + (sine * -20.0F * sideM).toRadians() + ).rotateAxis( (sine * -40.0F * sideM).toRadians(), 1.0F * sideM, 0.0F, 0.0F ) - matrices.mulPose(rot4) + matrices.mulPose(rot) applySwingOffset(matrices, arm, 0f) } @@ -312,37 +290,33 @@ object ModuleAnimations : ClientModule("Animations", ModuleCategories.RENDER, al val sine = Mth.sin(Mth.sqrt(swingProgress) * Math.PI) val sqrtSwing = Mth.sqrt(swingProgress) val altSine = Mth.sin(sqrtSwing * Math.PI - 3) - val sideM = if (arm == HumanoidArm.RIGHT) 1.0f else -1.0f - val rot1 = Quaternionf().rotationAxis( + val rot = Quaternionf().rotationAxis( (-sine * 10).toRadians(), 0.0f, 15.0f, 200.0f - ) - matrices.mulPose(rot1) - - val rot2 = Quaternionf().rotationAxis( + ).rotateAxis( (-sine * 10f).toRadians(), 300.0f, sine.div(2f), 1.0f ) - matrices.mulPose(rot2) + matrices.mulPose(rot) + matrices.translate(3.4, 0.3, -0.4) matrices.translate(-2.10f, -0.2f, 0.1f) - val rot3 = Quaternionf().rotationAxis( + val rot1 = Quaternionf().rotationAxis( (altSine * 13.0f).toRadians(), -10.0f, -1.4f, -10.0f ) - matrices.mulPose(rot3) + matrices.mulPose(rot1) matrices.translate(if(arm == HumanoidArm.RIGHT) -1f else -2f, translateY, 0f) - applySwingOffset(matrices, arm, 0f) } } } From e857cd878256c70fc661e6a6a37ae8e59714d659 Mon Sep 17 00:00:00 2001 From: minecrrrr Date: Tue, 4 Aug 2026 15:48:26 +0300 Subject: [PATCH 13/13] fix(animations): adapt swing animations and arm transform mixins to 26.2 pipeline --- .../item/MixinItemInHandRenderer.java | 36 ++++++++-- .../render/MixinSwingAnimationRenderer.java | 56 ---------------- .../render/animations/SwingAnimations.kt | 66 +++++-------------- src/main/resources/liquidbounce.mixins.json | 1 - 4 files changed, 47 insertions(+), 112 deletions(-) delete mode 100644 src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/render/MixinSwingAnimationRenderer.java diff --git a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/item/MixinItemInHandRenderer.java b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/item/MixinItemInHandRenderer.java index c604f7d73f0..78d5c9c0f84 100644 --- a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/item/MixinItemInHandRenderer.java +++ b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/item/MixinItemInHandRenderer.java @@ -27,6 +27,7 @@ import net.ccbluex.liquidbounce.features.module.modules.combat.ModuleSwordBlock; import net.ccbluex.liquidbounce.features.module.modules.render.animations.ModuleAnimations; import net.ccbluex.liquidbounce.features.module.modules.render.ModuleSilentHotbar; +import net.ccbluex.liquidbounce.features.module.modules.render.animations.SwingAnimations; import net.ccbluex.liquidbounce.utils.client.SilentHotbar; import net.ccbluex.liquidbounce.utils.item.ItemCategorizationsKt; import net.ccbluex.liquidbounce.utils.render.FirstPersonShieldTint; @@ -37,6 +38,7 @@ import net.minecraft.client.renderer.item.ItemStackRenderState; import net.minecraft.core.component.DataComponents; import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.HumanoidArm; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.ItemStack; @@ -46,10 +48,7 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyArg; -import org.spongepowered.asm.mixin.injection.Slice; +import org.spongepowered.asm.mixin.injection.*; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @@ -82,6 +81,34 @@ private void hookFirstPersonShieldTint( original.call(instance, poseStack, submitNodeCollector, lightCoords, overlayCoords, outlineColor); } + @Inject( + method = "swingArm", + at = @At("HEAD"), + cancellable = true + ) + private void cancelVanillaSwing( + float attack, + PoseStack poseStack, + int invert, + HumanoidArm arm, + CallbackInfo ci + ) { + AbstractClientPlayer player = Minecraft.getInstance().player; + + if (player == null || !ModuleAnimations.INSTANCE.getRunning() || !SwingAnimations.INSTANCE.getEnabled() || ModuleSwordBlock.shouldAnimateSwordBlock(player)) { + return; + } + + SwingAnimations.INSTANCE.onRenderItem( + player, + InteractionHand.MAIN_HAND, + attack, + poseStack + ); + + ci.cancel(); + } + @Inject(method = "submitArmWithItem", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack;pushPose()V", shift = At.Shift.AFTER)) private void hookRenderFirstPersonItem( AbstractClientPlayer player, float frameInterp, float xRot, InteractionHand hand, float attack, ItemStack itemStack, float inverseArmHeight, PoseStack poseStack, SubmitNodeCollector submitNodeCollector, int lightCoords, CallbackInfo ci) { @@ -246,7 +273,6 @@ private int hookItemUseItem(int original, @Local(argsOnly = true, name = "player if (ModuleSwordBlock.shouldAnimateSwordBlock(player)) { return 7200; } - return original; } diff --git a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/render/MixinSwingAnimationRenderer.java b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/render/MixinSwingAnimationRenderer.java deleted file mode 100644 index 7b41f0e20e5..00000000000 --- a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/render/MixinSwingAnimationRenderer.java +++ /dev/null @@ -1,56 +0,0 @@ -package net.ccbluex.liquidbounce.injection.mixins.minecraft.render; - -import com.mojang.blaze3d.vertex.PoseStack; -import net.ccbluex.liquidbounce.features.module.modules.combat.ModuleSwordBlock; -import net.ccbluex.liquidbounce.features.module.modules.render.animations.ModuleAnimations; -import net.minecraft.client.player.AbstractClientPlayer; -import net.minecraft.client.renderer.ItemInHandRenderer; -import net.minecraft.client.renderer.SubmitNodeCollector; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.item.ItemDisplayContext; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.entity.HumanoidArm; -import net.minecraft.world.item.Items; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import static net.minecraft.world.item.Items.SHIELD; - -@Mixin(ItemInHandRenderer.class) -public abstract class MixinSwingAnimationRenderer { - - @Shadow - public abstract void renderItem(net.minecraft.world.entity.LivingEntity entity, ItemStack stack, ItemDisplayContext displayContext, PoseStack poseStack, SubmitNodeCollector nodeCollector, int packedLight); - - @Shadow - private ItemStack mainHandItem; - - @Inject( - method = "renderArmWithItem", - at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/ItemInHandRenderer;applyItemArmTransform(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/world/entity/HumanoidArm;F)V"), - cancellable = true - ) - private void onRenderArmWithItem(AbstractClientPlayer player, float partialTick, float pitch, InteractionHand hand, float swingProgress, ItemStack item, float equippedProgress, PoseStack poseStack, SubmitNodeCollector nodeCollector, int packedLight, CallbackInfo ci) { - if (ModuleAnimations.INSTANCE.getEnabled() && ModuleAnimations.INSTANCE.getSwingAnimation().getEnabled() && hand == InteractionHand.MAIN_HAND) { - if (!ModuleSwordBlock.shouldAnimateSwordBlock(player)) { - if (!player.isUsingItem() && player.getItemInHand(InteractionHand.MAIN_HAND).getItem() != SHIELD) { - - ModuleAnimations.INSTANCE.getSwingAnimation().onRenderItem(player, hand, swingProgress, equippedProgress, poseStack); - - boolean isMainHand = hand == InteractionHand.MAIN_HAND; - HumanoidArm arm = isMainHand ? player.getMainArm() : player.getMainArm().getOpposite(); - ItemDisplayContext context = (arm == HumanoidArm.RIGHT) ? ItemDisplayContext.FIRST_PERSON_RIGHT_HAND : ItemDisplayContext.FIRST_PERSON_LEFT_HAND; - - this.renderItem(player, item, context, poseStack, nodeCollector, packedLight); - - poseStack.popPose(); - ci.cancel(); - - } - } - } - } -} diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/SwingAnimations.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/SwingAnimations.kt index 560de8904d7..8db4cd4e705 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/SwingAnimations.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/animations/SwingAnimations.kt @@ -30,13 +30,12 @@ import net.minecraft.world.entity.HumanoidArm object SwingAnimations : ToggleableValueGroup(ModuleAnimations, "SwingAnimations", false) { - val mode by enumChoice("Mode", Mode.Fourteen) + val mode by enumChoice("Mode", Mode.Spin) enum class Mode(override val tag: String) : Tagged { - One("Jump"), Two("Swipe"), Three("Bounce"), Four("Tilt"), - Five("Pulse"), Six("Spin"), Seven("Hook"), Eight("Dash"), Nine("Tap"), - Ten("Inject"), Eleven("Slap"), Twelve("Akrien"), - Thirteen("Smooth"), Fourteen("Power"), Fifteen("Feast") + Swipe("Swipe"), Spin("Spin"), Hook("Hook"), Dash("Dash"), + Tap("Tap"), Inject("Inject"), Slap("Slap"), Akrien("Akrien"), + Smooth("Smooth"), Power("Power"), Feast("Feast") } private fun fSin(v: Float) = Mth.sin(v.toDouble()) @@ -46,19 +45,17 @@ object SwingAnimations : ToggleableValueGroup(ModuleAnimations, "SwingAnimations fun onRenderItem(player: AbstractClientPlayer, hand: InteractionHand, swingProgress: Float, - equipProgress: Float, poseStack: PoseStack ) { val isMainHand = hand == InteractionHand.MAIN_HAND val arm = if (isMainHand) player.mainArm else player.mainArm.opposite - applySwing(poseStack, swingProgress, equipProgress, arm) + applySwing(poseStack, swingProgress, arm) } @Suppress("LongMethod") private fun applySwing(poseStack: PoseStack, swing: Float, - equip: Float, arm: HumanoidArm ) { val i = if (arm == HumanoidArm.RIGHT) 1 else -1 @@ -70,62 +67,40 @@ object SwingAnimations : ToggleableValueGroup(ModuleAnimations, "SwingAnimations val sinSmooth = (fSin(swing * PI) * 0.5f) when (mode) { - Mode.One -> applyEquipOffset(poseStack, arm, 0.2f * fSin(fSqrt * PI * 2f)) - Mode.Two -> { - applyEquipOffset(poseStack, arm, n) + Mode.Swipe -> { poseStack.mulPose(Axis.YP.rotationDegrees(i * (45.0f + swing * -20.0f))) poseStack.mulPose(Axis.ZP.rotationDegrees(i * g * -70.0f)) poseStack.mulPose(Axis.XP.rotationDegrees(-70f)) poseStack.mulPose(Axis.YP.rotationDegrees(i * -45.0f)) } - Mode.Three -> { - applyEquipOffset(poseStack, arm, 0f) - if (swing > 0) poseStack.mulPose(Axis.XP.rotationDegrees(-fSin(swing * 13f) * 37f)) - } - Mode.Four -> { - applyEquipOffset(poseStack, arm, 0f) - poseStack.mulPose(Axis.ZP.rotationDegrees(i * g * -20.0f)) - } - Mode.Five -> { - applyEquipOffset(poseStack, arm, 0f) - val scale = -fSin(swing * 3f) / 2f + 1f - poseStack.scale(scale, scale, scale) - } - Mode.Six -> { - applyEquipOffset(poseStack, arm, 0f) + Mode.Spin -> { poseStack.mulPose(Axis.XP.rotationDegrees(swing * -360f)) } - Mode.Seven -> { - applyEquipOffset(poseStack, arm, 0f) + Mode.Hook -> { poseStack.mulPose(Axis.XP.rotationDegrees(50f)) poseStack.mulPose(Axis.YP.rotationDegrees(i * (-30f * (1f - g) - 30f))) poseStack.mulPose(Axis.ZP.rotationDegrees(i * 110f)) } - Mode.Eight -> { - applyEquipOffset(poseStack, arm, 0f) + Mode.Dash -> { poseStack.mulPose(Axis.XP.rotationDegrees(50f)) poseStack.mulPose(Axis.YP.rotationDegrees(i * (-60f * g - 50f))) poseStack.mulPose(Axis.ZP.rotationDegrees(i * 110f)) } - Mode.Nine -> { - applyEquipOffset(poseStack, arm, 0f) + Mode.Tap -> { poseStack.mulPose(Axis.XP.rotationDegrees(50f)) poseStack.mulPose(Axis.YP.rotationDegrees(i * -60f)) poseStack.mulPose(Axis.ZP.rotationDegrees(i * (110f + 20f * g))) } - Mode.Ten -> { - applyEquipOffset(poseStack, arm, 0f) + Mode.Inject -> { poseStack.translate(0.0, 0.0, (-g / 4.0)) poseStack.mulPose(Axis.XP.rotationDegrees(-120f)) } - Mode.Eleven -> { - applyEquipOffset(poseStack, arm, 0f) + Mode.Slap -> { poseStack.mulPose(Axis.XP.rotationDegrees(-fSin(swing * 3f) * 60f)) poseStack.mulPose(Axis.ZP.rotationDegrees(i * -60f * g)) } - Mode.Twelve -> { + Mode.Akrien -> { if (swing > 0) { - poseStack.translate(i * 0.56, (equip * -0.2f) - 0.5, -0.7) poseStack.mulPose(Axis.YP.rotationDegrees(i * 45f)) poseStack.mulPose(Axis.XP.rotationDegrees(g * -85.0f)) poseStack.translate(i * -0.1, 0.28, 0.2) @@ -134,13 +109,11 @@ object SwingAnimations : ToggleableValueGroup(ModuleAnimations, "SwingAnimations val m = 0.2f * fSin(fSqrt * PI * 2f) val f2 = -0.2f * fSin(swing * PI) poseStack.translate(i * n.toDouble(), m.toDouble(), f2.toDouble()) - applyEquipOffset(poseStack, arm, 0f) applySwingOffset(poseStack, arm, swing) } } - Mode.Thirteen -> { - poseStack.translate(i * 0.56, -0.42, -0.72) + Mode.Smooth -> { poseStack.mulPose(Axis.YP.rotationDegrees(i * (45.0f + sin1 * -20.0f))) poseStack.mulPose(Axis.ZP.rotationDegrees(i * sin2 * -20.0f)) poseStack.mulPose(Axis.XP.rotationDegrees(sin2 * -80.0f)) @@ -148,8 +121,7 @@ object SwingAnimations : ToggleableValueGroup(ModuleAnimations, "SwingAnimations poseStack.translate(0.0, -0.1, 0.0) } - Mode.Fourteen -> { - poseStack.translate(i * 0.56, -0.32, -0.72) + Mode.Power -> { poseStack.translate((-sinSmooth * sinSmooth * sin1 * i).toDouble(), 0.0, 0.0) poseStack.mulPose(Axis.YP.rotationDegrees(i * 61f)) poseStack.mulPose(Axis.ZP.rotationDegrees(sin2)) @@ -159,8 +131,7 @@ object SwingAnimations : ToggleableValueGroup(ModuleAnimations, "SwingAnimations poseStack.mulPose(Axis.XP.rotationDegrees(sinSmooth * -60.0f)) } - Mode.Fifteen -> { - poseStack.translate(i * 0.56, -0.32, -0.72) + Mode.Feast -> { poseStack.mulPose(Axis.YP.rotationDegrees(i * 30f)) poseStack.mulPose(Axis.YP.rotationDegrees(sin2 * 75.0f * i)) poseStack.mulPose(Axis.XP.rotationDegrees(sin2 * -45.0f)) @@ -171,11 +142,6 @@ object SwingAnimations : ToggleableValueGroup(ModuleAnimations, "SwingAnimations } } - private fun applyEquipOffset(poseStack: PoseStack, arm: HumanoidArm, equip: Float) { - val i = if (arm == HumanoidArm.RIGHT) 1 else -1 - poseStack.translate(i * 0.56, -0.52 + equip * -0.6, -0.72) - } - private fun applySwingOffset(poseStack: PoseStack, arm: HumanoidArm, swing: Float) { val i = if (arm == HumanoidArm.RIGHT) 1 else -1 val f1 = fSin(swing * swing * PI) diff --git a/src/main/resources/liquidbounce.mixins.json b/src/main/resources/liquidbounce.mixins.json index 7e09c5e1198..4c7a34feef9 100644 --- a/src/main/resources/liquidbounce.mixins.json +++ b/src/main/resources/liquidbounce.mixins.json @@ -146,7 +146,6 @@ "minecraft.render.fog.MixinBlindnessFogEnvironment", "minecraft.render.fog.MixinFogRenderer", "minecraft.render.special.MixinShieldSpecialRenderer", - "minecraft.render.MixinSwingAnimationRenderer", "minecraft.text.MixinGuiMessage", "minecraft.text.MixinGuiMessageLineVisible", "minecraft.text.MixinMutableComponent",