Skip to content

Block Entity Guide

Markus Bordihn edited this page Jun 16, 2026 · 2 revisions

Block Entities

Block entities are the right choice for models that stay at a fixed block position. They are often cheaper than entities for decorations and machines because they do not need mob movement, pathfinding, or entity tracking.

✅ When To Use

Use a block entity for:

  • Shrines, statues, decorations, and displays.
  • Machines, chests, altars, or mimic-style block models.
  • Models that only need occasional idle animation.
  • Fixed models that do not walk around or use entity pathfinding.

A block entity cannot walk through the world like a mob. If the model needs real movement or AI, use an entity.

📁 Pack Structure

Block entity server profiles go into the data pack:

data/<namespace>/easy_model_entities/profiles/block_entity/<id>.json

Render profiles, models, and textures go into the resource pack:

assets/<namespace>/easy_model_entities/render_profiles/<id>.json
assets/<namespace>/easy_model_entities/models/<model>.bbmodel
assets/<namespace>/textures/block/<texture>.png

A server profile at profiles/block_entity/shrine.json is used as:

my_pack:block_entity/shrine

The render profile can still use a short client ID such as my_pack:shrine.

📄 Example Profile

Small shrine or mimic-style profile:

{
  "model_type": "block_entity",
  "preset_type": "animated_randomly",
  "client": {
    "render_profile": "my_pack:shrine"
  }
}
{
  "preset_type": "static",
  "texture": "my_pack:textures/block/shrine.png",
  "animation": {
    "mode": "random_idle"
  }
}

This expects the model at:

assets/my_pack/easy_model_entities/models/shrine.bbmodel

Add dimensions and rendering only when the default 1-block bounds do not fit the model.

Data pack server profile:

{
  "model_type": "block_entity",
  "preset_type": "animated_randomly",
  "version": "shrine-v1",
  "client": {
    "render_profile": "my_pack:shrine"
  },
  "dimensions": {
    "width": 1.0,
    "height": 1.35,
    "eye_height": 0.75
  }
}

Resource pack render profile:

{
  "preset_type": "static",
  "version": "shrine-v1",
  "model": "my_pack:easy_model_entities/models/shrine",
  "texture": "my_pack:textures/block/shrine.png",
  "animation": {
    "mode": "random_idle"
  }
}

🪄 Place

/easy_model_entities place_block my_pack:block_entity/shrine

With an explicit position:

/easy_model_entities place_block my_pack:block_entity/shrine ~ ~ ~

🎞️ Random Idle

Use animated_randomly in the server profile for EME host block entities. The client plays short animation bursts and rests between them, which is useful for shrines, mimics, and small decoration movement.

For render-only integrations, such as your own block entity rendered through EME, use random_idle in the render profile.

🧩 Developer Integration

Custom block entities implement EasyModelRenderable. Use the block entity render delegate in the renderer:

public class MyBlockEntityRenderer implements BlockEntityRenderer<MyBlockEntity> {

  private final EasyModelBlockEntityRenderDelegate<MyBlockEntity> delegate =
    EasyModelEntitiesClientApi.createBlockEntityRenderDelegate();

  @Override
  public void render(
    MyBlockEntity blockEntity,
    float partialTick,
    PoseStack poseStack,
    MultiBufferSource buffer,
    int packedLight,
    int packedOverlay) {
    EasyModelBlockEntityRenderOptions options =
      EasyModelBlockEntityRenderOptions.DEFAULT.withYawDegrees(180.0f);

    this.delegate.render(blockEntity, partialTick, poseStack, buffer, packedLight, options);
  }
}

For custom part animation, pass an animator with EasyModelBlockEntityRenderOptions:

EasyModelBlockEntityRenderOptions options =
  EasyModelBlockEntityRenderOptions.DEFAULT
    .withPartAnimator(animator)
    .withPartAnimationMode(EasyModelPartAnimationMode.ADD);

this.delegate.render(blockEntity, partialTick, poseStack, buffer, packedLight, options);

ADD keeps the automatic EME transform and adds your transform. REPLACE replaces the automatic transform for the part. See Custom Part Animation.

Read the public part structure when needed:

List<EasyModelPartDefinition> roots = this.delegate.rootModelParts(blockEntity);
List<EasyModelPartDefinition> parts = this.delegate.modelParts(blockEntity);

Clone this wiki locally