A volte non basta usare il formato del modello di Minecraft. Se devi aggiungere del rendering dinamico all'aspetto del tuo blocco, dovrai usare un BlockEntityRenderer.
Per esempio, facciamo in modo che il Blocco Contatore dell'articolo sui Blocchi-Entità mostri il numero di clic sulla sua faccia superiore.
Creare un BlockEntityRenderer
Anzitutto, dobbiamo creare un BlockEntityRenderer per il nostro CounterBlockEntity.
Nel creare un BlockEntityRenderer per il CounterBlockEntity, è importante inserire la classe nell'insieme delle fonti corretto, come src/client/, se il tuo progetto divide gli insiemi delle fonti tra client e server. Accedere a classi legate al rendering direttamente nell'insieme delle fonti src/main/ non è sicuro perché quelle classi potrebbero essere caricare su un server.
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
La nuova classe ha un costruttore con un BlockEntityRendererFactory.Context come parametro. Il Context ha alcune utilità per il rendering, come l'ItemRenderer o il TextRenderer. Inoltre, includendo un costruttore come questo, è possibile usare il costruttore come interfaccia funzionale per la 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
Dovresti registrare i renderer dei blocchi-entità nella tua classe ClientModInitializer.
BlockEntityRendererFactories è una registry che mappa ogni BlockEntityType con del codice di rendering personalizzato al rispettivo BlockEntityRenderer.
Disegnare su Blocchi
Ora che abbiamo un renderer, possiamo disegnare. Il metodo render viene chiamato ad ogni frame, ed è qui che la magia del rendering avviene.
Orientarsi
Anzitutto, dobbiamo bilanciare e ruotare il testo in modo che sia sul lato superiore del blocco.
INFO
Come suggerisce il nome, il MatrixStack è uno stack, il che significa che puoi inserirci (push) ed estrarne (pop) le trasformazioni. Una buona regola di base è inserirne uno nuovo all'inizio del metodo render ed estrarlo alla fine, in modo che il rendering di un blocco non influenzi gli altri.
Si possono trovare maggiori informazioni riguardo al MatrixStack nell'articolo sui Concetti Base del Rendering.
Per capire meglio le traslazioni e le rotazioni necessarie, visualizziamole. Nell'immagine, il blocco verde è dove il testo verrebbe disegnato, nel punto più in basso a sinistra del blocco in maniera predefinita:

Quindi dobbiamo inizialmente spostare il testo a metà del blocco sugli assi X e Z, poi muoverlo in cima al blocco lungo l'asse Y:

Questo si fa con una sola chiamata a translate:
java
matrices.translate(0.5, 1, 0.5);1
Ecco che abbiamo completato la tranlazione, mancano la rotazione e la scala.
Per impostazione predefinita il testo viene disegnato sul piano XY, quindi dobbiamo ruotarlo di 90 gradi attorno all'asse X perché sia orientato verso l'alto sul piano XZ:

Il MatrixStack non ha una funzione rotate, invece dobbiamo usare multiply e RotationAxis.POSITIVE_X:
java
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(90));1
Ora il testo è nella posizione corretta, ma è troppo grande. Il BlockEntityRenderer mappa l'intero blocco ad un cubo [-0.5, 0.5], mentre il TextRenderer usa come coordinate Y [0, 9]. Per questo dobbiamo rimpicciolirlo di un fattore di 18:
java
matrices.scale(1/18f, 1/18f, 1/18f);1
Ora la trasformazione completa ha questo aspetto:
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
Disegnare Testo
Come menzionato in precedenza, il Context passato al costruttore del nostro renderer ha un TextRenderer che possiamo usare per disegnare testo. Per questo esempio lo salveremo in un attributo.
Il TextRenderer ha metodi per misurare il testo (getWidth), il che è utile per centrarlo, e per disegnarlo (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
Il metodo draw accetta molti parametri, ma quelli più importanti sono:
- Il
Text(oString) da disegnare; - Le sue coordinate
xey; - Il valore RGB di
color; - La
Matrix4fche descrive come deve essere trasformato (peeeeer ottenerne una da unMatrixStack, possiamo usare.peek().getPositionMatrix()per ottenere laMatrix4fper la voce in cima).
Dopo tutto questo lavoro, eccone il risultato:


