Adding a Conditional Bone
In your armor renderer, call the createPipeline and return a new AzArmorRendererPipeline. In that new AzArmorRendererPipeline override the boneContext method you can now define your bone as below
public ExampleItemRenderer() {super(AzArmorRendererConfig.builder(MODEL, TEXTURE).setAnimatorProvider(ExampleAnimator::new).setPipelineContext(rendererPipeline -> new AzArmorRendererPipelineContext(rendererPipeline) {@Overridepublic AzArmorBoneContext boneContext() {return new AzArmorBoneContext() {private AzBone armorLeggingTorsoBone;public AzBone getArmorLeggingTorsoBone(AzBakedModel model) {return model.getBone("newArmorBone").orElse(null);}@Overridepublic void grabRelevantBones(AzBakedModel model, AzArmorBoneProvider boneProvider) {super.grabRelevantBones(model, boneProvider);this.armorLeggingTorsoBone = this.getArmorLeggingTorsoBone(model);}};}}).build());}
Displaying Conditional Bones Only When Certain Armor Items are Equipped
Like above after you add your bone, simply override applyBoneVisibilityBySlot like so and first hide it then unhide in the armor piece you want it to show in.boneContext
public ExampleItemRenderer() {super(AzArmorRendererConfig.builder(MODEL, TEXTURE).setAnimatorProvider(ExampleAnimator::new).setPipelineContext(rendererPipeline -> new AzArmorRendererPipelineContext(rendererPipeline) {@Overridepublic AzArmorBoneContext boneContext() {return new AzArmorBoneContext() {private AzBone armorLeggingTorsoBone;public AzBone getArmorLeggingTorsoBone(AzBakedModel model) {return model.getBone("newArmorBone").orElse(null);}@Overridepublic void grabRelevantBones(AzBakedModel model, AzArmorBoneProvider boneProvider) {super.grabRelevantBones(model, boneProvider);this.armorLeggingTorsoBone = this.getArmorLeggingTorsoBone(model);}@Overridepublic void applyBoneVisibilityBySlot(EquipmentSlot currentSlot) {setAllVisible(false);// Hide the legging torso bone initiallythis.setBoneVisible(this.armorLeggingTorsoBone, false);switch (currentSlot) {case HEAD -> setBoneVisible(this.head, true);case CHEST -> {setBoneVisible(this.body, true);setBoneVisible(this.rightArm, true);setBoneVisible(this.leftArm, true);}case LEGS -> {// Make the legging torso bone visible when the legging armor is equippedthis.setBoneVisible(this.armorLeggingTorsoBone, true);setBoneVisible(this.rightLeg, true);setBoneVisible(this.leftLeg, true);}case FEET -> {setBoneVisible(this.rightBoot, true);setBoneVisible(this.leftBoot, true);}case MAINHAND, OFFHAND -> { /* NO-OP */ }}}};}}).build());}
Use setBoneTextureOverrideProvider when you want one bone in a model to render with a different texture than the rest of the model. The provider receives the AzBone currently being rendered, so you can check the bone name and return the texture you want that bone to use.
A common use case is giving a cape, accessory, or other extra model part its own texture without creating a separate render layer.
public class GremlinRenderer extends AzEntityRenderer {private static final ResourceLocation MODEL = ResourceLocation.fromNamespaceAndPath("YOUR_MOD_ID", "geo/entity/gremlin.geo.json");private static final ResourceLocation TEXTURE = ResourceLocation.fromNamespaceAndPath("YOUR_MOD_ID", "textures/entity/gremlin.png");private static final ResourceLocation CAPE_TEXTURE = ResourceLocation.fromNamespaceAndPath("YOUR_MOD_ID", "textures/entity/gremlin_cape.png");public GremlinRenderer(EntityRendererProvider.Context context) {super(AzEntityRendererConfig.builder(MODEL, TEXTURE).setBoneTextureOverrideProvider(bone ->"bipedCape".equals(bone.getName()) ? CAPE_TEXTURE : null).setShadowRadius(0.5F).build(),context);}}
In this example, only the bone named bipedCape uses gremlin_cape.png. Every other bone returns null, which means AzureLib will keep using the normal entity texture.
Using Entity-Aware Bone Texture Overrides
If your texture override depends on the entity being rendered, use the entity-aware overload of setBoneTextureOverrideProvider.
This is useful when the same bone should use different textures based on entity state, variant, owner data, equipment, or any other entity-specific condition.
AzEntityRendererConfig.builder(MODEL, TEXTURE).setBoneTextureOverrideProvider((entity, bone) -> {if (entity != null && entity.isSuperman() && "bipedCape".equals(bone.getName())) {return CAPE_TEXTURE;}return null;}).setShadowRadius(0.5F).build();
The original bone-only overload is still supported:
AzEntityRendererConfig.builder(MODEL, TEXTURE).setBoneTextureOverrideProvider(bone ->"bipedCape".equals(bone.getName()) ? CAPE_TEXTURE : null).build();
Use the bone-only overload when the override only depends on the bone. Use the entity-aware overload when the override also needs access to the entity.
Using a Custom RenderType for a Bone
If the alternate bone texture needs a different render type, use setBoneRenderTypeOverrideProvider alongside the texture override.
AzEntityRendererConfig.builder(MODEL, TEXTURE).setBoneTextureOverrideProvider(bone ->"glowLayer".equals(bone.getName()) ? GLOW_TEXTURE : null).setBoneRenderTypeOverrideProvider(bone ->"glowLayer".equals(bone.getName())? RenderType.eyes(GLOW_TEXTURE): null).build();
If the render type depends on the entity being rendered, use the entity-aware overload:
AzEntityRendererConfig.builder(MODEL, TEXTURE).setBoneTextureOverrideProvider((entity, bone) -> {if (entity != null && entity.isGlowing() && "glowLayer".equals(bone.getName())) {return GLOW_TEXTURE;}return null;}).setBoneRenderTypeOverrideProvider((entity, bone) -> {if (entity != null && entity.isGlowing() && "glowLayer".equals(bone.getName())) {return RenderType.eyes(GLOW_TEXTURE);}return null;}).build();
If you only set setBoneTextureOverrideProvider, AzureLib will pick a default render type for the overridden texture. Use setBoneRenderTypeOverrideProvider only when the bone needs special rendering behavior, such as emissive-style rendering.
Render 3D Item in GUI instead of 2D texture for Armor
Call AzItemRendererRegistry#register() in your onInitializeClient for Fabric, or inside event.enqueueWork(...) in your FMLClientSetupEvent handler for NeoForge for your ArmorItem.
Warning
On NeoForge, setup events fire for every mod at the same time on parallel worker threads. Always register inside event.enqueueWork(...), which runs your code on the main thread after every mod's handler has finished, so your registrations can't race another mod's. Registering directly in the event handler can cause renderers to go missing at random between launches. Fabric runs its initializers one after another on a single thread, so no wrapper is needed there.
Fabric:
@Overridepublic void onInitializeClient() {AzItemRendererRegistry.register(CustomHelmetItemRenderer::new, YourItemRegistry.YOUR_ARMOR_HELMET);}
NeoForge:
private void onClientSetup(FMLClientSetupEvent event) {event.enqueueWork(() -> {AzItemRendererRegistry.register(CustomHelmetItemRenderer::new, YourItemRegistry.YOUR_ARMOR_HELMET);});}