Skip to content

Commit 1811bf1

Browse files
beanbag44emyfops
andauthored
Feature: ViewModel module (#128)
This module adds a way to modify the vanilla rendering of held items. You can do / adjust: - scale - position - rotation - field of view - constant swing progress - disable / enable hand rendering adjustments - split changes between both hands - modify which hand is swinging - use old minecraft swing animations - remove the bobbing effect when switching items - remove the delay between swinging animations There is one todo left that i want to achieve at some point but doesn't seem worth it at the moment. Its possible to remove the shadows from the rendered items however i haven't figured out how to implement that yet. --------- Co-authored-by: Edouard127 <46357922+Edouard127@users.noreply.github.com>
1 parent 7903f33 commit 1811bf1

File tree

6 files changed

+367
-12
lines changed

6 files changed

+367
-12
lines changed

common/src/main/java/com/lambda/mixin/entity/ClientPlayerEntityMixin.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@
2525
import com.lambda.interaction.PlayerPacketManager;
2626
import com.lambda.interaction.request.rotation.RotationManager;
2727
import com.lambda.module.modules.player.PortalGui;
28+
import com.lambda.module.modules.render.ViewModel;
2829
import net.minecraft.client.MinecraftClient;
29-
import net.minecraft.client.gui.screen.DeathScreen;
3030
import net.minecraft.client.gui.screen.Screen;
31-
import net.minecraft.client.gui.screen.ingame.HandledScreen;
3231
import net.minecraft.client.input.Input;
32+
import net.minecraft.client.network.AbstractClientPlayerEntity;
3333
import net.minecraft.client.network.ClientPlayerEntity;
3434
import net.minecraft.entity.MovementType;
3535
import net.minecraft.entity.damage.DamageSource;
@@ -154,6 +154,18 @@ void onSwingHandPre(Hand hand, CallbackInfo ci) {
154154
if (EventFlow.post(new PlayerEvent.SwingHand(hand)).isCanceled()) ci.cancel();
155155
}
156156

157+
@Redirect(method = "swingHand", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/AbstractClientPlayerEntity;swingHand(Lnet/minecraft/util/Hand;)V"))
158+
private void adjustSwing(AbstractClientPlayerEntity instance, Hand hand) {
159+
ViewModel viewModel = ViewModel.INSTANCE;
160+
161+
if (!viewModel.isEnabled()) {
162+
instance.swingHand(hand, false);
163+
return;
164+
}
165+
166+
viewModel.adjustSwing(hand, instance);
167+
}
168+
157169
@Inject(method = "damage", at = @At("HEAD"), cancellable = true)
158170
public void damage(DamageSource source, float amount, CallbackInfoReturnable<Boolean> cir) {
159171
if (EventFlow.post(new PlayerEvent.Damage(source, amount)).isCanceled()) cir.setReturnValue(false);

common/src/main/java/com/lambda/mixin/entity/LivingEntityMixin.java

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,14 @@
2121
import com.lambda.event.EventFlow;
2222
import com.lambda.event.events.MovementEvent;
2323
import com.lambda.interaction.request.rotation.RotationManager;
24+
import com.lambda.module.modules.render.ViewModel;
2425
import net.minecraft.entity.LivingEntity;
2526
import net.minecraft.util.math.MathHelper;
2627
import net.minecraft.util.math.Vec3d;
2728
import org.spongepowered.asm.mixin.Mixin;
2829
import org.spongepowered.asm.mixin.Shadow;
29-
import org.spongepowered.asm.mixin.injection.At;
30-
import org.spongepowered.asm.mixin.injection.Inject;
31-
import org.spongepowered.asm.mixin.injection.Redirect;
32-
import org.spongepowered.asm.mixin.injection.Slice;
30+
import org.spongepowered.asm.mixin.Unique;
31+
import org.spongepowered.asm.mixin.injection.*;
3332
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
3433

3534
@Mixin(LivingEntity.class)
@@ -38,6 +37,9 @@ public abstract class LivingEntityMixin extends EntityMixin {
3837
@Shadow
3938
protected abstract float getJumpVelocity();
4039

40+
@Unique
41+
private final LivingEntity lambda$instance = (LivingEntity) (Object) this;
42+
4143
/**
4244
* Overwrites the jump function to use our rotation and movements
4345
* <pre>{@code
@@ -55,7 +57,7 @@ public abstract class LivingEntityMixin extends EntityMixin {
5557
*/
5658
@Inject(method = "jump", at = @At("HEAD"), cancellable = true)
5759
void onJump(CallbackInfo ci) {
58-
LivingEntity self = (LivingEntity) (Object) this;
60+
LivingEntity self = lambda$instance;
5961
if (self != Lambda.getMc().player) return;
6062
ci.cancel();
6163

@@ -78,15 +80,14 @@ void onJump(CallbackInfo ci) {
7880

7981
@Inject(method = "travel", at = @At("HEAD"), cancellable = true)
8082
void onTravelPre(Vec3d movementInput, CallbackInfo ci) {
81-
LivingEntity entity = (LivingEntity) (Object) this;
82-
if (EventFlow.post(new MovementEvent.Entity.Pre(entity, movementInput)).isCanceled()) {
83+
if (EventFlow.post(new MovementEvent.Entity.Pre(lambda$instance, movementInput)).isCanceled()) {
8384
ci.cancel();
8485
}
8586
}
8687

8788
@Inject(method = "travel", at = @At("TAIL"))
8889
void onTravelPost(Vec3d movementInput, CallbackInfo ci) {
89-
EventFlow.post(new MovementEvent.Entity.Post((LivingEntity) (Object) this, movementInput));
90+
EventFlow.post(new MovementEvent.Entity.Post(lambda$instance, movementInput));
9091
}
9192

9293
/**
@@ -123,7 +124,7 @@ private float hookModifyFallFlyingPitch(LivingEntity entity) {
123124
*/
124125
@Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;getYaw()F"), slice = @Slice(to = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;getYaw()F", ordinal = 1)))
125126
private float rotBody(LivingEntity entity) {
126-
if ((Object) this != Lambda.getMc().player) {
127+
if (lambda$instance != Lambda.getMc().player) {
127128
return entity.getYaw();
128129
}
129130

@@ -154,11 +155,18 @@ private float rotBody(LivingEntity entity) {
154155
*/
155156
@Redirect(method = "turnHead", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;getYaw()F"))
156157
private float rotHead(LivingEntity entity) {
157-
if ((Object) this != Lambda.getMc().player) {
158+
if (lambda$instance != Lambda.getMc().player) {
158159
return entity.getYaw();
159160
}
160161

161162
Float yaw = RotationManager.getRenderYaw();
162163
return (yaw == null) ? entity.getYaw() : yaw;
163164
}
165+
166+
@ModifyConstant(method = "getHandSwingDuration", constant = @Constant(intValue = 6))
167+
private int getHandSwingDuration(int constant) {
168+
if (lambda$instance != Lambda.getMc().player || ViewModel.INSTANCE.isDisabled()) return constant;
169+
170+
return ViewModel.INSTANCE.getSwingDuration();
171+
}
164172
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package com.lambda.mixin.render;
2+
3+
import com.google.common.base.MoreObjects;
4+
import com.lambda.Lambda;
5+
import com.lambda.module.modules.render.ViewModel;
6+
import net.minecraft.client.MinecraftClient;
7+
import net.minecraft.client.network.AbstractClientPlayerEntity;
8+
import net.minecraft.client.render.VertexConsumerProvider;
9+
import net.minecraft.client.render.item.HeldItemRenderer;
10+
import net.minecraft.client.util.math.MatrixStack;
11+
import net.minecraft.item.ItemStack;
12+
import net.minecraft.util.Hand;
13+
import org.spongepowered.asm.mixin.Final;
14+
import org.spongepowered.asm.mixin.Mixin;
15+
import org.spongepowered.asm.mixin.Shadow;
16+
import org.spongepowered.asm.mixin.injection.At;
17+
import org.spongepowered.asm.mixin.injection.Inject;
18+
import org.spongepowered.asm.mixin.injection.ModifyArg;
19+
import org.spongepowered.asm.mixin.injection.ModifyVariable;
20+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
21+
22+
@Mixin(HeldItemRenderer.class)
23+
public class HeldItemRendererMixin {
24+
@Final @Shadow private MinecraftClient client;
25+
@Shadow private ItemStack mainHand;
26+
@Shadow private ItemStack offHand;
27+
@Shadow private float equipProgressMainHand;
28+
@Shadow private float equipProgressOffHand;
29+
30+
@Inject(method = "renderFirstPersonItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/item/HeldItemRenderer;renderArmHoldingItem(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;IFFLnet/minecraft/util/Arm;)V"))
31+
private void onRenderArmHoldingItem(AbstractClientPlayerEntity player, float tickDelta, float pitch, Hand hand, float swingProgress, ItemStack itemStack, float equipProgress, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, CallbackInfo ci) {
32+
if (!ViewModel.INSTANCE.isEnabled()) return;
33+
34+
ViewModel.INSTANCE.transform(itemStack, hand, matrices);
35+
}
36+
37+
@Inject(method = "renderFirstPersonItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/item/HeldItemRenderer;renderItem(Lnet/minecraft/entity/LivingEntity;Lnet/minecraft/item/ItemStack;Lnet/minecraft/client/render/model/json/ModelTransformationMode;ZLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V"))
38+
private void onRenderFirstPersonItem(AbstractClientPlayerEntity player, float tickDelta, float pitch, Hand hand, float swingProgress, ItemStack itemStack, float equipProgress, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, CallbackInfo ci) {
39+
if (!ViewModel.INSTANCE.isEnabled()) return;
40+
41+
ViewModel.INSTANCE.transform(itemStack, hand, matrices);
42+
}
43+
44+
@ModifyArg(method = "updateHeldItems", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/MathHelper;clamp(FFF)F", ordinal = 2), index = 0)
45+
private float modifyEquipProgressMainHand(float value) {
46+
if (client.player == null || ViewModel.INSTANCE.isDisabled()) return value;
47+
48+
ViewModel config = ViewModel.INSTANCE;
49+
ItemStack currentStack = client.player.getMainHandStack();
50+
if (config.getOldAnimations() && !config.getSwapAnimation()) {
51+
mainHand = currentStack;
52+
}
53+
54+
float progress = config.getOldAnimations() ? 1 : (float) Math.pow(client.player.getAttackCooldownProgress(1), 3);
55+
56+
return (ItemStack.areEqual(mainHand, currentStack) ? progress : 0) - equipProgressMainHand;
57+
}
58+
59+
@ModifyArg(method = "updateHeldItems", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/MathHelper;clamp(FFF)F", ordinal = 3), index = 0)
60+
private float modifyEquipProgressOffHand(float value) {
61+
if (client.player == null || ViewModel.INSTANCE.isDisabled()) return value;
62+
63+
ViewModel config = ViewModel.INSTANCE;
64+
65+
ItemStack currentStack = client.player.getOffHandStack();
66+
if (config.getOldAnimations() && !config.getSwapAnimation()) {
67+
offHand = currentStack;
68+
}
69+
70+
return (ItemStack.areEqual(offHand, currentStack) ? 1 : 0) - equipProgressOffHand;
71+
}
72+
73+
@ModifyVariable(method = "renderItem(FLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider$Immediate;Lnet/minecraft/client/network/ClientPlayerEntity;I)V", at = @At(value = "STORE", ordinal = 0), index = 6)
74+
private float modifySwing(float swingProgress) {
75+
ViewModel config = ViewModel.INSTANCE;
76+
MinecraftClient mc = Lambda.getMc();
77+
if (config.isDisabled() || mc.player == null) return swingProgress;
78+
Hand hand = MoreObjects.firstNonNull(mc.player.preferredHand, Hand.MAIN_HAND);
79+
80+
if (hand == Hand.MAIN_HAND) {
81+
return swingProgress + config.getMainSwingProgress();
82+
} else if (hand == Hand.OFF_HAND) {
83+
return swingProgress + config.getOffhandSwingProgress();
84+
}
85+
86+
return swingProgress;
87+
}
88+
}

0 commit comments

Comments
 (0)