---
title: Entity metadata
description: Set entity flags, names, poses, health and display properties by name instead of by index and serializer ID.
---

[SetEntityData](/packets/play/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.

```ts
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](https://minecraft.wiki/w/Java_Edition_protocol/Entity_metadata) 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`](#metadataentryindex-type-value) 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](/docs/particles#createparticlename-data)).
- `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:

```ts
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.

```ts
// 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:

```ts
metadata: [
  ...helpers.createEntityMetadata("mob", { customName: "Trader", noAi: true }),
  helpers.metadataEntry(18, "villager_data", { villagerType: 2, villagerProfession: 5, level: 1 }),
]
```

## What you get back

```ts
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`.
