NeoForge-1.20.4Mod开发教程之物品特殊渲染

本篇教程参考为Flandre芙兰的NeoForge1.20.4Mod开发的视频,这篇教程是我边学边总结的,与其说是教程更像我的学习笔记,如有不清楚的地方,大家可以在评论区提问。在我力所能及的范围内,我都会解答的。

 

首先添加一个物品

创建AroundYItem类

public class AroundYItem extends Item {
     public AroundYItem() {
         super(new Properties());
    }
     private static final BlockEntityWithoutLevelRenderer R = new AroundYItemRenderer();
 ​
     @Override
     public void initializeClient(Consumer<IClientItemExtensions> consumer) {//接入自定义渲染
         consumer.accept(new IClientItemExtensions() {
             @Override
             public BlockEntityWithoutLevelRenderer getCustomRenderer() {
                 return R;//返回此物品专用BlockEntityWithoutLevelRenderer
            }
        });
    }
 }

 

创建AroundYItemRenderer类

public class AroundYItemRenderer extends BlockEntityWithoutLevelRenderer {
     private int degree = 0;//初始化旋转角度
     public AroundYItemRenderer() {
         super(null, null);
    }
 ​
     @Override
     public void renderByItem(ItemStack stack, ItemDisplayContext displayContext, PoseStack poseStack, MultiBufferSource buffer, int packedLight, int packedOverlay) {//渲染物品的方法,根据物品类型的不同,选择不同的渲染方式
         ItemRenderer itemRenderer = Minecraft.getInstance().getItemRenderer();//获取全局渲染器
         BakedModel bakedModel = itemRenderer.getModel(stack,null,null,1);//获取此栈当前模型
         BakedModel modelToRender = bakedModel instanceof AroundYItemModel aroundYItemModel//若模型是AroundYItemModel,则getOriginalModel()用原本的模型;否则直接用当前模型
                 ? aroundYItemModel.getOriginalModel()
                : bakedModel;
 ​
         if (degree == 360) {degree = 0;}//旋转角度
         degree++;
 ​
         poseStack.pushPose();
         poseStack.translate(0.5f, 0.5f, 0.5f);//把旋转中心移到模型中心
         poseStack.mulPose(Axis.YP.rotationDegrees(degree));//绕物体y轴旋转
         itemRenderer.render(stack, ItemDisplayContext.NONE, false, poseStack, buffer, packedLight, packedOverlay, modelToRender);//绘制模型
         poseStack.popPose();
    }
 }

 

创建AroundYItemModel类

public class AroundYItemModel implements BakedModel {
     private final BakedModel existingModel;
     public AroundYItemModel(BakedModel existingModel) {
         this.existingModel = existingModel;
    }
 ​
     public BakedModel getOriginalModel() {
         return existingModel;
    }
 ​
     @Override
     public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction direction, RandomSource random) {
         return this.existingModel.getQuads(state, direction, random);
    }
 ​
     @Override
     public boolean useAmbientOcclusion() {
         return existingModel.useAmbientOcclusion();
    }
 ​
     @Override
     public boolean isGui3d() {
         return existingModel.isGui3d();
    }
 ​
     @Override
     public boolean usesBlockLight() {
         return existingModel.usesBlockLight();
    }
 ​
     @Override
     public boolean isCustomRenderer() {//返回true,使用自定义渲染
         return true;
    }
 ​
     @Override
     public TextureAtlasSprite getParticleIcon() {
         return existingModel.getParticleIcon();
    }
 ​
     @Override
     public ItemOverrides getOverrides() {
         return existingModel.getOverrides();
    }
 ​
     @Override
     public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, RandomSource rand, ModelData data, @Nullable RenderType renderType) {
         throw new AssertionError("IBakedModel::getQuads should never be called, only IForgeBakedModel::getQuads");
    }
 ​
 ​
 }

 

这个是前面说过的烘焙模型,不一样的是要使用public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction direction, RandomSource random)而不是另一个同名方法

 

替换模型

Map<ResourceLocation, BakedModel> models = event.getModels();//获取本次烘焙结果里的“模型表”,键是模型资源位置,值是烘焙后的BakedModel
 ModelResourceLocation location = new ModelResourceLocation(BuiltInRegistries.ITEM.getKey(ModItems.AROUNDY_ITEM.get()),"inventory");//构造aroundy物品在物品栏场景对应的模型键
 BakedModel existingModel = models.get(location);
 if (existingModel == null) {
     throw new RuntimeException("Did not find Aroundy ");
 } else if (existingModel instanceof AroundYItemModel) {
     throw new RuntimeException("Tried to replace Wrench twice");
 }else {
     AroundYItemModel AroundYItemModel = new AroundYItemModel(existingModel);
     event.getModels().put(location,AroundYItemModel);
 }

 

最后不要忘记注册和提供模型、材质,之后你就得到了一个围绕自身y轴旋转的物品

如果你想在特定展示环境才显示动画你可以在在AroundYItemModel类中写重写applyTransform方法

public  BakedModel applyTransform(ItemDisplayContext ctx, PoseStack poseStack, boolean applyLeftHandTransform) {
         if (ctx == ItemDisplayContext.FIRST_PERSON_LEFT_HAND || ctx == ItemDisplayContext.FIRST_PERSON_RIGHT_HAND) {//只在第一人称主手和副手上时才显示动画
             return this;
        }
         return this.existingModel.applyTransform(ctx, poseStack, applyLeftHandTransform);
    }

 

如果写了此方法需要去掉AroundYItemRenderer类中的

BakedModel modelToRender = bakedModel instanceof AroundYItemModel aroundYItemModel
                 ? aroundYItemModel.getOriginalModel()
                : bakedModel;

这个是为了防止无限回调,在不是aroundYItemModel时给出默认的模型。applyTransform实现了这个功能

© 版权声明
THE END
喜欢就支持一下吧
点赞3赞赏 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容