<!-- https://minecraftdocs.dev/systems/entities/entity-anatomy — this page as markdown. The book's index: https://minecraftdocs.dev/llms.txt; the whole book in one file: https://minecraftdocs.dev/llms-full.txt -->

# Entity anatomy

> Verified against **Minecraft 26.3** · Part VI · What an entity *is*: one `EntityType` from the registry, through a factory, to a live object the level ticks.

You type */summon pig*, and by the next tick there is a pig standing where
you are. Between the command and the animal are three objects and one factory
call: a `ResourceKey` in `EntityTypeIds`, the `EntityType` that `EntityTypes`
built from it before any world existed, and the `Entity` that the type's
`EntityType.EntityFactory` returns. This page is the vocabulary of that chain,
and the rest of Part VI is built on it. The surprise is what happens when the
kind is one nobody has heard of, because that depends entirely on which of two
doors it came through. An entity arriving over the network is named by a
**number**, the registry index inside a `ClientboundAddEntityPacket`; an entity
read back off disk is named by a **string**, the *id* field in the region file.
Those two doors give opposite answers to the same bad name.
`Registries.ENTITY_TYPE` is one of the few **defaulted** registries, its
default is *pig*, and `DefaultedMappedRegistry` overrides nine methods, seven
of which hand that default back — five for a miss, among them
`DefaultedMappedRegistry.byId` and `DefaultedMappedRegistry.getValue`, and
`DefaultedMappedRegistry.getAny` and `DefaultedMappedRegistry.getDefaultKey`
always.
So the numeric door cannot fail: `ByteBufCodecs.registry` decodes through
`IdMap.byIdOrThrow`, which cannot throw here because
`DefaultedMappedRegistry.byId` never returns null, and a pig walks out of the
packet. The string door is not defaulted at all, because `EntityType.CODEC` is
`Registry.byNameCodec` and resolves through a lookup the subclass leaves alone
— as does `DefaultedMappedRegistry.getOptional`, the one override that
deliberately answers empty. So the same unknown name in a region file yields
nothing: `EntityType.create` logs *Skipping Entity with id …* and leaves a hole
where the entity was. The default reaches the network and never reaches your
save file.

## The cast

| class | what it decides | thread |
|---|---|---|
| `EntityType` | one registered kind: its factory, category, frozen dimensions, feature flags, and the two numbers that decide how it reaches clients | built in a class initialiser, read from both game threads and the worldgen executor after |
| `EntityTypes` | which 161 kinds exist and what every one of them is *sized* like — the most useful single table in the package | class initialiser, once |
| `Entity` | position, box, network id, synched values, vehicle, removal reason. Deliberately thin on behaviour | the tick thread of whichever level owns it, or the worldgen executor before its chunk is live |
| `EntityDimensions` | width, height, eye height, attachment points, and whether `Attributes.SCALE` may touch them | immutable record; the type's is shared by every entity of the type |
| `SynchedEntityData` | which of the entity's fields the other side is told about ([synched entity data](synched-entity-data#nineteen-slots-and-where-the-numbers-come-from)) | one container per side; only the server's writes travel |
| `EntityInLevelCallback` | whether the object is *in* a world or merely on the heap | installed by the level's entity manager |
| `ServerEntity` | when a tracked entity's state becomes packets ([what the client is told](../networking/what-the-client-is-told#gate-3-and-the-position-it-chooses)) | the Server thread |
| `EntityReference` | how one entity remembers another across a chunk unload | wherever it is resolved |

Only one packet is this page's own: `ClientboundAddEntityPacket`, the birth
announcement. Everything after it — `ClientboundSetEntityDataPacket`,
`ClientboundEntityPositionSyncPacket`, `ClientboundEntityEventPacket`,
`ClientboundRemoveEntitiesPacket` — belongs to a sibling page.

## The type is frozen, the entity is not

An entity is anything in the world that is not a block: mobs, players, items
on the ground, arrows, boats, item frames, experience orbs, the invisible
markers a data pack uses as bookmarks. The kind is an `EntityType`, built once
and never changed. The individual is an `Entity`, and nearly all of its state
is mutable by design.

```mermaid
classDiagram
    class EntityType {
        one object per registered kind, 161 of them
        EntityType.EntityFactory, usually the constructor
        MobCategory, the spawn cap and despawn distance
        clientTrackingRange in chunks, updateInterval in ticks
        frozen by EntityType.Builder.build
    }
    class EntityDimensions {
        width, height, eye height
        EntityAttachments, and a fixed flag
    }
    class Entity {
        SynchedEntityData, eight accessors and the chain's
        Entity.position at the feet, Entity.bb a stored box
        Entity.dimensions and Entity.eyeHeight, both caches
        Entity.levelCallback, a NULL sentinel until a level takes it
        Entity.removalReason, the whole am-I-alive bit
        Entity.vehicle and Entity.passengers
    }
    EntityType --> EntityDimensions : holds one, built once
    EntityType ..> Entity : EntityType.create calls the factory
    EntityDimensions ..> Entity : copied into the two caches, and recopied on a pose change
```

*What each object holds, and the line the page turns on: everything in the
top two boxes is frozen at class-initialiser time and shared by every
individual of that kind, and everything in the bottom one belongs to one
individual and changes.*

`Entity` implements nine interfaces — `Nameable`, `EntityAccess`,
`ScoreHolder`, `SyncedDataHolder`, `DataComponentGetter`, `ItemOwner`,
`SlotProvider`, `DebugValueSource` and `TypedInstance` over `EntityType` —
which is a fair measure of how many systems reach into it. Health, AI, the
damage pipeline and inventory are all further down the tree.

In 26.3 the type constants are **not on `EntityType`**. They live in two
parallel files: `EntityTypeIds`, 161 `ResourceKey`s with no reference to any
entity class, and `EntityTypes`, the 161 matching objects that
`EntityType.Builder` produced from them. `MobCategory` — `MobCategory.MONSTER`,
`MobCategory.CREATURE`, `MobCategory.AMBIENT`, `MobCategory.AXOLOTLS`,
`MobCategory.UNDERGROUND_WATER_CREATURE`, `MobCategory.WATER_CREATURE`,
`MobCategory.WATER_AMBIENT`, `MobCategory.MISC` — carries the spawn cap
([entity lifecycle](entity-lifecycle#the-two-caps-and-where-289-comes-from))
and the despawn distance
([entity lifecycle](entity-lifecycle#ending-one-mobcheckdespawn)). None of
this is data-driven: `Registries.ENTITY_TYPE` is code-registered
([the data-driven type pattern](../foundations/data-driven-types#the-idea-stated-once)
is what it is *not*), and what a
data pack *can* reach is the tags in `EntityTypeTags`, the loot table at
*entities/&lt;id&gt;*, `DataComponents.ENTITY_DATA` on a spawn egg, and the
per-species variant registries (`Registries.WOLF_VARIANT`,
`Registries.CAT_VARIANT`, `Registries.PAINTING_VARIANT` and the rest).

### Dimensions, attachments and pose

`EntityDimensions` is a record — width, height, eye height, an
`EntityAttachments` map and a *fixed* flag — and
`EntityDimensions.makeBoundingBox` centres the box in X and Z on
`Entity.position` and grows it **upward**, because that position is the bottom
centre, the feet, and not the middle of the entity.
`EntityDimensions.scale` returns the record unchanged when it is fixed, and
also when both factors are 1. The flag is not the only way to escape `Attributes.SCALE`,
either: plain `Entity.getDimensions` never scales at all, so every non-living
entity ignores scale for free, and `LivingEntity.getDimensions` — which is
final, the overridable hook being `LivingEntity.getDefaultDimensions` —
short-circuits a sleeping entity to `LivingEntity.SLEEPING_DIMENSIONS` before
any scaling happens.

`EntityAttachments` answers where a passenger sits, where the entity itself
sits on a vehicle, where the name tag floats: `EntityAttachment.PASSENGER`,
`EntityAttachment.VEHICLE`, `EntityAttachment.NAME_TAG` and
`EntityAttachment.WARDEN_CHEST`, each with a fallback such as
`EntityAttachment.Fallback.AT_HEIGHT` that `EntityAttachments.Builder.build`
fills in from the width and height.

`Pose` is eighteen constants with **explicit wire ids**, not ordinals — the
ones that matter are `Pose.STANDING`, `Pose.CROUCHING`, `Pose.SWIMMING`,
`Pose.FALL_FLYING`, `Pose.SLEEPING`, `Pose.SPIN_ATTACK` and `Pose.DYING`, and
the rest are animation states of one mob or a few, such as `Pose.EMERGING` and
`Pose.DIGGING`. `Pose.BY_ID` is built with
`ByIdMap.OutOfBoundsStrategy.ZERO`, so a pose id outside the range decodes
silently to `Pose.STANDING` rather than failing the connection. Pose is the
synched value on the *base* class that changes the box — a dozen subclasses
have their own, from a pufferfish's puff state to a slime's size — and the
loop is worth stating
because everything else on this page hangs off it: `Entity.setPose` writes the
value, `SynchedEntityData.set` calls `Entity.onSyncedDataUpdated`
**inside the setter**, before anything is marked dirty, and that sees
`Entity.DATA_POSE` and calls `Entity.refreshDimensions`, which asks
`Entity.getDimensions` for the new record, overwrites both caches, and calls
`Entity.reapplyPosition` to rebuild the box. The side that set the pose
resizes immediately, the other resizes when the value lands. If the box grew,
`Entity.fudgePositionAfterSizeChange` nudges the entity out of whatever it now
overlaps — but only on the server, only after the first tick, only with
physics on, only when the entity is not a `Player`, and only when the new box
is at most four blocks in both width and height.

That loop is also the answer to *why did the hitbox not change when I changed
the size*. `Entity.dimensions`, `Entity.eyeHeight` and `Entity.bb` are caches,
and two things in the base classes refresh them unasked: a pose change, in
`Entity`, and `LivingEntity.onAttributeUpdated` on `Attributes.SCALE`. The dozen
subclasses with a box-changing value of their own — `AgeableMob` on the
baby bit among them — each call `Entity.refreshDimensions` for it, and
everything else has to call it by hand. While a cache is stale the two
eye-height accessors disagree: `Entity.getEyeHeight` with no argument reads the
cache, and the `Pose` overload recomputes.

## The tree, and the class that was inserted into it

`Entity` has **18** direct subclasses and 192 descendants. `LivingEntity` and
its own 124 make 125 of them — two thirds of the tree in one branch — and the
seventeen non-living branches hold the other 67.

<figure class="map">
*(figure: tree-Entity.svg — a generated SVG, not reproduced here)*
<figcaption>The <code>Entity</code> tree to three levels, generated from the decompile: a name in brackets carries how many types descend from it, and a grey line folds a node's childless children when there are two or more of them. Click to enlarge.</figcaption>
</figure>

The full drawing, with the block, item and screen trees beside it, is in
[what extends what](../../maps/hierarchy#entity). What matters here is the shape:
a long spine and a scattering. The spine is `LivingEntity`, and for all that it
carries it has exactly **three** direct subclasses — `Avatar`, `ArmorStand` and
`Mob` —
which is worth saying plainly, because it means **an armour stand is a living
entity with no AI at all**: no `GoalSelector`, no `PathNavigation`, both of
those being `Mob`'s. The `Brain` is not `Mob`'s, though. It is declared on
`LivingEntity`, built in its constructor and written under a *Brain* tag by
every living entity, so an armour stand carries an empty one.
`PathfinderMob` is a small class that scores walk targets and adds no way of
moving, which is why `Ghast` and `Phantom` navigate without ever being one.
`AgeableMob` adds babies, `TamableAnimal` an owner reference and a tame bit,
`Animal` and `Monster` split by disposition, and `Monster` implements `Enemy`,
a marker interface carrying nothing but XP-reward constants.

The 67 outside `LivingEntity`'s branch are shallow, and the atlas draws them as
four families and a scattering: `Projectile` with 26 descendants,
`VehicleEntity` with 15, `BlockAttachedEntity` with 6, `Display` with 3, and
thirteen direct subclasses of `Entity` with no
children of their own, from `ItemEntity` to `LightningBolt`. Sharing a base class that thin is what lets
them disagree so completely about being hit
([damage and death](damage-and-death#twenty-two-classes-with-no-pipeline-at-all)).

**`Avatar` sits between `LivingEntity` and `Player`.** It is a small class
carrying the player-shaped `Avatar.POSES` dimension map, `Avatar.DEFAULT_EYE_HEIGHT`
of 1.62 and one abstract method, `Avatar.getProfile`, so anything written
against "`Player extends LivingEntity`" is wrong by one level. Its point
is `Mannequin`, a posable, profile-skinned, player-looking entity in the
decoration package that is *not* a `Player` and carries none of the
inventory, abilities or hunger. What the rung holds and who draws it belong to
[player anatomy](../player/player-anatomy#the-ladder-and-the-class-in-the-middle);
what matters here is that the tree has that level.

Cutting across the tree are the capability interfaces, where most of the
shared behaviour lives: `Leashable` is the fattest, with
`Leashable.tickLeash` called from `Entity.baseTick`, and beside it
`Bucketable`, `EquipmentUser`, `NeutralMob`, `Attackable`, `Targeting`,
`TraceableEntity`, `OwnableEntity`, `Shearable`, `PlayerRideableJumping`,
`ItemSteerable`, and `ContainerUser`, with exactly two implementors: `Player`
and `CopperGolem`.

`EntityReference` deserves a name of its own. It stores either a UUID or the
live object, and `EntityReference.getEntity` resolves lazily *and decays back
to the UUID* the first time it is resolved after the target reports itself
removed. It is how "who last hurt me", "who owns this pet" and "who shot this
arrow" survive a chunk unload.

### Where the 727 files are

| subpackage | files | what |
|---|---:|---|
| `entity/ai` | 277 | goals, brains, navigation, attributes, sensors |
| `entity/animal` | 130 | one subpackage per species or family now |
| `entity/monster` | 84 | mostly likewise |
| `world/entity` itself | 85 | `Entity`, `LivingEntity`, `Mob`, `Avatar`, `EntityType`, `EntityTypes`, the capability interfaces |
| `entity/projectile` | 37 | arrows, fireballs, thrown items |
| `entity/boss` | 24 | dragon and wither |
| `entity/vehicle` | 24 | boats and minecarts |
| `entity/npc` | 15 | villagers and traders |
| `entity/player` | 14 | `Player`, `Inventory`, `Abilities` |
| `entity/decoration` | 13 | armour stands, frames, paintings, `Mannequin` |
| `entity/variant` | 11 | the machinery that picks a data-driven mob variant |
| `entity/item`, `entity/raid`, `entity/ambient`, `entity/schedule` | 13 | items, raids, bats, and `Activity` — which is all `entity/schedule` still holds |

## From a registry entry to a live object

`EntityTypes` runs `EntityType.Builder.build` for each of the 161 keys in
`EntityTypeIds` and registers the result, and it is that call which freezes
the `EntityDimensions` and its attachment points for the life of the type.
Everything below happens per entity, long afterwards.

```mermaid
sequenceDiagram
    participant SumC as SummonCommand
    participant ET as EntityType
    participant Entity as Entity
    participant SL as ServerLevel
    participant PESM as PersistentEntity<br/>SectionManager

    SumC->>SumC: rejects out of bounds, then on peaceful
    SumC->>ET: loadEntityRecursive, a tag with an id string
    ET->>ET: EntityType.by reads the id through EntityType.CODEC
    ET->>ET: EntityType.create checks canSpawn, then the factory
    ET->>Entity: the constructor: the next id, a new UUID, the type's dimensions
    Entity->>Entity: eight base accessors, then defineSynchedData, then setPos
    ET->>Entity: load, then readAdditionalSaveData
    SumC->>Entity: snapTo, the postLoad processor, before any passenger exists
    ET->>Entity: each Passengers child the same way, then startRiding
    SumC->>SL: tryAddFreshEntityWithPassengers, one body at a time
    SL->>PESM: addNewEntity
    PESM->>Entity: setLevelCallback, and only now is it in a world
    Note over SL,Entity: the next server tick
    SL->>Entity: commonTick, then tick
```

*Thirteen steps between a registry entry and a live object, and the one that
matters is the second from last: everything above `Entity.setLevelCallback`
happens
to an object no level knows about.*

The client builds its own copy of the same object, from a packet, whenever a
player comes into range — which is the same journey a second time, in five
steps instead of thirteen:

```mermaid
sequenceDiagram
    participant Entity as Entity
    participant SE as ServerEntity
    participant CPL as ClientPacketListener

    SE->>Entity: getAddEntityPacket
    SE->>CPL: ClientboundAddEntityPacket, with data, attributes and equipment
    CPL->>CPL: createEntityFromPacket, a second object
    CPL->>CPL: Entity.recreateFrom<br/>Packet
    CPL->>CPL: ClientLevel.addEntity
```

*The client's `Entity` is not the server's: it is a separate object, of the
same class for all but a player or a mannequin, built from a packet rather than from a tag, and the two are only
ever as alike as the channels in the rest of this part keep them.*

**Name to type.** `EntityType.by` reads the *id* field through
`EntityType.CODEC`. An unknown id yields nothing, and the entity is dropped
with the log line the opening quoted — this is the save-file half of the hook.

**Type to object.** `EntityType.create` checks `EntityType.canSpawn`: the
feature flags, plus a peaceful-difficulty test gated on the type's own
`EntityType.isAllowedInPeaceful` flag, which is a declared property and not a
synonym for *hostile*. `EntitySpawnRequest.ignoreChecks` skips both.
`SummonCommand` tests the same peaceful rule itself, a few lines earlier, purely
to fail with a better message; the command does not set the skip flag, so both
run. One type fails `EntityType.create` always: `EntityTypes.PLAYER` was built
with `EntityType.Builder.createNothing`, so its factory returns null, which
is why `ClientPacketListener.createEntityFromPacket` special-cases it and
hand-builds a `RemotePlayer` from the player info it already has; it is
`EntityType.Builder.noSave` and `EntityType.Builder.noSummon` besides. Otherwise the
factory runs. The `Entity` constructor takes the next id from the level,
invents a UUID with `Mth.createInsecureUUID`, copies the type's dimensions
into its cache, and builds the synched-data container — its own eight
accessors, then the abstract `Entity.defineSynchedData`, which contributes
nothing on the base class and exists only for the subclasses to chain up
through ([synched entity
data](synched-entity-data#nineteen-slots-and-where-the-numbers-come-from)
names the eight and says why their order is the whole numbering
scheme). It then calls `Entity.setPos` at the origin,
so a fresh entity already has a full-size box rather than the zero-size
`Entity.INITIAL_AABB` the field initialiser gave it.

**Tag to state.** `Entity.load` reads position (clamped to ±3.0000512E7
horizontally), motion, rotation and UUID, then calls the abstract
`Entity.readAdditionalSaveData`, then `Entity.reapplyPosition` again if
`Entity.repositionEntityAfterLoad` says so — which everything says except
`BlockAttachedEntity`, the corpus's one override, so paintings, item frames,
leash knots and cushions are precisely the entities that *skip* it and keep the
position their own load computed. The save twin is `Entity.addAdditionalSaveData`, and
passengers save inside their vehicle: `Entity.save` returns false for anything
currently riding, and the vehicle writes them into its *Passengers* list
through `Entity.saveAsPassenger`, using `Entity.getEncodeId`, which is null
for types that never serialise.

**Object to level.** `ServerLevel.tryAddFreshEntityWithPassengers` refuses if
any UUID in the stack is already loaded, then
`ServerLevelAccessor.addFreshEntityWithPassengers` calls
`ServerLevel.addFreshEntity` once per body.
`PersistentEntitySectionManager.addNewEntity` files it into a section and
replaces `EntityInLevelCallback.NULL` with a real callback. *That* is the
moment it stops being an object on the heap;
[entity lifecycle](entity-lifecycle#entry-what-addfreshentity-actually-does)
takes it from here.

**Level to client.** `ServerEntity.addPairing` sends
`ServerEntity.sendPairingData` as one bundle: the packet
`Entity.getAddEntityPacket` returns — id, UUID, type, position, velocity,
three rotation *bytes* and one varint of type-specific data — then the
non-default synched values, then attributes and equipment. On the client,
`ClientPacketListener.handleAddEntity` builds the object, calls
`Entity.recreateFromPacket`, and only then adds it to the level.

The spawn-egg path is a different pipeline that meets this one at the end.
`EntityType.spawn` snaps the new entity out of collision with
`EntityType.getYOffset`, aligns head and body rotation, runs
`Mob.finalizeSpawn`, applies a `PostSpawnProcessor`, adds it through
`ServerLevelAccessor.addFreshEntityWithPassengers` and plays an ambient
sound. `SummonCommand` also calls `Mob.finalizeSpawn`, but only when the
command asks for it, and it never touches the Y offset.

## The tick both sides share

`ServerLevel.tickNonPassenger` opens a profiler section named after the entity
type, calls `Entity.commonTick` — which counts `Entity.invulnerableTime` down,
calls `Entity.setOldPosAndRot`, steps the interpolation on a client and
increments `Entity.tickCount` — and then calls `Entity.tick`, all of it
through `Level.guardEntityTick`, which turns any exception into a crash report
with the entity's details attached.
`ClientLevel.tickEntities` does the same, through the same guard, having first
skipped anything removed, riding or frozen by the tick-rate manager. Which
entities the server's loop reaches, and in what order, belongs to [the level
tick](../server/server-level-tick#every-entity-and-then-its-riders). No
entity is ever *ticked* on a worker pool, and `Entity` is not thread-safe —
though entities are constructed on one: `ChunkStatus.SPAWN` runs
`NaturalSpawner.spawnMobsForChunkGeneration` on the worldgen executor, so a
chunk's first animals are built and finalised off the Server thread before the
chunk ever becomes live.

`Entity.tick` on the base class is one line: call `Entity.baseTick`.
Everything else readers remember happening "in tick" is in `Entity.baseTick` — the
dead-vehicle check, the boarding cooldown, the portal handling, the fluid
snapshot, swimming, fire ticking, the lava halving of fall distance, the
below-world check, the leash — or in an override. `LivingEntity.tick` calls up
and then runs `LivingEntity.aiStep`, and `Mob.tick` calls up and refreshes its
goal-control flags through `Mob.updateControlFlags` every five ticks, on the
server only — as the portal handling, the burning and the leash inside
`Entity.baseTick` are too.

What differs between the sides is not the tick but what the tick is allowed to
*do*, and that is exactly the subject of the next page,
[authority](authority#five-predicates-and-the-final-one-the-other-four-hang-off).

## The id, and what compares equal

`Entity.equals` compares the network id and nothing else — not the UUID, not
identity — and `Entity.hashCode` *is* the id. Ids are handed out by
`ServerLevel.getNextEntityId` from a static `AtomicInteger` on `ServerLevel`,
so they are process-global, which keeps two server levels' ids apart, and the
level is consulted only to avoid a collision. Equal ids still meet across
levels: in singleplayer the client's copy of an entity and the integrated
server's share one, which is why entities from two levels must never go in one
set.

On the client there is no id at all until a packet supplies one.
`Level.getNextEntityId` returns a literal zero and `ClientLevel` does not
override it, while zero is the reserved invalid id and `Entity.getId` throws
*Tried to access entity ID before ID assignment* on it. Between construction
and the `Entity.setId` that `Entity.recreateFromPacket` performs, a
client-side entity has no id, and therefore no equality and no hash.
`ServerLevel.getNextEntityId` skips zero deliberately.

## The two numbers frozen onto the type

The cast promised two numbers that decide how an entity reaches clients.
`EntityType.clientTrackingRange` is in **chunks** and
`EntityType.updateInterval` in ticks — 5 and 3 unless a builder says
otherwise — and between them they decide who is told about the entity and how
often its movement is sent, never mind what the packet says ([what the client is
told](../networking/what-the-client-is-told#gate-3-and-the-position-it-chooses)
owns the asking, and a third parameter, `EntityType.trackDeltas`, which is
true of every type but eleven).
Thirty-eight of the 161 types set an interval explicitly, most of them at 10
or 20; eight set *Integer.MAX_VALUE* (most through
`EntityType.Builder.noUpdateInterval`), which `ChunkMap` turns into
`UpdateInterval.NEVER`, so their interval branch never fires at all —
`EntityTypes.ITEM_FRAME` and `EntityTypes.GLOW_ITEM_FRAME`,
`EntityTypes.PAINTING`, `EntityTypes.LEASH_KNOT`, `EntityTypes.END_CRYSTAL`,
`EntityTypes.LIGHTNING_BOLT`, `EntityTypes.AREA_EFFECT_CLOUD` and
`EntityTypes.CUSHION`. At the
other end `EntityTypes.MARKER` has a tracking range of 0 and is never sent to
anyone at all.

The client holds a lever over a distance of its own, how far away an entity is
still drawn (in singleplayer the same option also scales how far the integrated
server tracks), and it is process-global in the same way the ids are. `Entity.viewScale` is a **static** field on `Entity`,
and `LevelExtractor` writes it from the effective render distance *and* the
entity-distance option together, not from the option alone — which is why
entity render distance moves when you touch a slider that does not name
entities.

## Where to look

Start at `EntityTypes`, which builds all 161 types and is the most useful
single table in the package, and read `EntityType.Builder.build` beside it for
what gets frozen. Then `EntityType.create` and `EntityType.loadEntityRecursive`
for the chain this page traces, and `Entity` itself — its constructor,
`Entity.defineSynchedData` and `Entity.load` — for what comes out of it.
`Entity.refreshDimensions` is the way into the dimension caches and
`EntityDimensions.makeBoundingBox` the arithmetic under them.
`PersistentEntitySectionManager.addNewEntity` is where an object becomes part
of a world. Two doors the page opens only a crack: `EntityReference`, for how
one entity remembers another, and `EntityType.spawn`, the spawn-egg path that
meets the trace at its end.

---

*Rules: names, never code · how the system works, not how the code reads ·
newest version only · every backticked name passes `tools/verify_names.py`.*
