Entity metadata
Set entity flags, names, poses, health and display properties by name instead of by index and serializer ID.
SetEntityData updates an entity’s synced fields. Each entry is an index (which field), a serializer type (how it is encoded) and a value; the array ends with 0xff. Indices depend on the entity’s class hierarchy, so “glowing” is index 0 on everything while “health” is index 9 only on living entities. helpers.createEntityMetadata knows the layouts for a set of verified entity kinds and turns named fields into entries.
import { helpers } from "mc-protocol";
await client.sendPacket("SetEntityData", {
entityId: 42,
metadata: helpers.createEntityMetadata("player", {
customName: { text: "Steve", color: "gold" },
customNameVisible: true,
glowing: true,
health: 20,
skinParts: { cape: true, jacket: true, hat: true },
}),
});
Only the fields you pass are sent; the client keeps everything else. The codec appends the terminator.
createEntityMetadata(kind, fields)
kind selects the layout. Each kind inherits its parents’ fields, matching the entity class hierarchy in 26.2:
| Kind | Inherits | Own fields |
|---|---|---|
entity |
onFire, sneaking, sprinting, swimming, invisible, glowing, elytraFlying (one flag byte, index 0), airTicks, customName, customNameVisible, silent, noGravity, pose, frozenTicks |
|
living_entity |
entity | handActive, activeHand ("main" | "off"), riptide (flag byte 8), health, potionParticles, potionAmbient, arrows, beeStingers, sleepingPosition |
mob |
living_entity | noAi, leftHanded, aggressive (flag byte 15) |
armor_stand |
living_entity | small, arms, noBasePlate, marker (flag byte 15), headRotation, bodyRotation, leftArmRotation, rightArmRotation, leftLegRotation, rightLegRotation |
avatar |
living_entity | mainHand ("left" | "right"), skinParts |
player |
avatar | additionalHearts, score, leftShoulderParrot, rightShoulderParrot |
mannequin |
avatar | profile (wire-shaped ResolvableProfile), immovable, description |
interaction |
entity | width, height, responsive |
item |
entity | item |
item_frame, glow_item_frame |
entity | direction, item, rotation |
display |
entity | interpolationDelay, transformationInterpolationDuration, positionInterpolationDuration, translation, scale, leftRotation, rightRotation, billboard, brightness, viewRange, shadowRadius, shadowStrength, width, height, glowColor |
block_display |
display | blockState |
item_display |
display | item, displayType |
text_display |
display | text, lineWidth, backgroundColor, textOpacity, shadow, seeThrough, defaultBackground, alignment (flag byte 27) |
Field indices were taken from the wiki and checked against the order of defineId calls in the official 26.2 server classes. Mobs beyond these (creepers, villagers, boats, …) have their own extra fields; use metadataEntry for those rather than guessing an index.
Values
- Booleans are booleans;
1is rejected. pose:"standing","fall_flying","sleeping","swimming","spin_attack","crouching"(alias"sneaking"),"long_jumping","dying","croaking","using_tongue","sitting","roaring","sniffing","emerging","digging","sliding","shooting","inhaling".direction:"down","up","north","south","west","east".billboard:"fixed","vertical","horizontal","center".displayType:"none","third_person_left_hand","third_person_right_hand","first_person_left_hand","first_person_right_hand","head","gui","ground","fixed".customName,description: a string or text component object, ornullto clear.texton a text display cannot benull.item: acreateSlotresult or an item name.potionParticles: an array ofcreateParticleresults.sleepingPosition:{ x, y, z }block coordinates, ornull.- Rotations (
headRotation, …),translation,scale:{ x, y, z }floats.leftRotation,rightRotation:{ x, y, z, w }. brightness:{ block, sky }with each 0–15, ornullfor no override.glowColor: ARGB color ornullfor no override.backgroundColor: ARGB (see colors).textOpacity: 0–255; the helper converts it to the signed byte the wire wants.leftShoulderParrot,rightShoulderParrot: a parrot variant ID, ornullfor empty.skinParts: an object of booleans out ofcape,jacket,leftSleeve,rightSleeve,leftPants,rightPants,hat.
Flag bytes
Several fields share one byte on the wire. If you set any of them, the whole byte is sent and the bits you did not mention are 0. To make a player glow without clearing their sneaking state, send both:
helpers.createEntityMetadata("entity", { glowing: true, sneaking: true });
// [{ key: 0, type: "byte", value: 0x42 }]
Validation
Unknown field names throw with the kind in the message (Unknown display metadata field: text). Unknown kinds throw. Integers are range-checked against their wire width; block positions against the packed Position limits; enums against their name lists. Numeric values must be finite.
metadataEntry(index, type, value)
For fields the named layouts do not cover. index is 0–254 (255 is the terminator), type is a 26.2 serializer name from helpers.METADATA_TYPES ("byte", "int", "float", "optional_block_state", "villager_data", …), and value is the shape the codec expects for that type.
// Enderman carried block (index 16, Optional Block State): a block state ID or null.
helpers.metadataEntry(16, "optional_block_state", 1);
// Villager data (index 18): registry IDs for type, profession and level.
helpers.metadataEntry(18, "villager_data", { villagerType: 2, villagerProfession: 5, level: 1 });
Mix both in one packet by concatenating arrays:
metadata: [
...helpers.createEntityMetadata("mob", { customName: "Trader", noAi: true }),
helpers.metadataEntry(18, "villager_data", { villagerType: 2, villagerProfession: 5, level: 1 }),
]
What you get back
helpers.createEntityMetadata("text_display", { text: "Hi", billboard: "center", shadow: true });
// [
// { key: 15, type: "byte", value: 3 },
// { key: 23, type: "component", value: "Hi" },
// { key: 27, type: "byte", value: 1 },
// ]
Entries are sorted by index. Decoded packets return type as { value, translation }, so a decoded entry’s type is { value: 5, translation: "component" } rather than the bare string.
Types
EntityMetadataEntry, EntityMetadataKinds, EntityKind, MetadataType, Pose, Direction, Billboard, ItemDisplayType, Quaternion, SkinParts, and one …Fields interface per kind (EntityFields, LivingEntityFields, PlayerFields, TextDisplayFields, …), all under helpers.