Miscellaneous Features

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) {
@Override
public AzArmorBoneContext boneContext() {
return new AzArmorBoneContext() {
private AzBone armorLeggingTorsoBone;
public AzBone getArmorLeggingTorsoBone(AzBakedModel model) {
return model.getBone("newArmorBone").orElse(null);
}
@Override
public 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) {
@Override
public AzArmorBoneContext boneContext() {
return new AzArmorBoneContext() {
private AzBone armorLeggingTorsoBone;
public AzBone getArmorLeggingTorsoBone(AzBakedModel model) {
return model.getBone("newArmorBone").orElse(null);
}
@Override
public void grabRelevantBones(AzBakedModel model, AzArmorBoneProvider boneProvider) {
super.grabRelevantBones(model, boneProvider);
this.armorLeggingTorsoBone = this.getArmorLeggingTorsoBone(model);
}
@Override
public void applyBoneVisibilityBySlot(EquipmentSlot currentSlot) {
setAllVisible(false);
// Hide the legging torso bone initially
this.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 equipped
this.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.

Fabric:

@Override
public 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);
});
}