Adding and Using the Armor Layer
Overview
The AzArmorLayer is a built-in render layer designed for per-bone dynamic armor rendering. It supports rendering both vanilla-style armor and custom armor models registered via AzureLib's AzArmorRendererRegistry
. This layer works seamlessly with animated models, allowing armor or skull blocks to be rendered on specific bones of an entity, providing incredible flexibility for custom animations and render configurations.
Key features include:
- Support for vanilla armor models and custom armor models.
- Dynamic rendering of custom per-bone armor pieces.
- Per-bone rendering of skull blocks using Mojang's
SkullBlockRenderer
.
This guide will walk you through setting up and customizing the AzArmorLayer
.
Setup Instructions
Step 1: Understanding the Basics
The AzArmorLayer
works by:
- Collecting armor or head equipment from an entity's inventory for each bone.
- Automatically determining which equipment slot's item stack belongs to a specific bone using the bone names.
- Rendering the appropriate model for vanilla or custom armor while applying transformations to match your model's animation.
Step 2: Adding the Armor Layer to Your Renderer
To use the AzArmorLayer
, you need to add it as a render layer in your entity's renderer configuration. Below is an example:
import mod.azure.azurelib.rewrite.render.layer.AzArmorLayer;public class ExampleEntityRenderer extends AzEntityRenderer<ExampleEntity> {private static final ResourceLocation MODEL_LOCATION =ResourceLocation.fromNamespaceAndPath("yourmodid", "geo/example_model.geo.json");private static final ResourceLocation TEXTURE_LOCATION =ResourceLocation.fromNamespaceAndPath("yourmodid", "textures/entity/example_model.png");public ExampleEntityRenderer(EntityRendererProvider.Context context) {super(AzEntityRendererConfig.<ExampleEntity>builder(MODEL_LOCATION, TEXTURE_LOCATION).addRenderLayer(new AzArmorLayer<>() {// Override methods here}) // Add the armor layer.build(),context);}}
This configuration adds the AzArmorLayer
to your entity's renderer pipeline, allowing it to automatically render armor and head equipment dynamically.
Step 3: Customizing Per-Bone Armor Rendering
The AzArmorLayer
provides methods to allow customization of how armor is rendered for specific bones. Below are a few key methods to override and customize.
1. Determine Armor Items for Bones
You can customize which armor items are rendered for specific bones by overriding getArmorItemForBone
. For example:
@Overrideprotected ItemStack getArmorItemForBone(AzRendererPipelineContext<ExampleEntity> context, AzBone bone) {return switch (bone.getName()) {case "helmetBone" -> context.animatable().getItemBySlot(EquipmentSlot.HEAD);case "chestPlateBone" -> context.animatable().getItemBySlot(EquipmentSlot.CHEST);case "leggingsBone" -> context.animatable().getItemBySlot(EquipmentSlot.LEGS);case "bootsBone" -> context.animatable().getItemBySlot(EquipmentSlot.FEET);default -> null;};}
This ensures items are associated with specific bones based on their name and corresponding equipment slot.
2. Custom Transformations for Armor Rendering
If you need to adjust transformations (such as scaling or positioning) for any armor piece before it's rendered, you can override the prepModelPartForRender
method:
@Overrideprotected void prepModelPartForRender(AzRendererPipelineContext<ExampleEntity> context, AzBone bone, ModelPart sourcePart) {context.poseStack().translate(0.0F, 0.2F, 0.0F);context.poseStack().scale(1.2F, 1.2F, 1.2F);super.prepModelPartForRender(context, bone, sourcePart);}
This applies custom adjustments, such as translating the armor upwards slightly or scaling it larger before rendering.
3. Customize Skull Blocks as Helmets
The AzArmorLayer
also supports rendering skull blocks (e.g., player heads) dynamically for specific bones. You can override the renderSkullAsArmor
method to fine-tune how skulls are positioned and scaled:
@Overrideprotected void renderSkullAsArmor(AzRendererPipelineContext<ExampleEntity> context, AzBone bone, ItemStack stack, AbstractSkullBlock skullBlock) {context.poseStack().scale(1.5F, 1.5F, 1.5F); // Make the skull largercontext.poseStack().translate(0.0D, 0.25D, 0.0D); // Adjust positionsuper.renderSkullAsArmor(context, bone, stack, skullBlock);}
Troubleshooting
-
Armor Doesn't Display:
- Make sure the bone name in
getArmorItemForBone
matches the bone names in your.geo
model file. - Check that the entity has items equipped in the corresponding armor slots.
- Make sure the bone name in
-
Incorrect Scaling/Positioning:
- Use
prepModelPartForRender
to fix scaling or positioning issues. - Make sure vanilla armor models (like leggings or boots) are not overriding any custom behaviors.
- Use
-
Custom Models Not Used:
- Verify the armor renderer is registered in
AzArmorRendererRegistry
. - Ensure your custom model classes implement the necessary interfaces for dynamic rendering.
- Verify the armor renderer is registered in
Example Use Case
Scenario: You have a custom animated model for an entity, where:
- A helmet must be rendered on the
helmetBone
. - A player head (skull block) should be rendered dynamically if equipped as a helmet.
Here’s how you would set it up in the AzArmorLayer
:
@Overrideprotected ItemStack getArmorItemForBone(AzRendererPipelineContext<ExampleEntity> context, AzBone bone) {return switch (bone.getName()) {case "helmetBone" -> context.animatable().getItemBySlot(EquipmentSlot.HEAD);case "chestPlateBone" -> context.animatable().getItemBySlot(EquipmentSlot.CHEST);default -> null;};}@Overrideprotected void renderSkullAsArmor(AzRendererPipelineContext<ExampleEntity> context, AzBone bone, ItemStack stack, AbstractSkullBlock skullBlock) {context.poseStack().scale(1.2F, 1.2F, 1.2F);context.poseStack().translate(0.0D, 0.4D, 0.0D);super.renderSkullAsArmor(context, bone, stack, skullBlock);}
With this setup:
- For the
helmetBone
, either a helmet or a skull block will render dynamically. - Additional custom scaling and translation is applied to ensure the skull looks correct on the animated model.