Іноді використання формату моделі Minecraft недостатньо. Якщо вам потрібно додати динамічне промальовування до візуальних елементів вашого блоку, вам потрібно буде використовувати BlockEntityRenderer.
Наприклад, нумо зробимо так, щоб блок лічильника зі статті про блокові-сутностей показував кількість натискань у зверху.
Створення BlockEntityRenderer
Для початку, нам треба створити BlockEntityRenderer для CounterBlockEntity.
Створюючи BlockEntityRenderer для CounterBlockEntity, важливо помістити клас у відповідний вихідний набір, наприклад src/client/, якщо ваш проєкт використовує розділені вихідні набори для клієнта та сервера. Доступ до пов’язаних із промальовуванням класів безпосередньо у вихідному наборі src/main/ небезпечний, оскільки ці класи можуть бути завантажені на сервер.
java
public class CounterBlockEntityRenderer implements BlockEntityRenderer<CounterBlockEntity> {
public CounterBlockEntityRenderer(BlockEntityRendererFactory.Context context) {
}
@Override
public void render(CounterBlockEntity entity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay) {
}
}1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
Новий клас має конструктор із BlockEntityRendererFactory.Context як параметр. У Context є кілька корисних штук промальовування, наприклад ItemRenderer або TextRenderer. Крім того, включивши такий конструктор, стає можливим використовувати конструктор як сам функціональний інтерфейс BlockEntityRendererFactory:
java
public class FabricDocsBlockEntityRenderer implements ClientModInitializer {
@Override
public void onInitializeClient() {
BlockEntityRendererFactories.register(ModBlockEntities.COUNTER_BLOCK_ENTITY, CounterBlockEntityRenderer::new);
}
}1
2
3
4
5
6
2
3
4
5
6
Ви маєте зареєструвати промальовування блокових сутностей у своєму класі ClientModInitializer.
BlockEntityRendererFactory — це реєстр, який зіставляє кожен BlockEntityType зі спеціальним кодом відтворення на відповідний BlockEntityRenderer.
Малювання на блоках
Тепер, коли у нас є промальовування, ми можемо малювати. Метод render викликається кожним кадром, і саме в ньому відбувається магія промальовування.
Пересування
По-перше, нам потрібно змістити та повернути текст так, щоб він знаходився вище блоку.
INFO
Як випливає з назви, MatrixStack є стосом, що означає, що ви можете надсилати та витягувати перетворення. Гарне емпіричне правило полягає в тому, щоб додати новий блок на початку методу render і відкрити його в кінці, щоб промальовування одного блоку не впливав на інші.
Більше інформації про MatrixStack можна знайти в статті про базові концепції промальовування.
Щоб полегшити розуміння необхідних перекладів і поворотів, візуалізуємо їх. На цьому зображенні зелений блок – це місце, де буде намальовано текст, за замовчуванням у найдальшій нижній лівій точці блоку:

Отже, спочатку нам потрібно перемістити текст наполовину блоку по осях X і Z, а потім перемістити його вгору до верхньої частини блоку по осі Y:

Це робиться за допомогою одного виклику translate:
java
matrices.translate(0.5, 1, 0.5);1
Ось і переклад зроблено, обертання і масштаб залишаються.
За замовчуванням текст малюється на площині X-Y, тому нам потрібно повернути його на 90 градусів навколо осі X, щоб він був спрямований вгору на площині X-Z:
![Зелений блок у верхній центральній точці, спрямований догори] (/assets/develop/blocks/block_entity_renderer_3.png)
MatrixStack не має функції rotate, натомість нам потрібно використовувати multiply і RotationAxis.POSITIVE_X:
java
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(90));1
Тепер текст у правильному положенні, але він завеликий. BlockEntityRenderer промальовує весь блок на куб [-0.5, 0.5], тоді як TextRenderer використовує координати Y [0, 9]. Таким чином, нам потрібно зменшити його в 18 разів:
java
matrices.scale(1/18f, 1/18f, 1/18f);1
Тепер усе перетворення виглядає так:
java
matrices.push();
matrices.translate(0.5, 1, 0.5);
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(90));
matrices.scale(1/18f, 1/18f, 1/18f);1
2
3
4
2
3
4
Малювання тексту
Як згадувалося раніше, Context, переданий у конструктор нашого промальовування, має TextRenderer, який ми можемо використовувати для малювання тексту. Для цього прикладу ми збережемо його в полі.
TextRenderer має методи для вимірювання тексту (getWidth), що корисно для центрування, і для його малювання (draw).
java
String text = entity.getClicks() + "";
float width = textRenderer.getWidth(text);
// draw the text. params:
// text, x, y, color, shadow, matrix, vertexConsumers, layerType, backgroundColor, light
textRenderer.draw(
text,
-width/2, -4f,
0xffffff,
false,
matrices.peek().getPositionMatrix(),
vertexConsumers,
TextRenderer.TextLayerType.SEE_THROUGH,
0,
light
);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Метод draw приймає багато параметрів, але найважливіші з них:
Text(абоString) для малювання;- його координати
xіy; - значення 'кольору' RGB;
Matrix4f, що описує, як його слід трансформувати (щоб отримати один ізMatrixStack, ми можемо використати.peek().getPositionMatrix(), щоб отриматиMatrix4fдля самого верхнього запису).
І після всієї цієї роботи ось результат:


