Skip to content
mc-protocol
Esc
↑↓navigate↵open⌘Jpreview
On this page

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; 1 is 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, or null to clear. text on a text display cannot be null.
  • item: a createSlot result or an item name.
  • potionParticles: an array of createParticle results.
  • sleepingPosition: { x, y, z } block coordinates, or null.
  • Rotations (headRotation, …), translation, scale: { x, y, z } floats. leftRotation, rightRotation: { x, y, z, w }.
  • brightness: { block, sky } with each 0–15, or null for no override. glowColor: ARGB color or null for 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, or null for empty.
  • skinParts: an object of booleans out of cape, 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.

Was this page helpful?