Jump to content

Recommended Posts

Posted

How to add a new renderLayer to the player?

In the original player class we have its constructor:

Spoiler
@OnlyIn(Dist.CLIENT)
public class PlayerRenderer extends LivingEntityRenderer<AbstractClientPlayer, PlayerModel<AbstractClientPlayer>> {

   public PlayerRenderer(EntityRendererProvider.Context p_174557_, boolean p_174558_) {
      super(p_174557_, new PlayerModel<>(p_174557_.bakeLayer(p_174558_ ? ModelLayers.PLAYER_SLIM : ModelLayers.PLAYER), p_174558_), 0.5F);
      this.addLayer(new HumanoidArmorLayer<>(this, new HumanoidModel(p_174557_.bakeLayer(p_174558_ ? ModelLayers.PLAYER_SLIM_INNER_ARMOR : 	ModelLayers.PLAYER_INNER_ARMOR)), new HumanoidModel(p_174557_.bakeLayer(p_174558_ ? ModelLayers.PLAYER_SLIM_OUTER_ARMOR : 	ModelLayers.PLAYER_OUTER_ARMOR))));
      this.addLayer(new PlayerItemInHandLayer<>(this, p_174557_.getItemInHandRenderer()));
      this.addLayer(new ArrowLayer<>(p_174557_, this));
      this.addLayer(new Deadmau5EarsLayer(this));
      this.addLayer(new CapeLayer(this));
      this.addLayer(new CustomHeadLayer<>(this, p_174557_.getModelSet(), p_174557_.getItemInHandRenderer()));
      this.addLayer(new ElytraLayer<>(this, p_174557_.getModelSet()));
      this.addLayer(new ParrotOnShoulderLayer<>(this, p_174557_.getModelSet()));
      this.addLayer(new SpinAttackEffectLayer<>(this, p_174557_.getModelSet()));
      this.addLayer(new BeeStingerLayer<>(this));
   }
	// ..... MORE CODE
}

 

I would like to add an additional Layer through events.
I searched a lot and found the way below, using
EntityRenderersEvent.AddLayers.

Spoiler
@Mod.EventBusSubscriber(modid = ModCraft.MOD_ID, value = Dist.CLIENT)
public static class ClientForgeEvents {
	@SubscribeEvent
        public static void registerArmorRenderers(EntityRenderersEvent.AddLayers event) {
            boolean bool=true;
            //LivingEntityRenderer render = event.getRenderer(EntityType.PLAYER);
            LivingEntityRenderer<Player, PlayerModel<Player>> renderer = event.getRenderer(EntityType.PLAYER);
            ExampleTypeAcessoryLayer layer = new ExampleTypeAcessoryLayer(renderer, new HumanoidModel(event.getEntityModels().bakeLayer(bool ? ModelLayers.PLAYER_SLIM_INNER_ARMOR : ModelLayers.PLAYER_INNER_ARMOR)), new HumanoidModel(event.getEntityModels().bakeLayer(bool ? ModelLayers.PLAYER_SLIM_OUTER_ARMOR : ModelLayers.PLAYER_OUTER_ARMOR)));
            renderer.addLayer(layer);
        }
}

 

However, the code states that o renderer = null.
How to add this RenderLayer to entities that already exist in vanilla?

Posted

Thanks. The renderer isn't more null. But the layer not render nothing.

Let's go back a few houses!!!

To check if the exampleentityLayer is working(Is working).
-> I built a new entity (extends Skeleton)
-> I added this render (my renderLayer) to my new created entity. It works! see

My entity renderer (created by me) and the added renderlayer:

Spoiler
public class ExampleTypeRender extends HumanoidMobRenderer<AbstractSkeleton, HumanoidModel<AbstractSkeleton>> {
    private static final ResourceLocation SKELETON_LOCATION = new ResourceLocation(ModCraft.MOD_ID, "textures/entity/example_entity/skeleton.png");

    public ExampleTypeRender(EntityRendererProvider.Context context) {
        this(context, ModelLayers.SKELETON, ModelLayers.SKELETON_INNER_ARMOR, ModelLayers.SKELETON_OUTER_ARMOR);
    }

    public ExampleTypeRender(EntityRendererProvider.Context context, ModelLayerLocation modelLayerLocation, ModelLayerLocation layerLocation, ModelLayerLocation location) {
        super(context, new SkeletonModel<>(context.bakeLayer(modelLayerLocation)), 0.3F);
		// Here I Add my Custom RenderLayer
        this.addLayer(new ExampleEntityLayer<>(this, new ExampleTypeModel(context.bakeLayer(layerLocation)), new ExampleTypeModel(context.bakeLayer(location))));
    }

    public ResourceLocation getTextureLocation(AbstractSkeleton skeleton) {
        return SKELETON_LOCATION;
    }

    protected boolean isShaking(AbstractSkeleton p_174389_) {
        return p_174389_.isShaking();
    }
}

 

Look at the image that works:

Spoiler

spacer.png

Now let's put my RenderLayer in a Vanila entity (a Skeleton). Not yet in the Player (we will do this later, if possible).
So all Skeletons must render this armor. But this does not happen: See the image below.

Adding the RenderLayer in Skeleton Vanilla via Register EntityRenderersEvent.AddLayers:

Spoiler
public class ClientEvents {
    @Mod.EventBusSubscriber(modid = ModCraft.MOD_ID, value = Dist.CLIENT)
    public static class ClientForgeEvents {
	@SubscribeEvent
        public static void registerArmorRenderers(final EntityRenderersEvent.AddLayers event) {
            boolean bool=true;
            LivingEntityRenderer render = event.getRenderer(EntityType.SKELETON);
            render.addLayer(new ExampleEntityLayer(render,new HumanoidModel(event.getEntityModels().bakeLayer(ModelLayers.PLAYER_INNER_ARMOR)),new HumanoidModel(event.getEntityModels().bakeLayer(ModelLayers.PLAYER_OUTER_ARMOR))));
        }

}

 

The Vanilla Skeleton Image:

Spoiler

spacer.png

Posted

Right. 

That is complete custom Skeleton:

Spoiler
public class ExampleTypeEntity extends AbstractSkeleton {
    private static final EntityDataAccessor<Boolean> DATA_STRAY_CONVERSION_ID = SynchedEntityData.defineId(Skeleton.class, EntityDataSerializers.BOOLEAN);
    public static final String CONVERSION_TAG = "StrayConversionTime";
    private int inPowderSnowTime;
    private int conversionTime;

    @Nullable
    @Override
    public SpawnGroupData finalizeSpawn(ServerLevelAccessor p_levelAccessor2146_, DifficultyInstance instance, MobSpawnType spawnType, @Nullable SpawnGroupData groupData, @Nullable CompoundTag tag) {
        return super.finalizeSpawn(p_levelAccessor2146_, instance, spawnType, groupData, tag);
    }

    public ExampleTypeEntity(EntityType<? extends ExampleTypeEntity> entityType, Level level) {
        super(entityType, level);
    }

    protected void defineSynchedData() {
        super.defineSynchedData();
        this.getEntityData().define(DATA_STRAY_CONVERSION_ID, false);
    }

    public boolean isFreezeConverting() {
        return this.getEntityData().get(DATA_STRAY_CONVERSION_ID);
    }

    public void setFreezeConverting(boolean p_149843_) {
        this.entityData.set(DATA_STRAY_CONVERSION_ID, p_149843_);
    }

    public boolean isShaking() {
        return this.isFreezeConverting();
    }

    public void tick() {
        if (!this.level.isClientSide && this.isAlive() && !this.isNoAi()) {
            if (this.isFreezeConverting()) {
                --this.conversionTime;
                if (this.conversionTime < 0) {
                    this.doFreezeConversion();
                }
            } else if (this.isInPowderSnow) {
                ++this.inPowderSnowTime;
                if (this.inPowderSnowTime >= 140) {
                    this.startFreezeConversion(300);
                }
            } else {
                this.inPowderSnowTime = -1;
            }
        }

        super.tick();
    }

    public void addAdditionalSaveData(CompoundTag p_149836_) {
        super.addAdditionalSaveData(p_149836_);
        p_149836_.putInt("StrayConversionTime", this.isFreezeConverting() ? this.conversionTime : -1);
    }

    public void readAdditionalSaveData(CompoundTag p_149833_) {
        super.readAdditionalSaveData(p_149833_);
        if (p_149833_.contains("StrayConversionTime", 99) && p_149833_.getInt("StrayConversionTime") > -1) {
            this.startFreezeConversion(p_149833_.getInt("StrayConversionTime"));
        }

    }

    private void startFreezeConversion(int p_149831_) {
        this.conversionTime = p_149831_;
        this.entityData.set(DATA_STRAY_CONVERSION_ID, true);
    }

    protected void doFreezeConversion() {
        this.convertTo(EntityType.STRAY, true);
        if (!this.isSilent()) {
            this.level.levelEvent((Player)null, 1048, this.blockPosition(), 0);
        }

    }

    public boolean canFreeze() {
        return false;
    }

    protected SoundEvent getAmbientSound() {
        return SoundEvents.SKELETON_AMBIENT;
    }

    protected SoundEvent getHurtSound(DamageSource p_33579_) {
        return SoundEvents.SKELETON_HURT;
    }

    protected SoundEvent getDeathSound() {
        return SoundEvents.SKELETON_DEATH;
    }

    protected SoundEvent getStepSound() {
        return SoundEvents.SKELETON_STEP;
    }

    protected void dropCustomDeathLoot(DamageSource p_33574_, int p_33575_, boolean p_33576_) {
        super.dropCustomDeathLoot(p_33574_, p_33575_, p_33576_);
        Entity entity = p_33574_.getEntity();
        if (entity instanceof Creeper creeper) {
            if (creeper.canDropMobsSkull()) {
                creeper.increaseDroppedSkulls();
                this.spawnAtLocation(Items.SKELETON_SKULL);
            }
        }

    }
}

 

And this is the Complete Custom ExampleEntityLayer (the custom renderLayer to Custom Skeletom)

(It's basically an adapted HumanoidArmorLayer class)

Spoiler

@OnlyIn(Dist.CLIENT)
public class ExampleEntityLayer <T extends LivingEntity, M extends HumanoidModel<T>, A extends HumanoidModel<T>> extends RenderLayer<T, M> {
    private static final Map<String, ResourceLocation> ARMOR_LOCATION_CACHE = Maps.newHashMap();
    private final A innerModel;
    private final A outerModel;

    public ExampleEntityLayer(RenderLayerParent<T, M> p_117075_, A p_117076_, A p_117077_) {
        super(p_117075_);
        this.innerModel = p_117076_;
        this.outerModel = p_117077_;
    }

    public void render(PoseStack p_117096_, MultiBufferSource p_117097_, int p_117098_, T p_117099_, float p_117100_, float p_117101_, float p_117102_, float p_117103_, float p_117104_, float p_117105_) {
        this.renderArmorPiece(p_117096_, p_117097_, p_117099_, EquipmentSlot.CHEST, p_117098_, this.getArmorModel(EquipmentSlot.CHEST));
        this.renderArmorPiece(p_117096_, p_117097_, p_117099_, EquipmentSlot.LEGS, p_117098_, this.getArmorModel(EquipmentSlot.LEGS));
        this.renderArmorPiece(p_117096_, p_117097_, p_117099_, EquipmentSlot.FEET, p_117098_, this.getArmorModel(EquipmentSlot.FEET));
        this.renderArmorPiece(p_117096_, p_117097_, p_117099_, EquipmentSlot.HEAD, p_117098_, this.getArmorModel(EquipmentSlot.HEAD));
    }

    private void renderArmorPiece(PoseStack poseStack, MultiBufferSource bufferSource, T livingEntity, EquipmentSlot equipmentSlot, int i1, A armorModel) {
        ItemStack itemstack = livingEntity.getItemBySlot(equipmentSlot);
        equipmentSlot = EquipmentSlot.HEAD;
        itemstack = new ItemStack(ModItem.STEEL_ARMOR_STANDART_HELMET.get());
        if (itemstack.getItem() instanceof ArmorItem) {
            ArmorItem armoritem = (ArmorItem)itemstack.getItem();
            if (armoritem.getSlot() == equipmentSlot) {
                //this.getParentModel().copyPropertiesTo(p_117124_);
                //ModelPartUtils.copyOriginalPropertiesTo(this.getParentModel(), armorModel,0.1F);// trabalho dobrado a frente
                //this.setPartVisibility(armorModel, equipmentSlot);
                net.minecraft.client.model.Model model = getArmorModelHook(livingEntity, itemstack, equipmentSlot, armorModel);
                boolean flag = this.usesInnerModel(equipmentSlot);
                boolean flag1 = itemstack.hasFoil();
                if (armoritem instanceof net.minecraft.world.item.DyeableLeatherItem) {
                    int i = ((net.minecraft.world.item.DyeableLeatherItem)armoritem).getColor(itemstack);
                    float f = (float)(i >> 16 & 255) / 255.0F;
                    float f1 = (float)(i >> 8 & 255) / 255.0F;
                    float f2 = (float)(i & 255) / 255.0F;
                    this.renderModel(poseStack, bufferSource, i1, flag1, model, f, f1, f2, this.getArmorResource(livingEntity, itemstack, equipmentSlot, null));
                    this.renderModel(poseStack, bufferSource, i1, flag1, model, 1.0F, 1.0F, 1.0F, this.getArmorResource(livingEntity, itemstack, equipmentSlot, "overlay"));
                } else {
                    this.renderModel(poseStack, bufferSource, i1, flag1, model, 1.0F, 1.0F, 1.0F, this.getArmorResource(livingEntity, itemstack, equipmentSlot, null));
                }

            }
        }
    }

    protected void setPartVisibility(A p_117126_, EquipmentSlot p_117127_) {
        p_117126_.setAllVisible(false);
        switch (p_117127_) {
            case HEAD:
                p_117126_.head.visible = true;
                p_117126_.hat.visible = true;
                break;
            case CHEST:
                p_117126_.body.visible = true;
                p_117126_.rightArm.visible = true;
                p_117126_.leftArm.visible = true;
                break;
            case LEGS:
                p_117126_.body.visible = true;
                p_117126_.rightLeg.visible = true;
                p_117126_.leftLeg.visible = true;
                break;
            case FEET:
                p_117126_.rightLeg.visible = true;
                p_117126_.leftLeg.visible = true;
        }

    }

    private void renderModel(PoseStack p_117107_, MultiBufferSource p_117108_, int p_117109_, ArmorItem p_117110_, boolean p_117111_, A p_117112_, boolean p_117113_, float p_117114_, float p_117115_, float p_117116_, @Nullable String p_117117_) {
        renderModel(p_117107_, p_117108_, p_117109_, p_117111_, p_117112_, p_117114_, p_117115_, p_117116_, this.getArmorLocation(p_117110_, p_117113_, p_117117_));
    }
    private void renderModel(PoseStack p_117107_, MultiBufferSource p_117108_, int p_117109_, boolean p_117111_, net.minecraft.client.model.Model p_117112_, float p_117114_, float p_117115_, float p_117116_, ResourceLocation armorResource) {
        VertexConsumer vertexconsumer = ItemRenderer.getArmorFoilBuffer(p_117108_, RenderType.armorCutoutNoCull(armorResource), false, p_117111_);
        p_117112_.renderToBuffer(p_117107_, vertexconsumer, p_117109_, OverlayTexture.NO_OVERLAY, p_117114_, p_117115_, p_117116_, 1.0F);
    }

    private A getArmorModel(EquipmentSlot p_117079_) {
        return (A)(this.usesInnerModel(p_117079_) ? this.innerModel : this.outerModel);
    }

    private boolean usesInnerModel(EquipmentSlot p_117129_) {
        return p_117129_ == EquipmentSlot.LEGS;
    }

    @Deprecated //Use the more sensitive version getArmorResource below
    private ResourceLocation getArmorLocation(ArmorItem p_117081_, boolean p_117082_, @Nullable String p_117083_) {
        String s = "textures/models/armor/" + p_117081_.getMaterial().getName() + "_layer_" + (p_117082_ ? 2 : 1) + (p_117083_ == null ? "" : "_" + p_117083_) + ".png";
        return ARMOR_LOCATION_CACHE.computeIfAbsent(s, ResourceLocation::new);
    }

    /*=================================== FORGE START =========================================*/

    /**
     * Hook to allow item-sensitive armor model. for HumanoidArmorLayer.
     */
    protected net.minecraft.client.model.Model getArmorModelHook(T entity, ItemStack itemStack, EquipmentSlot slot, A model) {
        return net.minecraftforge.client.ForgeHooksClient.getArmorModel(entity, itemStack, slot, model);
    }

    /**
     * More generic ForgeHook version of the above function, it allows for Items to have more control over what texture they provide.
     *
     * @param entity Entity wearing the armor
     * @param stack ItemStack for the armor
     * @param slot Slot ID that the item is in
     * @param type Subtype, can be null or "overlay"
     * @return ResourceLocation pointing at the armor's texture
     */
    public ResourceLocation getArmorResource(net.minecraft.world.entity.Entity entity, ItemStack stack, EquipmentSlot slot, @Nullable String type) {
        ArmorItem item = (ArmorItem)stack.getItem();
        String texture = item.getMaterial().getName();
        String domain = "minecraft";
        int idx = texture.indexOf(':');
        if (idx != -1) {
            domain = texture.substring(0, idx);
            texture = texture.substring(idx + 1);
        }
        String s1 = String.format(java.util.Locale.ROOT, "%s:textures/models/armor/%s_layer_%d%s.png", domain, texture, (usesInnerModel(slot) ? 2 : 1), type == null ? "" : String.format(java.util.Locale.ROOT, "_%s", type));

        s1 = net.minecraftforge.client.ForgeHooksClient.getArmorTexture(entity, stack, s1, slot, type);
        ResourceLocation resourcelocation = ARMOR_LOCATION_CACHE.get(s1);

        if (resourcelocation == null) {
            resourcelocation = new ResourceLocation(s1);
            ARMOR_LOCATION_CACHE.put(s1, resourcelocation);
        }

        return resourcelocation;
    }
    /*=================================== FORGE END ===========================================*/
}

 

 

Posted

Is Here:

Spoiler
public class ExampleTypeRender extends HumanoidMobRenderer<AbstractSkeleton, HumanoidModel<AbstractSkeleton>> {
    private static final ResourceLocation SKELETON_LOCATION = new ResourceLocation(ModCraft.MOD_ID, "textures/entity/example_entity/skeleton.png");

    public ExampleTypeRender(EntityRendererProvider.Context context) {
        this(context, ModelLayers.SKELETON, ModelLayers.SKELETON_INNER_ARMOR, ModelLayers.SKELETON_OUTER_ARMOR);
    }

    public ExampleTypeRender(EntityRendererProvider.Context context, ModelLayerLocation modelLayerLocation, ModelLayerLocation layerLocation, ModelLayerLocation location) {
        super(context, new SkeletonModel<>(context.bakeLayer(modelLayerLocation)), 0.3F);
        this.addLayer(new ExampleEntityLayer<>(this, new ExampleTypeModel(context.bakeLayer(layerLocation)), new ExampleTypeModel(context.bakeLayer(location))));
    }

    public ResourceLocation getTextureLocation(AbstractSkeleton skeleton) {
        return SKELETON_LOCATION;
    }

    protected boolean isShaking(AbstractSkeleton p_174389_) {
        return p_174389_.isShaking();
    }
}

 

 

Posted

I discovered the error: My Event Bus was in the wrong place.

Correct Place:

Spoiler
@Mod.EventBusSubscriber(modid = ModCraft.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
public class ModEventBusEvents {

    @SubscribeEvent
    public static void registerArmorLayers(EntityRenderersEvent.AddLayers event){
        LivingEntityRenderer render = event.getRenderer(EntityType.SKELETON);
        EntityModelSet models = Minecraft.getInstance().getEntityModels();
        ModelPart rootInner = models.bakeLayer(ModelLayers.SKELETON_INNER_ARMOR);
        ModelPart rootOuter = models.bakeLayer(ModelLayers.SKELETON_OUTER_ARMOR);
        RenderLayer<LivingEntity, EntityModel<LivingEntity>> renderlayer1 = new ExampleEntityLayer(render, new HumanoidModel(rootInner), new HumanoidModel(rootOuter));
        render.addLayer(renderlayer1);

       

    }


}

 

 

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • Hello , when I try to launch the forge installer it just crash with a message for 0,5 secondes. I'm using java 17 to launch it. Here's the link of the error :https://cdn.corenexis.com/view/?img=d/ma24/qs7u4U.jpg  
    • You will find the crash-report or log in your minecraft directory (crash-report or logs folder)
    • Use a modpack which is using these 2 mods as working base:   https://www.curseforge.com/minecraft/modpacks/life-in-the-village-3
    • inicie un mundo donde instale Croptopia y Farmer's Delight, entonces instale el addon Croptopia Delight pero no funciona. es la version 1.18.2
    • Hello all. I'm currently grappling with the updateShape method in a custom class extending Block.  My code currently looks like this: The conditionals in CheckState are there to switch blockstate properties, which is working fine, as it functions correctly every time in getStateForPlacement.  The problem I'm running into is that when I update a state, the blocks seem to call CheckState with the position of the block which was changed updated last.  If I build a wall I can see the same change propagate across. My question thus is this: is updateShape sending its return to the neighbouring block?  Is each block not independently executing the updateShape method, thus inserting its own current position?  The first statement appears to be true, and the second false (each block is not independently executing the method). I have tried to fix this by saving the block's own position to a variable myPos at inception, and then feeding this in as CheckState(myPos) but this causes a worse outcome, where all blocks take the update of the first modified block, rather than just their neighbour.  This raises more questions than it answers, obviously: how is a different instance's variable propagating here?  I also tried changing it so that CheckState did not take a BlockPos, but had myPos built into the body - same problem. I have previously looked at neighbourUpdate and onNeighbourUpdate, but could not find a way to get this to work at all.  One post on here about updatePostPlacement and other methods has proven itself long superceded.  All other sources on the net seem to be out of date. Many thanks in advance for any help you might offer me, it's been several days now of trying to get this work and several weeks of generally trying to get round this roadblock.  - Sandermall
  • Topics

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.