Advanced Modding - Tile Entity Special Renderer

Goal

I want to show you how to create a rendering class to draw special models that cannot be created using the model files.

Difficulty


3/10 - Relatively Easy

Prerequisites

Forge Version

This Tutorial was created with Forge 11.14.3.1450 for Minecraft 1.8. If anything doesn't work with other versions, please contact me!


When do you need a Tile Entity Special Renderer?

A TileEntity special renderer (TESR) can be used to write a code-driven renderer for a TileEntity block. This renderer is not executed together with the other blocks, instead it is called every frame to draw the TileEntity onto the screen.

This has several advantages, but also some disadvantages.

The advantages are:

  • TESRs support mesh animations (Like rotation or scaling a cube over time. Note that you can also create texture animations with normal block models!)
  • TESRs can render stuff that depends on multiple properties of the TileEntity. This is also possible with model files, but would need a huge model file in order to define every possible state.
  • A TESR can render objects with much more detail than a model file can define. For instance, it is possible to render a solidified Item with a TESR (looking like an Item on the ground). With model files this is not possible in any way.

This may sound pretty cool already, but there is one great disadvantage:

  • A TESR is called every  frame. That means, that it can slow down Minecraft a lot if too many TileEntities with a TESR are rendered simultaneously. If you're planning to create blocks that are needed frequently, for instance energy pipes or something similar, consider the possible loss of performance before creating a (complicated) TESR.

So, when do you really need to use a TESR?

I've collected some scenarios where you need one by any means:

  • You want to render an Item from the TE's inventory or a solidified texture
  • You want to create a block with mesh animations
  • Your block is way to complicated to create a block model for it (for instance if you want to include too many states or too many faces, like for a sphere)

Creating a Tile Entity special renderer

The first thing we need is, of course, a new class. This will be our renderer, so we place it in the package client.render.blocks.

TileEntityTutorialRenderer.java:
package com.bedrockminer.tutorial.client.render.blocks;

import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;

public class TileEntityTutorialRenderer extends TileEntitySpecialRenderer {
}

As you can see, the class needs to extend TileEntitySpecialRenderer. This class contains the abstract method renderTileEntityAt, which we need to implement.

TileEntityTutorialRenderer.java:
@Override
public void renderTileEntityAt(TileEntity te, double x, double y, double z, float partialTick, int destroyStage) {

}

In this method we'd need to add the rendering code. I'll come back to that later.


First, we need to register the TESR. This can be done in the init() part of the client proxy, or in the registerBlockRenderer method of the BlockRenderRegister class, if you have one.

Note that you should register the block as normal, even if you use a Tile entity special renderer.

BlockRenderRegister.java:
public final class BlockRenderRegister {

    public static void registerBlockRenderer() {

        reg(ModBlocks.tutorialTileEntity);

        ClientRegistry.bindTileEntitySpecialRenderer(TileEntityTutorial.class, new TileEntityTutorialRenderer());
    }

    //=========================================================================

    public static String modid = Main.MODID;

    public static void reg(Block block) {
        Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(Item.getItemFromBlock(block), 0, new ModelResourceLocation(modid + ":" + block.getUnlocalizedName().substring(5), "inventory"));
    }
}

The registration method maps your renderer (new TileEntityTutorialRenderer()) with the class of your TileEntity (TileEntityTutorial.class). Every TileEntity of this class will now be rendered with the renderer we just created.

 

The normal block renderer needs to be turned off for this purpose. If your block extends the class BlockContainer, this is done automatically, if not you need to override the method getRenderType() and return -1. Depending on how you render the TE, it can be useful to make the block transparent as well, otherwise you might be able to see through the ground below the block.

BlockTutorialTileEntity.java:
@Override
public boolean isOpaqueCube() {
    return false;
}

@Override
public int getRenderType() {
    return -1;
}

One thing is very important: Currently,  Minecraft Forge does not support a TESR being used for the block's item. That means, you must define a normal item model. You can use a simple 2D texture or create a structure similar to the TE, but with less detail.

To make the block's destroy particles work correctly, you need to define a block model which sets the particle texture to the image you want to use. You can just create a normal cube model, it won't be rendered anyway.

Rendering Code

Now, let's get to the most important part: how do you render the TE?

 

I won't explain the actual rendering methods in this tutorial, because there are many different ways of rendering, however I'll show you how to set up the viewport so that the renderer is ready to go. The rendering methods are explained in other tutorials to which I provided links at the bottom.

 

There's only one thing we need to do in order to set up the viewport, namely moving the rendering matrix to the TE's position.

This can be done using these methods:

TileEntityTutorialRenderer.java:
@Override
public void renderTileEntityAt(TileEntity te, double x, double y, double z, float partialTick, int destroyStage) {
    GlStateManager.pushMatrix();
    GlStateManager.translate(x, y, z);

    //Your rendering code goes here

    GlStateManager.popMatrix();
}

These methods move the rendering matrix so that the Tile Entity reaches from rendering coordinates (0|0|0) to (1|1|1).

You can run Minecraft now if you want to, but the TileEntity block will not be visible at all, because it's not rendered. You can go to one of the rendering tutorials now to learn how to create rendering code.


You can download the code used in this tutorial as a .zip file from here. This file also contains rendering code created with the Vanilla Rendering tutorial.


Recommended tutorials to continue with

Advanced Modding:

  • Vanilla Rendering
  • Miner's Basic Rendering
  • Techne Models
  • In-code modeling
  • Rendering obj files

Comments and Questions:

If you want to report modding problems, please make sure to include the code in a pastebin link or something else! Don't just write "It doesn't work", otherwise your post will be deleted. For more complicated problems, please use the troubleshooter form.