AzureLib

Adding Block and Item Layer

How to use the Block and Item Layer

Overview

The Block and Item Layer feature allows you to easily render blocks and item stacks onto predefined bones of a model using AzureLib's rendering pipeline.

The AzBlockAndItemLayer handles the rendering logic for these elements by:

  • Applying transformations specific to the bones associated with items/blocks.
  • Rendering the correct visuals for items and blocks by using Minecraft’s rendering utilities.

Setup Instructions

Step 1: Add the Block and Item Layer to Your Renderer

Adding the AzBlockAndItemLayer to your renderer is straightforward. Use the addRenderLayer() method to register the layer in your entity renderer's configuration. Below is an example configuration:

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 AzBlockAndItemLayer<ExampleEntity>() {
// Override methods here
})
.build(),
context
);
}
}

Step 3: Customize Bone-Item Relationships

The AzBlockAndItemLayer provides several methods to define relationships between bones and the items or blocks they render:

  1. itemStackForBone:

    • Associates an ItemStack with a specific bone.
    • In the example, rightHandBone and leftHandBone are linked to the main and off-hand slots of the entity.
    @Override
    public ItemStack itemStackForBone(AzBone bone, ExampleEntity animatable) {
    return switch (bone.getName()) {
    case "rightHandBone" -> animatable.getItemBySlot(EquipmentSlot.MAINHAND);
    case "leftHandBone" -> animatable.getItemBySlot(EquipmentSlot.OFFHAND);
    default -> null;
    };
    }
  2. getTransformTypeForStack:

    • Determines the display context for rendering items.
    • For example:
      • ItemDisplayContext.THIRD_PERSON_RIGHT_HAND for the right hand.
      • ItemDisplayContext.THIRD_PERSON_LEFT_HAND for the left hand.
    @Override
    protected ItemDisplayContext getTransformTypeForStack(AzBone bone, ItemStack stack, ExampleEntity animatable) {
    return switch (bone.getName()) {
    case "rightHandBone" -> ItemDisplayContext.THIRD_PERSON_RIGHT_HAND;
    case "leftHandBone" -> ItemDisplayContext.THIRD_PERSON_LEFT_HAND;
    default -> ItemDisplayContext.NONE;
    };
    }
  3. renderItemForBone:

    • Applies specific transformations for the item before rendering.
    • In the example:
      • A rotation of 270° is applied to align the item correctly.
      • The position is adjusted with a small translation.
    @Override
    protected void renderItemForBone(AzRendererPipelineContext<ExampleEntity> context, AzBone bone, ItemStack itemStack, ExampleEntity animatable) {
    context.poseStack().mulPose(Axis.XP.rotationDegrees(270));
    context.poseStack().translate(0.0D, 0.1D, -0.1D);
    super.renderItemForBone(context, bone, itemStack, animatable);
    }
  4. renderBlockForBone:

    • Similar to renderItemForBone, but handles BlockState rendering instead of items.
    • Adjustments are made to ensure the block fits naturally within the bone space:
      • A default scaling factor of 0.5f reduces the block to an appropriate size.
    @Override
    protected void renderBlockForBone(AzRendererPipelineContext<ExampleEntity> context, AzBone bone, BlockState blockState, ExampleEntity animatable) {
    context.poseStack().pushPose();
    context.poseStack().translate(-0.25f, -0.25f, -0.25f);
    context.poseStack().scale(0.5f, 0.5f, 0.5f);
    super.renderBlockForBone(context, bone, blockState, animatable);
    }

Example Use Case

Scenario: Say you have an entity model where the right hand holds a sword, and the left hand holds a shield.

  1. Define bones in your model called rightHandBone and leftHandBone.
  2. Associate the bones with your entity's inventory slots using itemStackForBone.
  3. Set the appropriate display context for each bone with getTransformTypeForStack.
  4. Apply specific pose adjustments for how the item should look when held using renderItemForBone.

By following these steps, the entity model will dynamically render the correct items or blocks held in its hands, fully animated and interacting with your AzureLib model.

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 AzBlockAndItemLayer<ExampleEntity>() {
@Override
public ItemStack itemStackForBone(AzBone bone, ExampleEntity animatable) {
return switch (bone.getName()) {
case "rightHandBone" -> animatable.getItemBySlot(EquipmentSlot.MAINHAND);
case "leftHandBone" -> animatable.getItemBySlot(EquipmentSlot.OFFHAND);
default -> null;
};
}
@Override
protected ItemDisplayContext getTransformTypeForStack(AzBone bone, ItemStack stack, ExampleEntity animatable) {
return switch (bone.getName()) {
case "rightHandBone" -> ItemDisplayContext.THIRD_PERSON_RIGHT_HAND;
case "leftHandBone" -> ItemDisplayContext.THIRD_PERSON_LEFT_HAND;
default -> ItemDisplayContext.THIRD_PERSON_RIGHT_HAND;
};
}
@Override
protected void renderItemForBone(AzRendererPipelineContext<ExampleEntity> context, AzBone bone, ItemStack itemStack, ExampleEntity animatable) {
context.poseStack().mulPose(Axis.XP.rotationDegrees(270));
context.poseStack().translate(0.0D, 0.1D, -0.1D);
super.renderItemForBone(context, bone, itemStack, animatable);
}
})
.build(),
context
);
}
}

Troubleshooting

  1. Items/Blocks Not Rendering:

    • Ensure the bone name in your itemStackForBone/blockStateForBone logic matches the name declared in the model file.
  2. Incorrect Positioning:

    • Use the renderItemForBone or renderBlockForBone methods to fine-tune the rotation, translation, and scaling.
  3. Performance Issues:

    • Verify that your item stack/block state providers aren’t performing excessive calculations. Cache results when possible.