---
title: Miscellaneous Features
hide_meta: true
---

# Community Suggested Features

<Callout variant="info">
Credit to AceTheEldritchKing for this tip.
</Callout>

## 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

```java
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
```java
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.

```java
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.

<Callout variant="info">
Make sure the bone name matches the name in your Blockbench model exactly. If the name does not match, the override will never be selected.
</Callout>

### 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.

```java
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:

```java
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.

```java
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:

```java
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.

<Callout variant="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.
</Callout>

Fabric:

```java
@Override
public void onInitializeClient() {
    AzItemRendererRegistry.register(CustomHelmetItemRenderer::new, YourItemRegistry.YOUR_ARMOR_HELMET);
}
```

NeoForge:

```java
private void onClientSetup(FMLClientSetupEvent event) {
    event.enqueueWork(() -> {
        AzItemRendererRegistry.register(CustomHelmetItemRenderer::new, YourItemRegistry.YOUR_ARMOR_HELMET);
    });
}
```