549 words
3 minutes
22 更改玩家的渲染的模型
22 更改玩家的渲染的模型
我们使用上一次说的访问WalkAnimationState
的speedOld
,speed,position
@Mixin(WalkAnimationState.class)
public interface LimbAnimatorAccessor {
@Accessor("speedOld")
float getSpeedOld();
@Accessor("speedOld")
void setSpeedOld(float speedOld);
@Accessor
float getSpeed();
@Accessor
void setSpeed(float speed);
@Accessor
float getPosition();
@Accessor
void setPosition(float pos);
}
如果是其他的实体,则在对应的位置生成一个羊,然后移除当初的实体
@Mixin(LivingEntity.class)
public abstract class LivingEntityMixin extends Entity implements Attackable {
@Shadow public abstract boolean hasEffect(Holder<MobEffect> effect);
public LivingEntityMixin(EntityType<?> entityType, Level level) {
super(entityType, level);
}
@Inject(at = @At("HEAD"), method = "tick")
private void init(CallbackInfo info) {
if(!this.level().isClientSide) {
if (this.hasEffect(ModEffects.SHEEP_EFFECT)) {//变羊药水
if (!this.isAlwaysTicking()) {//如果不是玩家的话
Vec3 pos = this.position();
EntityType.SHEEP.spawn(((ServerLevel) this.level()), BlockPos.containing(pos), MobSpawnType.TRIGGERED);
this.remove(RemovalReason.KILLED);
}
}
}
}
}
如果是玩家的话,那么我们要调整 渲染将玩家渲染为羊,这个思路和之前的物品的渲染类似.
// 指定这是一个混入类,将功能添加到 PlayerRenderer 类。
// 这允许我们修改 PlayerRenderer 的渲染行为,而无需直接修改 PlayerRenderer 的源代码。
@Mixin(PlayerRenderer.class)
public abstract class PlayerEntityRendererMixin extends LivingEntityRenderer<AbstractClientPlayer, PlayerModel<AbstractClientPlayer>> {
// 构造函数,用于初始化 PlayerEntityRendererMixin 类。
// 调用父类 LivingEntityRenderer 的构造函数。
public PlayerEntityRendererMixin(EntityRendererProvider.Context context, PlayerModel<AbstractClientPlayer> model, float shadowRadius) {
super(context, model, shadowRadius);
}
// 使用 @Redirect 注解重定向 PlayerRenderer 的 render 方法。
// 这意味着我们将拦截对 PlayerRenderer.render 方法的调用,并用自定义的逻辑替代它。
@Redirect(
method = "render*", // 拦截所有以 render* 开头的方法
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/player/PlayerRenderer;render(Lnet/minecraft/client/player/AbstractClientPlayer;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V"))
private void redirectRender(PlayerRenderer renderer, AbstractClientPlayer entity, float entityYaw, float partialTicks, PoseStack poseStack, MultiBufferSource buffer, int packedLight) {
// 创建一个新的羊实体,使用当前游戏世界的实例。
LivingEntity sheep = new Sheep(EntityType.SHEEP, Minecraft.getInstance().level);
// 如果玩家有变羊效果
if (entity.hasEffect(ModEffects.SHEEP_EFFECT)) {
// 获取羊的渲染器
EntityRenderer sheepRenderer = Minecraft.getInstance().getEntityRenderDispatcher().getRenderer(sheep);
// 将玩家的动画属性复制到羊身上
LimbAnimatorAccessor target = (LimbAnimatorAccessor) sheep.walkAnimation;
LimbAnimatorAccessor source = (LimbAnimatorAccessor) entity.walkAnimation;
target.setSpeedOld(source.getSpeedOld());
target.setSpeed(source.getSpeed());
target.setPosition(source.getPosition());
// 同步其他动画参数
sheep.swinging = entity.swinging;
sheep.swingTime = entity.swingTime;
sheep.oAttackAnim = entity.oAttackAnim;
sheep.attackAnim = entity.attackAnim;
sheep.yBodyRot = entity.yBodyRot;
sheep.yBodyRotO = entity.yBodyRotO;
sheep.yHeadRot = entity.yHeadRot;
sheep.yHeadRotO = entity.yHeadRotO;
sheep.tickCount = entity.tickCount;
sheep.swingingArm = entity.swingingArm;
sheep.setOnGround(entity.onGround());
sheep.setDeltaMovement(entity.getDeltaMovement());
// 同步姿态和角度
sheep.setPose(entity.getPose());
sheep.setXRot(entity.getXRot());
sheep.xRotO = entity.xRotO;
// 使用羊的渲染器渲染羊实体
sheepRenderer.render(sheep, entityYaw, partialTicks, poseStack, buffer, packedLight);
} else {
// 如果玩家没有变羊效果,则调用父类的渲染方法来渲染玩家
super.render((AbstractClientPlayer) entity, entityYaw, partialTicks, poseStack, buffer, packedLight);
}
}
}