Display Entities

Display entities share a common set of world-rendering options and then add a few type-specific fields for blocks, items, or text.

Footprint

Only the entities you summon: eachsummon creates one display entity. No objective, storage, forceloaded chunk, tick or load function.

Shared display settings

All display entities inherit these properties from the shared DisplayEntity base type:

  • billboardMode - how the display faces the camera (FIXED, VERTICAL, HORIZONTAL, CENTER).
  • brightness - overrides the block and sky light levels used for rendering (Brightness(block = 15, sky = 15), 0 to 15).
  • glowColorOverride - replace the outline color with a custom RGB value.
  • height / width - size of the box used to cull the display, in blocks (0f, the default, never culls).
  • interpolationDuration / startInterpolation - animate transformation changes over time.
  • shadowRadius / shadowStrength - control the projected shadow.
  • teleportDuration - ticks over which a teleport is smoothed, 0 to 59.
  • transformation - combine translation, rotation, scale, or custom matrices.
  • viewRange - multiplier of the render distance, 1f by default.

Every entity field (tags, customName, glowing...) is available too, they come from the shared EntitySummonData base and are written first.

Entity Displays

Entity displays are used to display blocks/items/text in the world. You can define multiple properties for the display, such as transformation, billboard mode, shadow etc.

val entityDisplay = blockDisplay {
	blockState(Blocks.GRASS_BLOCK) {
		properties {
			this["snowy"] = true
		}
	}

	transformation {
		leftRotation {
			quaternionNormalized(0.0, 0.0, 0.0, 1.0)
		}

		scale = Vec3f(2, 2, 2)

		translation {
			y = 2f
		}
	}

	billboardMode = BillboardMode.CENTER
	shadowRadius = 0.5f
}

summon(entity = entityDisplay.entityType, pos = vec3(0, 0, 0), nbt = entityDisplay.toNbt())
Kotlin

This summons a snowy grass block at 0 0 0, scaled by 2 and translated 2 blocks up, facing the camera on both axes.

Block Displays

Block displays are used to display blocks in the world. They are created by calling the blockDisplay() DSL.

val blockDisplay = blockDisplay {
	blockState(Blocks.GRASS_BLOCK) {
		properties {
			this["snowy"] = true
		}
	}
}
Kotlin

Item Displays

Item displays are used to display items in the world. They are created by calling itemDisplay() DSL.

The optional displayMode property uses ItemDisplayModelMode, which serializes to the lowercase values Minecraft expects:

  • FIRSTPERSON_LEFTHAND
  • FIRSTPERSON_RIGHTHAND
  • FIXED
  • GROUND
  • GUI
  • HEAD
  • NONE
  • ON_SHELF
  • THIRDPERSON_LEFTHAND
  • THIRDPERSON_RIGHTHAND
val itemDisplay = itemDisplay {
	item(Items.DIAMOND_SWORD) {
		customName(textComponent("test"))

		enchantments {
			enchantment(Enchantments.SHARPNESS, 1)
			enchantment(Enchantments.UNBREAKING, 3)
		}

		attributeModifiers {
			modifier(
				type = Attributes.ATTACK_DAMAGE,
				amount = 1.0,
				name = "bonus_damage",
				operation = AttributeModifierOperation.ADD_VALUE,
			)
		}
	}
}
Kotlin

Text Displays

Text displays are used to display text in the world. They are created by calling textDisplay() DSL.

alignment uses TextAlignment, which currently supports:

  • LEFT
  • CENTER
  • RIGHT
val textDisplay = textDisplay {
	text("test", Color.RED) {
		bold = true
	}
}
Kotlin

text takes any text component, so several styled parts can be joined with +:

val legendary = textDisplay {
	text = textComponent("Legendary ", Color.GOLD) + textComponent("Sword")
}

summon(legendary.entityType, vec3(), legendary.toNbt())
Kotlin
summon minecraft:text_display ~ ~ ~ {text:[{type:text,text:""},{type:text,color:gold,text:"Legendary "},{type:text,text:Sword}]}
Mcfunction

Transformations

Transformations are used to modify the translation, left/right rotations and scale of displays. They are created by calling transformation DSL. You can also apply directly matrix transformations and use quaternions, axis angles or use Euler angles for rotations. eulerAngles(x, y, z) takes radians and applies the rotations like JOML's rotateXYZ.

transformation {
	leftRotation {
		quaternionNormalized(0.0, 0.0, 0.0, 1.0)
	}

	scale = Vec3f(2, 2, 2)

	translation {
		y = 2f
	}
}
Kotlin
transformation:{left_rotation:[0.0f,0.0f,0.0f,1.0f],right_rotation:[0.0f,0.0f,0.0f,1.0f],scale:[2.0f,2.0f,2.0f],translation:[0.0f,2.0f,0.0f]}
Mcfunction

A transformation holding a matrix (matrix { row(...) }, invert(), compose()) is written as its 16 floats row by row, which the game decomposes when loading the entity.

The game applies the parts to the model in this order: rightRotation, scale, leftRotation, then translation. Rotations and scale work around the pivot of each display type:

Display Pivot Scaled by 2
block_display Bottom north-west corner of the block Grows towards +X, +Y and +Z
item_display Center of the item Grows evenly around the entity
text_display Bottom center of the text Grows upwards and to both sides

The diagram below draws each display at its entity position, the pivot marked by a dot:

block_display: bottom north-west corner
item_display: center
text_display: bottom center

Without rotations, centering a block display on its entity takes a translation of -0.5 times the scale on each axis.

The editor below previews a transformation on each display type, from any angle, with the matching Kotlin and an equivalent summon command:

Display type
Billboard
Keeps the entity's own rotation: turn the camera, the model stays put.
X
Y
Z
The model's center sits at 0.5, 0.5, 0.5 blocks from the entity.
translation
leftRotation (degrees)
scale
rightRotation, applied before scale
Differs from leftRotation only when the scale isn't uniform.
rightRotation (degrees)
val display = blockDisplay {
	blockState(Blocks.GRASS_BLOCK)
}

summon(display.entityType, vec3(), display.toNbt())
Kotlin
Both tabs round rotations to 4 decimals, so the command is equivalent to Kore's output, not identical to it.

Quaternion and Matrix operators (+, -, *, /) return a new value and leave both operands untouched, while named methods like normalize(), slerp() or multiply() modify the receiver. Quaternion.IDENTITY and Matrix.IDENTITY give a new instance on each access, so modifying one never affects the others.

Transformations can also be combined:

  • a.interpolate(b, t) returns the transformation t of the way from a (0) to b (1).
  • a.invert() returns the transformation undoing a, as a matrix.
  • a.decompose() splits a matrix transformation back into translation, rotations and scale.

Reference: Display

Interpolations

You can convert your display entity into an "interpolable" display entity by calling interpolable() on it inside a function. This will allow you to interpolate between the current transformation and the target transformation in a given time. The interpolable gets a UUID hashed from the pack name, the display and its position, so it stays the same across builds and two identical displays still get different ones.

val interpolableEntityDisplay = blockDisplay {
	blockState(Blocks.STONE)
}.interpolable(position = vec3(0, 0, 0))

interpolableEntityDisplay.summon()

interpolableEntityDisplay.interpolateTo(duration = 2.seconds) {
	translation {
		y = 2f
	}
}
Kotlin

Interpolation is especially useful when you want display entities to move or morph smoothly between ticks without rebuilding the entity from scratch.

OOP Entity Handles

After creating an interpolable, call toEntity() to get a typed OOP entity handle (BlockDisplayEntity, ItemDisplayEntity, or TextDisplayEntity). This gives access to all Entity extension functions such as kill, teleportTo, addTag, and more.

val display = blockDisplay {
	blockState(Blocks.STONE)
}.interpolable(vec3(0, 64, 0))

display.summon()

// toEntity() is typed as Entity, so cast when you want the specific subclass
val entity: BlockDisplayEntity = display.toEntity() as BlockDisplayEntity

// every Entity OOP extension works on the handle
entity.addTag("my_display")
entity.teleportTo(0, 65, 0)
entity.kill()
Kotlin

You can also construct the typed entity handles directly when you already have a UUID:

val uuid = uuid("12345678-1234-1234-1234-123456789012")
val block = BlockDisplayEntity(uuid)
val item  = ItemDisplayEntity(uuid)
val text  = TextDisplayEntity(uuid)
Kotlin

All three target their entity with @e[limit=1,nbt={UUID:[I;...]},type=minecraft:<type>].

These handle classes live in the oop module and extend Entity, so every entity-scoped extension applies to them - see Entities & Players for the full list.