full card structure in place, card binder working.
Some checks failed
Build / build (push) Has been cancelled

This commit is contained in:
trunksbomb
2026-03-23 05:18:20 -04:00
parent 44ebb792ea
commit 4cd60e4fac
167 changed files with 3345 additions and 77 deletions

View File

@@ -0,0 +1,626 @@
package net.minecraft.client.renderer;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.MoreObjects;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import com.mojang.math.Axis;
import net.minecraft.client.Minecraft;
import net.minecraft.client.player.AbstractClientPlayer;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
import net.minecraft.client.renderer.entity.ItemRenderer;
import net.minecraft.client.renderer.entity.player.PlayerRenderer;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.core.component.DataComponents;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.HumanoidArm;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.CrossbowItem;
import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.MapItem;
import net.minecraft.world.level.saveddata.maps.MapId;
import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import org.joml.Matrix4f;
@OnlyIn(Dist.CLIENT)
public class ItemInHandRenderer {
private static final RenderType MAP_BACKGROUND = RenderType.text(ResourceLocation.withDefaultNamespace("textures/map/map_background.png"));
private static final RenderType MAP_BACKGROUND_CHECKERBOARD = RenderType.text(
ResourceLocation.withDefaultNamespace("textures/map/map_background_checkerboard.png")
);
private static final float ITEM_SWING_X_POS_SCALE = -0.4F;
private static final float ITEM_SWING_Y_POS_SCALE = 0.2F;
private static final float ITEM_SWING_Z_POS_SCALE = -0.2F;
private static final float ITEM_HEIGHT_SCALE = -0.6F;
private static final float ITEM_POS_X = 0.56F;
private static final float ITEM_POS_Y = -0.52F;
private static final float ITEM_POS_Z = -0.72F;
private static final float ITEM_PRESWING_ROT_Y = 45.0F;
private static final float ITEM_SWING_X_ROT_AMOUNT = -80.0F;
private static final float ITEM_SWING_Y_ROT_AMOUNT = -20.0F;
private static final float ITEM_SWING_Z_ROT_AMOUNT = -20.0F;
private static final float EAT_JIGGLE_X_ROT_AMOUNT = 10.0F;
private static final float EAT_JIGGLE_Y_ROT_AMOUNT = 90.0F;
private static final float EAT_JIGGLE_Z_ROT_AMOUNT = 30.0F;
private static final float EAT_JIGGLE_X_POS_SCALE = 0.6F;
private static final float EAT_JIGGLE_Y_POS_SCALE = -0.5F;
private static final float EAT_JIGGLE_Z_POS_SCALE = 0.0F;
private static final double EAT_JIGGLE_EXPONENT = 27.0;
private static final float EAT_EXTRA_JIGGLE_CUTOFF = 0.8F;
private static final float EAT_EXTRA_JIGGLE_SCALE = 0.1F;
private static final float ARM_SWING_X_POS_SCALE = -0.3F;
private static final float ARM_SWING_Y_POS_SCALE = 0.4F;
private static final float ARM_SWING_Z_POS_SCALE = -0.4F;
private static final float ARM_SWING_Y_ROT_AMOUNT = 70.0F;
private static final float ARM_SWING_Z_ROT_AMOUNT = -20.0F;
private static final float ARM_HEIGHT_SCALE = -0.6F;
private static final float ARM_POS_SCALE = 0.8F;
private static final float ARM_POS_X = 0.8F;
private static final float ARM_POS_Y = -0.75F;
private static final float ARM_POS_Z = -0.9F;
private static final float ARM_PRESWING_ROT_Y = 45.0F;
private static final float ARM_PREROTATION_X_OFFSET = -1.0F;
private static final float ARM_PREROTATION_Y_OFFSET = 3.6F;
private static final float ARM_PREROTATION_Z_OFFSET = 3.5F;
private static final float ARM_POSTROTATION_X_OFFSET = 5.6F;
private static final int ARM_ROT_X = 200;
private static final int ARM_ROT_Y = -135;
private static final int ARM_ROT_Z = 120;
private static final float MAP_SWING_X_POS_SCALE = -0.4F;
private static final float MAP_SWING_Z_POS_SCALE = -0.2F;
private static final float MAP_HANDS_POS_X = 0.0F;
private static final float MAP_HANDS_POS_Y = 0.04F;
private static final float MAP_HANDS_POS_Z = -0.72F;
private static final float MAP_HANDS_HEIGHT_SCALE = -1.2F;
private static final float MAP_HANDS_TILT_SCALE = -0.5F;
private static final float MAP_PLAYER_PITCH_SCALE = 45.0F;
private static final float MAP_HANDS_Z_ROT_AMOUNT = -85.0F;
private static final float MAPHAND_X_ROT_AMOUNT = 45.0F;
private static final float MAPHAND_Y_ROT_AMOUNT = 92.0F;
private static final float MAPHAND_Z_ROT_AMOUNT = -41.0F;
private static final float MAP_HAND_X_POS = 0.3F;
private static final float MAP_HAND_Y_POS = -1.1F;
private static final float MAP_HAND_Z_POS = 0.45F;
private static final float MAP_SWING_X_ROT_AMOUNT = 20.0F;
private static final float MAP_PRE_ROT_SCALE = 0.38F;
private static final float MAP_GLOBAL_X_POS = -0.5F;
private static final float MAP_GLOBAL_Y_POS = -0.5F;
private static final float MAP_GLOBAL_Z_POS = 0.0F;
private static final float MAP_FINAL_SCALE = 0.0078125F;
private static final int MAP_BORDER = 7;
private static final int MAP_HEIGHT = 128;
private static final int MAP_WIDTH = 128;
private static final float BOW_CHARGE_X_POS_SCALE = 0.0F;
private static final float BOW_CHARGE_Y_POS_SCALE = 0.0F;
private static final float BOW_CHARGE_Z_POS_SCALE = 0.04F;
private static final float BOW_CHARGE_SHAKE_X_SCALE = 0.0F;
private static final float BOW_CHARGE_SHAKE_Y_SCALE = 0.004F;
private static final float BOW_CHARGE_SHAKE_Z_SCALE = 0.0F;
private static final float BOW_CHARGE_Z_SCALE = 0.2F;
private static final float BOW_MIN_SHAKE_CHARGE = 0.1F;
private final Minecraft minecraft;
private ItemStack mainHandItem = ItemStack.EMPTY;
private ItemStack offHandItem = ItemStack.EMPTY;
private float mainHandHeight;
private float oMainHandHeight;
private float offHandHeight;
private float oOffHandHeight;
private final EntityRenderDispatcher entityRenderDispatcher;
private final ItemRenderer itemRenderer;
public ItemInHandRenderer(Minecraft minecraft, EntityRenderDispatcher entityRenderDispatcher, ItemRenderer itemRenderer) {
this.minecraft = minecraft;
this.entityRenderDispatcher = entityRenderDispatcher;
this.itemRenderer = itemRenderer;
}
public void renderItem(
LivingEntity entity,
ItemStack itemStack,
ItemDisplayContext displayContext,
boolean leftHand,
PoseStack poseStack,
MultiBufferSource buffer,
int seed
) {
if (!itemStack.isEmpty()) {
this.itemRenderer
.renderStatic(
entity,
itemStack,
displayContext,
leftHand,
poseStack,
buffer,
entity.level(),
seed,
OverlayTexture.NO_OVERLAY,
entity.getId() + displayContext.ordinal()
);
}
}
/**
* Return the angle to render the Map
*/
private float calculateMapTilt(float pitch) {
float f = 1.0F - pitch / 45.0F + 0.1F;
f = Mth.clamp(f, 0.0F, 1.0F);
return -Mth.cos(f * (float) Math.PI) * 0.5F + 0.5F;
}
private void renderMapHand(PoseStack poseStack, MultiBufferSource buffer, int packedLight, HumanoidArm side) {
PlayerRenderer playerrenderer = (PlayerRenderer)this.entityRenderDispatcher.<AbstractClientPlayer>getRenderer(this.minecraft.player);
poseStack.pushPose();
float f = side == HumanoidArm.RIGHT ? 1.0F : -1.0F;
poseStack.mulPose(Axis.YP.rotationDegrees(92.0F));
poseStack.mulPose(Axis.XP.rotationDegrees(45.0F));
poseStack.mulPose(Axis.ZP.rotationDegrees(f * -41.0F));
poseStack.translate(f * 0.3F, -1.1F, 0.45F);
if (side == HumanoidArm.RIGHT) {
playerrenderer.renderRightHand(poseStack, buffer, packedLight, this.minecraft.player);
} else {
playerrenderer.renderLeftHand(poseStack, buffer, packedLight, this.minecraft.player);
}
poseStack.popPose();
}
private void renderOneHandedMap(
PoseStack poseStack, MultiBufferSource buffer, int packedLight, float equippedProgress, HumanoidArm hand, float swingProgress, ItemStack stack
) {
float f = hand == HumanoidArm.RIGHT ? 1.0F : -1.0F;
poseStack.translate(f * 0.125F, -0.125F, 0.0F);
if (!this.minecraft.player.isInvisible()) {
poseStack.pushPose();
poseStack.mulPose(Axis.ZP.rotationDegrees(f * 10.0F));
this.renderPlayerArm(poseStack, buffer, packedLight, equippedProgress, swingProgress, hand);
poseStack.popPose();
}
poseStack.pushPose();
poseStack.translate(f * 0.51F, -0.08F + equippedProgress * -1.2F, -0.75F);
float f1 = Mth.sqrt(swingProgress);
float f2 = Mth.sin(f1 * (float) Math.PI);
float f3 = -0.5F * f2;
float f4 = 0.4F * Mth.sin(f1 * (float) (Math.PI * 2));
float f5 = -0.3F * Mth.sin(swingProgress * (float) Math.PI);
poseStack.translate(f * f3, f4 - 0.3F * f2, f5);
poseStack.mulPose(Axis.XP.rotationDegrees(f2 * -45.0F));
poseStack.mulPose(Axis.YP.rotationDegrees(f * f2 * -30.0F));
this.renderMap(poseStack, buffer, packedLight, stack);
poseStack.popPose();
}
private void renderTwoHandedMap(PoseStack poseStack, MultiBufferSource buffer, int packedLight, float pitch, float equippedProgress, float swingProgress) {
float f = Mth.sqrt(swingProgress);
float f1 = -0.2F * Mth.sin(swingProgress * (float) Math.PI);
float f2 = -0.4F * Mth.sin(f * (float) Math.PI);
poseStack.translate(0.0F, -f1 / 2.0F, f2);
float f3 = this.calculateMapTilt(pitch);
poseStack.translate(0.0F, 0.04F + equippedProgress * -1.2F + f3 * -0.5F, -0.72F);
poseStack.mulPose(Axis.XP.rotationDegrees(f3 * -85.0F));
if (!this.minecraft.player.isInvisible()) {
poseStack.pushPose();
poseStack.mulPose(Axis.YP.rotationDegrees(90.0F));
this.renderMapHand(poseStack, buffer, packedLight, HumanoidArm.RIGHT);
this.renderMapHand(poseStack, buffer, packedLight, HumanoidArm.LEFT);
poseStack.popPose();
}
float f4 = Mth.sin(f * (float) Math.PI);
poseStack.mulPose(Axis.XP.rotationDegrees(f4 * 20.0F));
poseStack.scale(2.0F, 2.0F, 2.0F);
this.renderMap(poseStack, buffer, packedLight, this.mainHandItem);
}
private void renderMap(PoseStack poseStack, MultiBufferSource buffer, int packedLight, ItemStack stack) {
poseStack.mulPose(Axis.YP.rotationDegrees(180.0F));
poseStack.mulPose(Axis.ZP.rotationDegrees(180.0F));
poseStack.scale(0.38F, 0.38F, 0.38F);
poseStack.translate(-0.5F, -0.5F, 0.0F);
poseStack.scale(0.0078125F, 0.0078125F, 0.0078125F);
MapId mapid = stack.get(DataComponents.MAP_ID);
MapItemSavedData mapitemsaveddata = MapItem.getSavedData(stack, this.minecraft.level);
VertexConsumer vertexconsumer = buffer.getBuffer(mapitemsaveddata == null ? MAP_BACKGROUND : MAP_BACKGROUND_CHECKERBOARD);
Matrix4f matrix4f = poseStack.last().pose();
vertexconsumer.addVertex(matrix4f, -7.0F, 135.0F, 0.0F).setColor(-1).setUv(0.0F, 1.0F).setLight(packedLight);
vertexconsumer.addVertex(matrix4f, 135.0F, 135.0F, 0.0F).setColor(-1).setUv(1.0F, 1.0F).setLight(packedLight);
vertexconsumer.addVertex(matrix4f, 135.0F, -7.0F, 0.0F).setColor(-1).setUv(1.0F, 0.0F).setLight(packedLight);
vertexconsumer.addVertex(matrix4f, -7.0F, -7.0F, 0.0F).setColor(-1).setUv(0.0F, 0.0F).setLight(packedLight);
if (mapitemsaveddata != null) {
this.minecraft.gameRenderer.getMapRenderer().render(poseStack, buffer, mapid, mapitemsaveddata, false, packedLight);
}
}
private void renderPlayerArm(PoseStack poseStack, MultiBufferSource buffer, int packedLight, float equippedProgress, float swingProgress, HumanoidArm side) {
boolean flag = side != HumanoidArm.LEFT;
float f = flag ? 1.0F : -1.0F;
float f1 = Mth.sqrt(swingProgress);
float f2 = -0.3F * Mth.sin(f1 * (float) Math.PI);
float f3 = 0.4F * Mth.sin(f1 * (float) (Math.PI * 2));
float f4 = -0.4F * Mth.sin(swingProgress * (float) Math.PI);
poseStack.translate(f * (f2 + 0.64000005F), f3 + -0.6F + equippedProgress * -0.6F, f4 + -0.71999997F);
poseStack.mulPose(Axis.YP.rotationDegrees(f * 45.0F));
float f5 = Mth.sin(swingProgress * swingProgress * (float) Math.PI);
float f6 = Mth.sin(f1 * (float) Math.PI);
poseStack.mulPose(Axis.YP.rotationDegrees(f * f6 * 70.0F));
poseStack.mulPose(Axis.ZP.rotationDegrees(f * f5 * -20.0F));
AbstractClientPlayer abstractclientplayer = this.minecraft.player;
poseStack.translate(f * -1.0F, 3.6F, 3.5F);
poseStack.mulPose(Axis.ZP.rotationDegrees(f * 120.0F));
poseStack.mulPose(Axis.XP.rotationDegrees(200.0F));
poseStack.mulPose(Axis.YP.rotationDegrees(f * -135.0F));
poseStack.translate(f * 5.6F, 0.0F, 0.0F);
PlayerRenderer playerrenderer = (PlayerRenderer)this.entityRenderDispatcher.<AbstractClientPlayer>getRenderer(abstractclientplayer);
if (flag) {
playerrenderer.renderRightHand(poseStack, buffer, packedLight, abstractclientplayer);
} else {
playerrenderer.renderLeftHand(poseStack, buffer, packedLight, abstractclientplayer);
}
}
private void applyEatTransform(PoseStack poseStack, float partialTick, HumanoidArm arm, ItemStack stack, Player player) {
float f = (float)player.getUseItemRemainingTicks() - partialTick + 1.0F;
float f1 = f / (float)stack.getUseDuration(player);
if (f1 < 0.8F) {
float f2 = Mth.abs(Mth.cos(f / 4.0F * (float) Math.PI) * 0.1F);
poseStack.translate(0.0F, f2, 0.0F);
}
float f3 = 1.0F - (float)Math.pow((double)f1, 27.0);
int i = arm == HumanoidArm.RIGHT ? 1 : -1;
poseStack.translate(f3 * 0.6F * (float)i, f3 * -0.5F, f3 * 0.0F);
poseStack.mulPose(Axis.YP.rotationDegrees((float)i * f3 * 90.0F));
poseStack.mulPose(Axis.XP.rotationDegrees(f3 * 10.0F));
poseStack.mulPose(Axis.ZP.rotationDegrees((float)i * f3 * 30.0F));
}
private void applyBrushTransform(PoseStack poseStack, float partialTick, HumanoidArm arm, ItemStack stack, Player player, float equippedProgress) {
this.applyItemArmTransform(poseStack, arm, equippedProgress);
float f = (float)(player.getUseItemRemainingTicks() % 10);
float f1 = f - partialTick + 1.0F;
float f2 = 1.0F - f1 / 10.0F;
float f3 = -90.0F;
float f4 = 60.0F;
float f5 = 150.0F;
float f6 = -15.0F;
int i = 2;
float f7 = -15.0F + 75.0F * Mth.cos(f2 * 2.0F * (float) Math.PI);
if (arm != HumanoidArm.RIGHT) {
poseStack.translate(0.1, 0.83, 0.35);
poseStack.mulPose(Axis.XP.rotationDegrees(-80.0F));
poseStack.mulPose(Axis.YP.rotationDegrees(-90.0F));
poseStack.mulPose(Axis.XP.rotationDegrees(f7));
poseStack.translate(-0.3, 0.22, 0.35);
} else {
poseStack.translate(-0.25, 0.22, 0.35);
poseStack.mulPose(Axis.XP.rotationDegrees(-80.0F));
poseStack.mulPose(Axis.YP.rotationDegrees(90.0F));
poseStack.mulPose(Axis.ZP.rotationDegrees(0.0F));
poseStack.mulPose(Axis.XP.rotationDegrees(f7));
}
}
private void applyItemArmAttackTransform(PoseStack poseStack, HumanoidArm hand, float swingProgress) {
int i = hand == HumanoidArm.RIGHT ? 1 : -1;
float f = Mth.sin(swingProgress * swingProgress * (float) Math.PI);
poseStack.mulPose(Axis.YP.rotationDegrees((float)i * (45.0F + f * -20.0F)));
float f1 = Mth.sin(Mth.sqrt(swingProgress) * (float) Math.PI);
poseStack.mulPose(Axis.ZP.rotationDegrees((float)i * f1 * -20.0F));
poseStack.mulPose(Axis.XP.rotationDegrees(f1 * -80.0F));
poseStack.mulPose(Axis.YP.rotationDegrees((float)i * -45.0F));
}
private void applyItemArmTransform(PoseStack poseStack, HumanoidArm hand, float equippedProg) {
int i = hand == HumanoidArm.RIGHT ? 1 : -1;
poseStack.translate((float)i * 0.56F, -0.52F + equippedProg * -0.6F, -0.72F);
}
public void renderHandsWithItems(float partialTicks, PoseStack poseStack, MultiBufferSource.BufferSource buffer, LocalPlayer playerEntity, int combinedLight) {
float f = playerEntity.getAttackAnim(partialTicks);
InteractionHand interactionhand = MoreObjects.firstNonNull(playerEntity.swingingArm, InteractionHand.MAIN_HAND);
float f1 = Mth.lerp(partialTicks, playerEntity.xRotO, playerEntity.getXRot());
ItemInHandRenderer.HandRenderSelection iteminhandrenderer$handrenderselection = evaluateWhichHandsToRender(playerEntity);
float f2 = Mth.lerp(partialTicks, playerEntity.xBobO, playerEntity.xBob);
float f3 = Mth.lerp(partialTicks, playerEntity.yBobO, playerEntity.yBob);
poseStack.mulPose(Axis.XP.rotationDegrees((playerEntity.getViewXRot(partialTicks) - f2) * 0.1F));
poseStack.mulPose(Axis.YP.rotationDegrees((playerEntity.getViewYRot(partialTicks) - f3) * 0.1F));
if (iteminhandrenderer$handrenderselection.renderMainHand) {
float f4 = interactionhand == InteractionHand.MAIN_HAND ? f : 0.0F;
float f5 = 1.0F - Mth.lerp(partialTicks, this.oMainHandHeight, this.mainHandHeight);
if(!net.neoforged.neoforge.client.ClientHooks.renderSpecificFirstPersonHand(InteractionHand.MAIN_HAND, poseStack, buffer, combinedLight, partialTicks, f1, f4, f5, this.mainHandItem))
this.renderArmWithItem(playerEntity, partialTicks, f1, InteractionHand.MAIN_HAND, f4, this.mainHandItem, f5, poseStack, buffer, combinedLight);
}
if (iteminhandrenderer$handrenderselection.renderOffHand) {
float f6 = interactionhand == InteractionHand.OFF_HAND ? f : 0.0F;
float f7 = 1.0F - Mth.lerp(partialTicks, this.oOffHandHeight, this.offHandHeight);
if(!net.neoforged.neoforge.client.ClientHooks.renderSpecificFirstPersonHand(InteractionHand.OFF_HAND, poseStack, buffer, combinedLight, partialTicks, f1, f6, f7, this.offHandItem))
this.renderArmWithItem(playerEntity, partialTicks, f1, InteractionHand.OFF_HAND, f6, this.offHandItem, f7, poseStack, buffer, combinedLight);
}
buffer.endBatch();
}
@VisibleForTesting
static ItemInHandRenderer.HandRenderSelection evaluateWhichHandsToRender(LocalPlayer player) {
ItemStack itemstack = player.getMainHandItem();
ItemStack itemstack1 = player.getOffhandItem();
boolean flag = itemstack.is(Items.BOW) || itemstack1.is(Items.BOW);
boolean flag1 = itemstack.is(Items.CROSSBOW) || itemstack1.is(Items.CROSSBOW);
if (!flag && !flag1) {
return ItemInHandRenderer.HandRenderSelection.RENDER_BOTH_HANDS;
} else if (player.isUsingItem()) {
return selectionUsingItemWhileHoldingBowLike(player);
} else {
return isChargedCrossbow(itemstack)
? ItemInHandRenderer.HandRenderSelection.RENDER_MAIN_HAND_ONLY
: ItemInHandRenderer.HandRenderSelection.RENDER_BOTH_HANDS;
}
}
private static ItemInHandRenderer.HandRenderSelection selectionUsingItemWhileHoldingBowLike(LocalPlayer player) {
ItemStack itemstack = player.getUseItem();
InteractionHand interactionhand = player.getUsedItemHand();
if (!itemstack.is(Items.BOW) && !itemstack.is(Items.CROSSBOW)) {
return interactionhand == InteractionHand.MAIN_HAND && isChargedCrossbow(player.getOffhandItem())
? ItemInHandRenderer.HandRenderSelection.RENDER_MAIN_HAND_ONLY
: ItemInHandRenderer.HandRenderSelection.RENDER_BOTH_HANDS;
} else {
return ItemInHandRenderer.HandRenderSelection.onlyForHand(interactionhand);
}
}
private static boolean isChargedCrossbow(ItemStack stack) {
return stack.is(Items.CROSSBOW) && CrossbowItem.isCharged(stack);
}
private void renderArmWithItem(
AbstractClientPlayer player,
float partialTicks,
float pitch,
InteractionHand hand,
float swingProgress,
ItemStack stack,
float equippedProgress,
PoseStack poseStack,
MultiBufferSource buffer,
int combinedLight
) {
if (!player.isScoping()) {
boolean flag = hand == InteractionHand.MAIN_HAND;
HumanoidArm humanoidarm = flag ? player.getMainArm() : player.getMainArm().getOpposite();
poseStack.pushPose();
if (stack.isEmpty()) {
if (flag && !player.isInvisible()) {
this.renderPlayerArm(poseStack, buffer, combinedLight, equippedProgress, swingProgress, humanoidarm);
}
} else if (stack.getItem() instanceof MapItem) {
if (flag && this.offHandItem.isEmpty()) {
this.renderTwoHandedMap(poseStack, buffer, combinedLight, pitch, equippedProgress, swingProgress);
} else {
this.renderOneHandedMap(poseStack, buffer, combinedLight, equippedProgress, humanoidarm, swingProgress, stack);
}
} else if (stack.getItem() instanceof CrossbowItem) {
boolean flag1 = CrossbowItem.isCharged(stack);
boolean flag2 = humanoidarm == HumanoidArm.RIGHT;
int i = flag2 ? 1 : -1;
if (player.isUsingItem() && player.getUseItemRemainingTicks() > 0 && player.getUsedItemHand() == hand) {
this.applyItemArmTransform(poseStack, humanoidarm, equippedProgress);
poseStack.translate((float)i * -0.4785682F, -0.094387F, 0.05731531F);
poseStack.mulPose(Axis.XP.rotationDegrees(-11.935F));
poseStack.mulPose(Axis.YP.rotationDegrees((float)i * 65.3F));
poseStack.mulPose(Axis.ZP.rotationDegrees((float)i * -9.785F));
float f9 = (float)stack.getUseDuration(player) - ((float)player.getUseItemRemainingTicks() - partialTicks + 1.0F);
float f13 = f9 / (float)CrossbowItem.getChargeDuration(stack, player);
if (f13 > 1.0F) {
f13 = 1.0F;
}
if (f13 > 0.1F) {
float f16 = Mth.sin((f9 - 0.1F) * 1.3F);
float f3 = f13 - 0.1F;
float f4 = f16 * f3;
poseStack.translate(f4 * 0.0F, f4 * 0.004F, f4 * 0.0F);
}
poseStack.translate(f13 * 0.0F, f13 * 0.0F, f13 * 0.04F);
poseStack.scale(1.0F, 1.0F, 1.0F + f13 * 0.2F);
poseStack.mulPose(Axis.YN.rotationDegrees((float)i * 45.0F));
} else {
float f = -0.4F * Mth.sin(Mth.sqrt(swingProgress) * (float) Math.PI);
float f1 = 0.2F * Mth.sin(Mth.sqrt(swingProgress) * (float) (Math.PI * 2));
float f2 = -0.2F * Mth.sin(swingProgress * (float) Math.PI);
poseStack.translate((float)i * f, f1, f2);
this.applyItemArmTransform(poseStack, humanoidarm, equippedProgress);
this.applyItemArmAttackTransform(poseStack, humanoidarm, swingProgress);
if (flag1 && swingProgress < 0.001F && flag) {
poseStack.translate((float)i * -0.641864F, 0.0F, 0.0F);
poseStack.mulPose(Axis.YP.rotationDegrees((float)i * 10.0F));
}
}
this.renderItem(
player,
stack,
flag2 ? ItemDisplayContext.FIRST_PERSON_RIGHT_HAND : ItemDisplayContext.FIRST_PERSON_LEFT_HAND,
!flag2,
poseStack,
buffer,
combinedLight
);
} else {
boolean flag3 = humanoidarm == HumanoidArm.RIGHT;
if (!net.neoforged.neoforge.client.extensions.common.IClientItemExtensions.of(stack).applyForgeHandTransform(poseStack, minecraft.player, humanoidarm, stack, partialTicks, equippedProgress, swingProgress)) // FORGE: Allow items to define custom arm animation
if (player.isUsingItem() && player.getUseItemRemainingTicks() > 0 && player.getUsedItemHand() == hand) {
int k = flag3 ? 1 : -1;
switch (stack.getUseAnimation()) {
case NONE:
this.applyItemArmTransform(poseStack, humanoidarm, equippedProgress);
break;
case EAT:
case DRINK:
this.applyEatTransform(poseStack, partialTicks, humanoidarm, stack, player);
this.applyItemArmTransform(poseStack, humanoidarm, equippedProgress);
break;
case BLOCK:
this.applyItemArmTransform(poseStack, humanoidarm, equippedProgress);
break;
case BOW:
this.applyItemArmTransform(poseStack, humanoidarm, equippedProgress);
poseStack.translate((float)k * -0.2785682F, 0.18344387F, 0.15731531F);
poseStack.mulPose(Axis.XP.rotationDegrees(-13.935F));
poseStack.mulPose(Axis.YP.rotationDegrees((float)k * 35.3F));
poseStack.mulPose(Axis.ZP.rotationDegrees((float)k * -9.785F));
float f8 = (float)stack.getUseDuration(player) - ((float)player.getUseItemRemainingTicks() - partialTicks + 1.0F);
float f12 = f8 / 20.0F;
f12 = (f12 * f12 + f12 * 2.0F) / 3.0F;
if (f12 > 1.0F) {
f12 = 1.0F;
}
if (f12 > 0.1F) {
float f15 = Mth.sin((f8 - 0.1F) * 1.3F);
float f18 = f12 - 0.1F;
float f20 = f15 * f18;
poseStack.translate(f20 * 0.0F, f20 * 0.004F, f20 * 0.0F);
}
poseStack.translate(f12 * 0.0F, f12 * 0.0F, f12 * 0.04F);
poseStack.scale(1.0F, 1.0F, 1.0F + f12 * 0.2F);
poseStack.mulPose(Axis.YN.rotationDegrees((float)k * 45.0F));
break;
case SPEAR:
this.applyItemArmTransform(poseStack, humanoidarm, equippedProgress);
poseStack.translate((float)k * -0.5F, 0.7F, 0.1F);
poseStack.mulPose(Axis.XP.rotationDegrees(-55.0F));
poseStack.mulPose(Axis.YP.rotationDegrees((float)k * 35.3F));
poseStack.mulPose(Axis.ZP.rotationDegrees((float)k * -9.785F));
float f7 = (float)stack.getUseDuration(player) - ((float)player.getUseItemRemainingTicks() - partialTicks + 1.0F);
float f11 = f7 / 10.0F;
if (f11 > 1.0F) {
f11 = 1.0F;
}
if (f11 > 0.1F) {
float f14 = Mth.sin((f7 - 0.1F) * 1.3F);
float f17 = f11 - 0.1F;
float f19 = f14 * f17;
poseStack.translate(f19 * 0.0F, f19 * 0.004F, f19 * 0.0F);
}
poseStack.translate(0.0F, 0.0F, f11 * 0.2F);
poseStack.scale(1.0F, 1.0F, 1.0F + f11 * 0.2F);
poseStack.mulPose(Axis.YN.rotationDegrees((float)k * 45.0F));
break;
case BRUSH:
this.applyBrushTransform(poseStack, partialTicks, humanoidarm, stack, player, equippedProgress);
}
} else if (player.isAutoSpinAttack()) {
this.applyItemArmTransform(poseStack, humanoidarm, equippedProgress);
int j = flag3 ? 1 : -1;
poseStack.translate((float)j * -0.4F, 0.8F, 0.3F);
poseStack.mulPose(Axis.YP.rotationDegrees((float)j * 65.0F));
poseStack.mulPose(Axis.ZP.rotationDegrees((float)j * -85.0F));
} else {
float f5 = -0.4F * Mth.sin(Mth.sqrt(swingProgress) * (float) Math.PI);
float f6 = 0.2F * Mth.sin(Mth.sqrt(swingProgress) * (float) (Math.PI * 2));
float f10 = -0.2F * Mth.sin(swingProgress * (float) Math.PI);
int l = flag3 ? 1 : -1;
poseStack.translate((float)l * f5, f6, f10);
this.applyItemArmTransform(poseStack, humanoidarm, equippedProgress);
this.applyItemArmAttackTransform(poseStack, humanoidarm, swingProgress);
}
this.renderItem(
player,
stack,
flag3 ? ItemDisplayContext.FIRST_PERSON_RIGHT_HAND : ItemDisplayContext.FIRST_PERSON_LEFT_HAND,
!flag3,
poseStack,
buffer,
combinedLight
);
}
poseStack.popPose();
}
}
public void tick() {
this.oMainHandHeight = this.mainHandHeight;
this.oOffHandHeight = this.offHandHeight;
LocalPlayer localplayer = this.minecraft.player;
ItemStack itemstack = localplayer.getMainHandItem();
ItemStack itemstack1 = localplayer.getOffhandItem();
if (ItemStack.matches(this.mainHandItem, itemstack)) {
this.mainHandItem = itemstack;
}
if (ItemStack.matches(this.offHandItem, itemstack1)) {
this.offHandItem = itemstack1;
}
if (localplayer.isHandsBusy()) {
this.mainHandHeight = Mth.clamp(this.mainHandHeight - 0.4F, 0.0F, 1.0F);
this.offHandHeight = Mth.clamp(this.offHandHeight - 0.4F, 0.0F, 1.0F);
} else {
float f = localplayer.getAttackStrengthScale(1.0F);
boolean requipM = net.neoforged.neoforge.client.ClientHooks.shouldCauseReequipAnimation(this.mainHandItem, itemstack, localplayer.getInventory().selected);
boolean requipO = net.neoforged.neoforge.client.ClientHooks.shouldCauseReequipAnimation(this.offHandItem, itemstack1, -1);
if (!requipM && this.mainHandItem != itemstack)
this.mainHandItem = itemstack;
if (!requipO && this.offHandItem != itemstack1)
this.offHandItem = itemstack1;
this.mainHandHeight += Mth.clamp((!requipM ? f * f * f : 0.0F) - this.mainHandHeight, -0.4F, 0.4F);
this.offHandHeight += Mth.clamp((float)(!requipO ? 1 : 0) - this.offHandHeight, -0.4F, 0.4F);
}
if (this.mainHandHeight < 0.1F) {
this.mainHandItem = itemstack;
}
if (this.offHandHeight < 0.1F) {
this.offHandItem = itemstack1;
}
}
public void itemUsed(InteractionHand hand) {
if (hand == InteractionHand.MAIN_HAND) {
this.mainHandHeight = 0.0F;
} else {
this.offHandHeight = 0.0F;
}
}
@OnlyIn(Dist.CLIENT)
@VisibleForTesting
static enum HandRenderSelection {
RENDER_BOTH_HANDS(true, true),
RENDER_MAIN_HAND_ONLY(true, false),
RENDER_OFF_HAND_ONLY(false, true);
final boolean renderMainHand;
final boolean renderOffHand;
private HandRenderSelection(boolean renderMainHand, boolean renderOffHand) {
this.renderMainHand = renderMainHand;
this.renderOffHand = renderOffHand;
}
public static ItemInHandRenderer.HandRenderSelection onlyForHand(InteractionHand hand) {
return hand == InteractionHand.MAIN_HAND ? RENDER_MAIN_HAND_ONLY : RENDER_OFF_HAND_ONLY;
}
}
}

View File

@@ -0,0 +1,120 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.neoforged.neoforge.client.event;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.item.ItemStack;
import net.neoforged.bus.api.Event;
import net.neoforged.bus.api.ICancellableEvent;
import net.neoforged.fml.LogicalSide;
import net.neoforged.neoforge.common.NeoForge;
import org.jetbrains.annotations.ApiStatus;
/**
* Fired before a hand is rendered in the first person view.
*
* <p>This event is {@linkplain ICancellableEvent cancellable}, and does not {@linkplain HasResult have a result}.
* If this event is cancelled, then the hand will not be rendered.</p>
*
* <p>This event is fired on the {@linkplain NeoForge#EVENT_BUS main Forge event bus},
* only on the {@linkplain LogicalSide#CLIENT logical client}.</p>
*
* @see RenderArmEvent
*/
public class RenderHandEvent extends Event implements ICancellableEvent {
private final InteractionHand hand;
private final PoseStack poseStack;
private final MultiBufferSource multiBufferSource;
private final int packedLight;
private final float partialTick;
private final float interpolatedPitch;
private final float swingProgress;
private final float equipProgress;
private final ItemStack stack;
@ApiStatus.Internal
public RenderHandEvent(InteractionHand hand, PoseStack poseStack, MultiBufferSource multiBufferSource, int packedLight,
float partialTick, float interpolatedPitch,
float swingProgress, float equipProgress, ItemStack stack) {
this.hand = hand;
this.poseStack = poseStack;
this.multiBufferSource = multiBufferSource;
this.packedLight = packedLight;
this.partialTick = partialTick;
this.interpolatedPitch = interpolatedPitch;
this.swingProgress = swingProgress;
this.equipProgress = equipProgress;
this.stack = stack;
}
/**
* {@return the hand being rendered}
*/
public InteractionHand getHand() {
return hand;
}
/**
* {@return the pose stack used for rendering}
*/
public PoseStack getPoseStack() {
return poseStack;
}
/**
* {@return the source of rendering buffers}
*/
public MultiBufferSource getMultiBufferSource() {
return multiBufferSource;
}
/**
* {@return the amount of packed (sky and block) light for rendering}
*
* @see LightTexture
*/
public int getPackedLight() {
return packedLight;
}
/**
* {@return the partial tick}
*/
public float getPartialTick() {
return partialTick;
}
/**
* {@return the interpolated pitch of the player entity}
*/
public float getInterpolatedPitch() {
return interpolatedPitch;
}
/**
* {@return the swing progress of the hand being rendered}
*/
public float getSwingProgress() {
return swingProgress;
}
/**
* {@return the progress of the equip animation, from {@code 0.0} to {@code 1.0}}
*/
public float getEquipProgress() {
return equipProgress;
}
/**
* {@return the item stack to be rendered}
*/
public ItemStack getItemStack() {
return stack;
}
}