From 272e113bce6830ebc0abe09b1046a8c5add2c4c0 Mon Sep 17 00:00:00 2001 From: Hubert Kuliniak <48128694+SfenKer@users.noreply.github.com> Date: Sun, 22 Mar 2026 19:08:26 +0100 Subject: [PATCH 1/2] swing animation customization --- .../config/SmallViewModelConfig.java | 22 ++++++++ .../mixin/MixinItemInHandRenderer.java | 14 +++++ .../mixin/MixinLocalPlayer.java | 56 +++++++++++++++++++ .../assets/smallviewmodel/lang/en_us.json | 4 +- src/main/resources/smallviewmodel.mixins.json | 3 +- 5 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 src/main/java/wales/cosmic/smallviewmodel/mixin/MixinLocalPlayer.java diff --git a/src/main/java/wales/cosmic/smallviewmodel/config/SmallViewModelConfig.java b/src/main/java/wales/cosmic/smallviewmodel/config/SmallViewModelConfig.java index 7ef07f0..d17f3fa 100644 --- a/src/main/java/wales/cosmic/smallviewmodel/config/SmallViewModelConfig.java +++ b/src/main/java/wales/cosmic/smallviewmodel/config/SmallViewModelConfig.java @@ -8,6 +8,7 @@ import com.moulberry.lattice.annotation.LatticeOption; import com.moulberry.lattice.annotation.constraint.LatticeDisableIf; import com.moulberry.lattice.annotation.constraint.LatticeFloatRange; +import com.moulberry.lattice.annotation.constraint.LatticeIntRange; import com.moulberry.lattice.annotation.widget.LatticeWidgetButton; import com.moulberry.lattice.annotation.widget.LatticeWidgetSlider; import net.fabricmc.loader.api.FabricLoader; @@ -33,6 +34,9 @@ public class SmallViewModelConfig { @LatticeCategory(name = "smallviewmodel.arm") public Arm arm = new Arm(); + @LatticeCategory(name = "smallviewmodel.swing_animation") + public Swing swing = new Swing(); + public static class MainHand { @LatticeCategory(name = "smallviewmodel.position") @@ -164,6 +168,24 @@ private boolean checkDisabled() { } } + public static class Swing { + + @LatticeOption(title = "smallviewmodel.swing.duration") + @LatticeDisableIf(function = "checkDisabled", frequency = LatticeDynamicFrequency.EVERY_TICK) + @LatticeIntRange(min = 1, max = 20, clampMin = 1, clampMax = 20) + @LatticeWidgetSlider + public int swingDuration = 6; + + @LatticeOption(title = "smallviewmodel.enabled") + @LatticeWidgetButton + public boolean enabled = true; + + private boolean checkDisabled() { + return !this.enabled; + } + + } + public static SmallViewModelConfig get() { if (INSTANCE == null) { load(); diff --git a/src/main/java/wales/cosmic/smallviewmodel/mixin/MixinItemInHandRenderer.java b/src/main/java/wales/cosmic/smallviewmodel/mixin/MixinItemInHandRenderer.java index a6371cb..b354bf8 100644 --- a/src/main/java/wales/cosmic/smallviewmodel/mixin/MixinItemInHandRenderer.java +++ b/src/main/java/wales/cosmic/smallviewmodel/mixin/MixinItemInHandRenderer.java @@ -1,5 +1,6 @@ package wales.cosmic.smallviewmodel.mixin; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; import net.minecraft.client.player.AbstractClientPlayer; @@ -73,4 +74,17 @@ private void applyConfig(PoseStack poseStack, SmallViewModelConfig.Rotation rota } } + @ModifyExpressionValue( + method = "tick", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/player/LocalPlayer;getItemSwapScale(F)F" + ) + ) + public float smallviewmodel$tick( + float original + ) { + return 1f; + } + } \ No newline at end of file diff --git a/src/main/java/wales/cosmic/smallviewmodel/mixin/MixinLocalPlayer.java b/src/main/java/wales/cosmic/smallviewmodel/mixin/MixinLocalPlayer.java new file mode 100644 index 0000000..9d30662 --- /dev/null +++ b/src/main/java/wales/cosmic/smallviewmodel/mixin/MixinLocalPlayer.java @@ -0,0 +1,56 @@ +package wales.cosmic.smallviewmodel.mixin; + +import com.mojang.authlib.GameProfile; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.player.AbstractClientPlayer; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.world.InteractionHand; +import org.spongepowered.asm.mixin.Mixin; +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.callback.CallbackInfo; +import wales.cosmic.smallviewmodel.config.SmallViewModelConfig; + +@Mixin(LocalPlayer.class) +public class MixinLocalPlayer extends AbstractClientPlayer { + + @Unique + private int smallviewmodel$animTicks; + + public MixinLocalPlayer(ClientLevel $0, GameProfile $1) { + super($0, $1); + } + + @Inject(method = "aiStep", at = @At("TAIL")) + public void smallviewmodel$animTicks$aiStep(CallbackInfo callbackInfo) { + + final var config = SmallViewModelConfig.get(); + + if (this.smallviewmodel$animTicks > config.swing.swingDuration) { + this.smallviewmodel$animTicks = 0; + } + if (this.smallviewmodel$animTicks == 0) { + this.attackAnim = 1f; + } else { + this.attackAnim = (this.smallviewmodel$animTicks - 1f) / config.swing.swingDuration; + this.smallviewmodel$animTicks++; + } + + } + + @Inject(method = "swing(Lnet/minecraft/world/InteractionHand;)V", at = @At("HEAD")) + public void smallviewmodel$swing( + InteractionHand hand, + CallbackInfo callbackInfo + ) { + final var config = SmallViewModelConfig.get(); + if (!config.swing.enabled) { + return; + } + if (this.smallviewmodel$animTicks == 0) { + this.smallviewmodel$animTicks = 1; + } + } + +} diff --git a/src/main/resources/assets/smallviewmodel/lang/en_us.json b/src/main/resources/assets/smallviewmodel/lang/en_us.json index 9ef433a..1412716 100644 --- a/src/main/resources/assets/smallviewmodel/lang/en_us.json +++ b/src/main/resources/assets/smallviewmodel/lang/en_us.json @@ -15,5 +15,7 @@ "smallviewmodel.scale": "Scale", "smallviewmodel.scale.x": "X Scale", "smallviewmodel.scale.y": "Y Scale", - "smallviewmodel.scale.z": "Z Scale" + "smallviewmodel.scale.z": "Z Scale", + "smallviewmodel.swing_animation": "Swing Animation Settings", + "smallviewmodel.swing.duration": "Animation Duration" } \ No newline at end of file diff --git a/src/main/resources/smallviewmodel.mixins.json b/src/main/resources/smallviewmodel.mixins.json index 1a99519..d156f6a 100644 --- a/src/main/resources/smallviewmodel.mixins.json +++ b/src/main/resources/smallviewmodel.mixins.json @@ -4,10 +4,9 @@ "package": "wales.cosmic.smallviewmodel.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ + "MixinLocalPlayer", "MixinItemInHandRenderer" ], - "client": [ - ], "injectors": { "defaultRequire": 1 } From b6f538d280defdbe5a9c5121fc6cc703c408c86f Mon Sep 17 00:00:00 2001 From: Hubert Kuliniak <48128694+SfenKer@users.noreply.github.com> Date: Sun, 22 Mar 2026 19:30:07 +0100 Subject: [PATCH 2/2] fixes --- .../mixin/MixinLocalPlayer.java | 55 ++++--------------- 1 file changed, 12 insertions(+), 43 deletions(-) diff --git a/src/main/java/wales/cosmic/smallviewmodel/mixin/MixinLocalPlayer.java b/src/main/java/wales/cosmic/smallviewmodel/mixin/MixinLocalPlayer.java index 9d30662..51aead2 100644 --- a/src/main/java/wales/cosmic/smallviewmodel/mixin/MixinLocalPlayer.java +++ b/src/main/java/wales/cosmic/smallviewmodel/mixin/MixinLocalPlayer.java @@ -1,55 +1,24 @@ package wales.cosmic.smallviewmodel.mixin; -import com.mojang.authlib.GameProfile; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.player.AbstractClientPlayer; -import net.minecraft.client.player.LocalPlayer; -import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.LivingEntity; import org.spongepowered.asm.mixin.Mixin; -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.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import wales.cosmic.smallviewmodel.config.SmallViewModelConfig; -@Mixin(LocalPlayer.class) -public class MixinLocalPlayer extends AbstractClientPlayer { +@Mixin(LivingEntity.class) +public class MixinLocalPlayer { - @Unique - private int smallviewmodel$animTicks; - - public MixinLocalPlayer(ClientLevel $0, GameProfile $1) { - super($0, $1); - } - - @Inject(method = "aiStep", at = @At("TAIL")) - public void smallviewmodel$animTicks$aiStep(CallbackInfo callbackInfo) { - - final var config = SmallViewModelConfig.get(); - - if (this.smallviewmodel$animTicks > config.swing.swingDuration) { - this.smallviewmodel$animTicks = 0; - } - if (this.smallviewmodel$animTicks == 0) { - this.attackAnim = 1f; - } else { - this.attackAnim = (this.smallviewmodel$animTicks - 1f) / config.swing.swingDuration; - this.smallviewmodel$animTicks++; - } - - } - - @Inject(method = "swing(Lnet/minecraft/world/InteractionHand;)V", at = @At("HEAD")) - public void smallviewmodel$swing( - InteractionHand hand, - CallbackInfo callbackInfo - ) { + @Inject( + method = "getCurrentSwingDuration", + at = @At("HEAD"), + cancellable = true + ) + private void smallviewmodel$getCurrentSwingDuration(CallbackInfoReturnable cir) { final var config = SmallViewModelConfig.get(); - if (!config.swing.enabled) { - return; - } - if (this.smallviewmodel$animTicks == 0) { - this.smallviewmodel$animTicks = 1; + if (config.swing.enabled) { + cir.setReturnValue(config.swing.swingDuration); } }