/* * Copyright 2025-2026 R3944Realms * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package top.r3944realms.eroticdungeongame.client.model; import net.minecraft.client.model.HumanoidModel; import net.minecraft.client.model.geom.ModelPart; 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.ItemStack; import top.r3944realms.eroticdungeongame.content.item.WhipItem; public class EDGArmPose { public static HumanoidModel.ArmPose WHIP; public static void init() { WHIP = HumanoidModel.ArmPose.create("edg_whip", false, EDGArmPose::applyWhipPose); } private static void applyWhipPose(HumanoidModel model, LivingEntity entity, HumanoidArm arm) { if (!(entity instanceof Player player)) return; // 检查是否在使用鞭子 ItemStack useItem = player.getUseItem(); if (!(useItem.getItem() instanceof WhipItem)) return; // 确定使用的是哪只手 InteractionHand useHand = player.getUsedItemHand(); // 只有当指定的手臂是使用鞭子的手臂时才应用动画 HumanoidArm useArm = useHand == InteractionHand.MAIN_HAND ? player.getMainArm() : (player.getMainArm() == HumanoidArm.RIGHT ? HumanoidArm.LEFT : HumanoidArm.RIGHT); if (arm != useArm) { // 非使用手臂保持正常姿势 resetToDefaultPose(model, arm); return; } // 计算使用进度 int remainedUseTime = player.getUseItemRemainingTicks(); int maxUseTime = useItem.getUseDuration(); float progress = 1.0f - (float)remainedUseTime / maxUseTime; // System.out.printf("Using %d times of %d seconds%n", remainedUseTime, maxUseTime); // 应用鞭子动画 applyWhipAnimation(model, arm, progress); // 如果是主手,应用身体动画 if (arm == player.getMainArm()) { applyBodyAnimation(model, progress, useArm); } } private static void resetToDefaultPose(HumanoidModel model, HumanoidArm arm) { ModelPart armPart = getArmPart(model, arm); // 设置为默认手持姿势 armPart.xRot = -0.87266463F; // 约 -50度 armPart.yRot = 0.0F; armPart.zRot = 0.0F; } private static ModelPart getArmPart(HumanoidModel model, HumanoidArm arm) { return arm == HumanoidArm.LEFT ? model.leftArm : model.rightArm; } private static void applyWhipAnimation(HumanoidModel model, HumanoidArm arm, float progress) { ModelPart armPart = getArmPart(model, arm); boolean isRightArm = arm == HumanoidArm.RIGHT; // 完全重置旋转 armPart.xRot = 0.0f; armPart.yRot = 0.0f; armPart.zRot = 0.0f; // 根据左右手决定挥舞方向 if (isRightArm) { applyRightHandWhipAnimation(armPart, progress); } else { applyLeftHandWhipAnimation(armPart, progress); } } private static void applyRightHandWhipAnimation(ModelPart arm, float progress) { // 右手:从右向左挥舞(从上到下) if (progress < 0.2f) { // 阶段1:准备(向后上方拉) float phase = progress / 0.2f; arm.xRot = Mth.lerp(phase, 0.0f, -2.8f); // 向上抬 arm.yRot = Mth.lerp(phase, 0.0f, 0.3f); // 先向右偏(准备从左向右) arm.zRot = Mth.lerp(phase, 0.0f, -0.2f); // 手腕外旋 } else if (progress < 0.5f) { // 阶段2:主要挥舞(从上到下,从右向左) float phase = (progress - 0.2f) / 0.3f; float swing = Mth.sin(phase * Mth.PI); // 手臂从上到下 arm.xRot = -0.4f + swing * 1.2f; // -0.4到0.8 // 手臂从右向左摆动 arm.yRot = 0.3f - swing * 0.6f; // 0.3到-0.3 // 手腕转动 arm.zRot = -0.2f + swing * 0.3f; // -0.2到0.1 } } private static void applyLeftHandWhipAnimation(ModelPart arm, float progress) { // 左手:从左向右挥舞(从上到下) if (progress < 0.2f) { // 阶段1:准备(向后上方拉) float phase = progress / 0.2f; arm.xRot = Mth.lerp(phase, 0.0f, -2.8f); // 向上抬 arm.yRot = Mth.lerp(phase, 0.0f, -0.3f); // 先向左偏(准备从右向左) arm.zRot = Mth.lerp(phase, 0.0f, 0.2f); // 手腕外旋 } else if (progress < 0.5f) { // 阶段2:主要挥舞(从上到下,从左向右) float phase = (progress - 0.2f) / 0.3f; float swing = Mth.sin(phase * Mth.PI); // 手臂从上到下 arm.xRot = -0.4f + swing * 1.2f; // -0.4到0.8 // 手臂从左向右摆动 arm.yRot = -0.3f + swing * 0.6f; // -0.3到0.3 // 手腕转动 arm.zRot = 0.2f - swing * 0.3f; // 0.2到-0.1 } } private static void applyBodyAnimation(HumanoidModel model, float progress, HumanoidArm useArm) { boolean isRightHand = useArm == HumanoidArm.RIGHT; // 身体跟随手臂转动 if (progress < 0.6f) { float phase = progress / 0.6f; // 根据使用的手决定身体转动方向 if (isRightHand) { // 右手使用时,身体先向右转,然后向左转 float bodyRot = Mth.sin(phase * Mth.PI) * 0.3f; // 0到0.3到0 model.body.yRot = bodyRot; // 身体向右转 } else { // 左手使用时,身体先向左转,然后向右转 float bodyRot = -Mth.sin(phase * Mth.PI) * 0.3f; // 0到-0.3到0 model.body.yRot = bodyRot; // 身体向左转 } } else { float phase = (progress - 0.6f) / 0.4f; model.body.yRot = Mth.lerp(phase, 0.0f, 0.0f); // 回正 } // 头部跟随身体转动,但幅度较小 model.head.yRot = model.body.yRot * 0.6f; // 根据挥舞动作,身体会有轻微的前倾 if (progress > 0.3f && progress < 0.7f) { float phase = (progress - 0.3f) / 0.4f; float lean = Mth.sin(phase * Mth.PI) * 0.1f; model.body.xRot = lean; // 轻微前倾 } else { model.body.xRot = 0.0f; } } }