<!-- https://minecraftdocs.dev/systems/entities/damage-and-death — 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 -->

# Damage and death

> Verified against **Minecraft 26.3** · Part VI · An arrow hits a player in full iron with Protection II: six damage becomes two, and if it kills, a message, a loot drop and a death screen.

The arrow lands, the screen goes red, the hearts drop by one, and somewhere
behind you the archer's client plays its hit ding. Six damage left the bow and
about two reached your health, which is the part everybody knows. The part
nobody sees is what happens when a second arrow arrives four ticks later,
inside the flash. If more than ten ticks of invulnerability remain, that hit
is worth only its *excess* over `LivingEntity.lastHurt`: a weaker one returns
without dealing any damage, and a stronger one takes a partial
branch that clears an internal *took full damage* flag. That one flag gates
the damage-event broadcast, the knockback, the hurt sound and the red flash
alike. Health goes down and none of those happens — which means neither
`ClientboundDamageEventPacket` nor the red flash is a reliable "was hit"
signal. It is all in `LivingEntity.hurtServer`.

## The cast

| class | what it decides | thread |
|---|---|---|
| `DamageSource` | *what* hit and *who*: a direct entity, a causing entity, and — rarely — a position instead | built wherever the hit starts, on the Server thread |
| `DamageType` | the message id, the difficulty scaling, the food cost, a *player's* hurt sound, and the kind of death message | a dynamic registry entry, loaded from a data pack and synced to clients |
| `DamageTypeTags` | almost every behavioural branch on the path below | read on the Server thread |
| `LivingEntity` | the whole reduction pipeline, the i-frames, the flash, the two attribution references and death | the Server thread |
| `CombatRules` | the two pieces of arithmetic — armour and enchantment protection | stateless statics |
| `CombatTracker` | what killed you, and which entry gets the credit | the Server thread, cleared on its own timer |
| `ServerPlayer` | PvP, the death screen packet, the death message, the inventory drop | the Server thread |
| `Entity` | that `Entity.hurtServer` is **abstract** — there is no default behaviour to inherit | — |

Everything above is server-side, and `LivingEntity` declares no
`Entity.hurtClient` at all: no damage is ever *calculated* on a client. A
client does set health — from `LivingEntity.DATA_HEALTH_ID`, from
`ClientboundSetHealthPacket`, and to zero on the death event — but it never
decides a number, and the signature says so: `Entity.hurtServer` takes a
`ServerLevel`, so the side is enforced by the compiler rather than by a
convention. Which side is allowed to decide *anything* is
[authority](authority#five-predicates-and-the-final-one-the-other-four-hang-off).

## The number the arrow decides

`AbstractArrow.onHitEntity` builds the *source* first, because the number
needs it: `EnchantmentHelper.modifyDamage` takes the `DamageSource` as an
argument. It starts from `AbstractArrow.baseDamage`, 2.0 for an ordinary
arrow, runs
`EnchantmentHelper.modifyDamage` over the bow that fired it so Power raises
the *base*, then multiplies by the arrow's current speed and rounds up with
`Mth.ceil` — so the damage that leaves the bow is an integer, and a slowing
arrow does less. `AbstractArrow.isCritArrow` adds a random bonus of up to
half the damage plus one. Six is a fresh arrow at full draw before that bonus,
which a full draw always earns, so six is the one draw in five that adds
nothing.

`DamageSources.arrow` then names two entities: the arrow as the *direct*
entity, the shooter as the *causing* one — or, when the arrow has no owner
left, the arrow itself in both roles. `DamageSource.getWeaponItem` reaches
through the direct entity, which is how Breach on the attacker's weapon
reaches the victim's armour calculation. A source can carry a position
instead, though far less often than you would guess: ordinary explosions do
not, and fall back to the direct entity in `DamageSource.getSourcePosition`.
Exactly three sources are genuinely positional, and only they put a position
on the wire through `DamageSource.sourcePositionRaw` —
`DamageSources.badRespawnPointExplosion`, `/damage … at` (`DamageCommand`),
and `ExplodeEffect` unattributed.

The `DamageType` behind the source is five fields — message id,
`DamageScaling`, food exhaustion, `DamageEffects` (which picks the hurt
*sound*, and only for a `Player`: `Player.getHurtSound` is its one caller)
and `DeathMessageType` — and it lives in a data pack. There are 51
keys in `DamageTypes` and 36 tags in `DamageTypeTags`, and **almost every
behavioural branch below is tag-driven rather than type-driven**. The
exceptions are worth listing because they are the whole list: thorns picks
its own secondary sound in `LivingEntity.playSecondaryHurtSound`, wind charge
is excluded from mob-anger attribution against an
`EntityTypeTags.NO_ANGER_FROM_WIND_CHARGE` entity, and a `ServerPlayer`
mid-dimension-change is invulnerable to all but `DamageTypes.ENDER_PEARL`.

## Three gates before anything is computed

`LivingEntity.hurtServer` opens with three early returns: already
invulnerable, already dying, or a `DamageTypeTags.IS_FIRE` source against
`MobEffects.FIRE_RESISTANCE` — a mob-effect immunity sitting *outside* the
reduction pipeline entirely. Invulnerability itself is
`Entity.isInvulnerableToBase` (removed, the invulnerable flag or its timed
twin `Entity.invulnerableTime`, fire immunity, fall immunity) **or** an
enchantment-granted one through
`EnchantmentHelper.isImmuneToDamage`, which is how Frost Walker makes its
wearer immune to magma blocks.

Two subclasses get there first. `ServerPlayer.hurtServer` adds the PvP and
team check — `ServerPlayer.canHarmPlayer` refuses when the level forbids PvP
or the two share a team that disallows friendly fire — testing both a `Player`
causing entity directly and an `AbstractArrow` causing entity by asking it for
its owner. `ServerPlayer.isInvulnerableTo` adds the two conditions that have
no tag: mid-dimension-change, and a client that has not finished loading. Then
`Player.hurtServer` refuses a creative player unless the source is
`DamageTypeTags.BYPASSES_INVULNERABILITY`, and applies **difficulty
scaling** — halved and offset on easy, one and a half times on hard, zero on
peaceful — but only when `DamageSource.scalesWithDifficulty` says so. That
reads `DamageScaling` off the type, and `DamageTypes.ARROW` is
*when_caused_by_living_non_player*: a skeleton's arrow scales and a player's
does not. `Player.isInvulnerableTo` is also where `GameRules.DROWNING_DAMAGE`,
`GameRules.FALL_DAMAGE`, `GameRules.FIRE_DAMAGE` and
`GameRules.FREEZE_DAMAGE` live — switching one off makes a player *immune*
rather than making the damage smaller.

## One number, eight steps, and no step that knows another

Past the gates the number goes down a chain of eight arithmetic steps — five
multiplications and three subtractions — each owned by a different piece of the
game, and none of them aware of the others.

```mermaid
flowchart TD
    N0["the bow"]
    N1["blocking"]
    N2["freezing"]
    N3["the helmet"]
    N4["i-frames"]
    N5["armour"]
    N6["Resistance"]
    N7["protection"]
    N8["absorption, then health"]

    N0 -- "6.0" --> N1
    N1 -- "6.0" --> N2
    N2 -- "6.0" --> N3
    N3 -- "6.0" --> N4
    N4 -- "6.0" --> N5
    N5 -- "3.12" --> N6
    N6 -- "3.12" --> N7
    N7 -- "2.12" --> N8
```

*The number rides the arrows: four steps in a row take nothing at all, and the
whole reduction on a fully armoured victim happens in two.*

Which piece of the game owns each of the eight, and what it does to the
number:

| # | step | owned by | what it does to the number | leaves |
|---:|---|---|---|---:|
| — | the arrow leaves the bow | `AbstractArrow` | `Mth.ceil` of speed times base damage, Power already folded into the base | 6.0 |
| 1 | blocking | `DataComponents.BLOCKS_ATTACKS`, through `LivingEntity.applyItemBlocking` | subtracts what the component resolves for this angle and this damage type | 6.0 |
| 2 | freezing | `EntityTypeTags.FREEZE_HURTS_EXTRA_TYPES` | multiplies by five | 6.0 |
| 3 | the helmet | `DamageTypeTags.DAMAGES_HELMET` | multiplies by 0.75 | 6.0 |
| 4 | the i-frame window | `LivingEntity.lastHurt` | over ten ticks left, only the excess survives | 6.0 |
| 5 | armour | `CombatRules.getDamageAfterAbsorb` | effective armour over 25, floored at a fifth and capped at 20 — here 48 per cent off | 3.12 |
| 6 | Resistance | `LivingEntity.getDamageAfterMagicAbsorb` | five of twenty-five per level, and nothing at all at amplifier four | 3.12 |
| 7 | protection | `CombatRules.getDamageAfterMagicAbsorb` | the summed points over 25, capped at 20 — here 8 points, 32 per cent off | 2.12 |
| 8 | absorption | `LivingEntity` | spent before health is, then `CombatTracker.recordDamage` and `LivingEntity.setHealth` | 2.12 |

Before the first row there is one gate the chain never sees:
`Player.hurtServer` scales incoming damage by difficulty, and a player's own
arrow is not scaled.

The first link is blocking, and **shields are no longer a mechanism, only a
vocabulary**. `LivingEntity.applyItemBlocking` asks the item being used —
through `LivingEntity.getItemBlockingWith`, which enforces
`BlocksAttacks.blockDelayTicks` — for a `DataComponents.BLOCKS_ATTACKS`
component, checks the damage type against `BlocksAttacks.bypassedBy`,
computes the angle between the source position and the victim's head
rotation, and lets `BlocksAttacks.resolveBlockedDamage` sum the reductions in
the component's own list that apply. `BlocksAttacks.hurtBlockingItem` then charges
durability — for a blocking `Player` only; a mob's item never wears — and a
non-projectile block sends the *blocker* reeling through
`LivingEntity.blockedByItem`, which is how a `Hoglin` throws whoever blocked
it and a `Ravager`, unless it is roaring, either stuns itself while shoving
them or shoves them harder on a coin flip. An arrow with any piercing level skips all of
it before the angle is computed. `ShieldItem` still exists, the statistic is
still `Stats.DAMAGE_BLOCKED_BY_SHIELD`, and the axe-disables-shield rule
survives as `LivingEntity.getSecondsToDisableBlocking` — which `Warden`
overrides, and which reads the attacker's `Weapon` component only while that
weapon is also their *active* item ([the sword
swing](../player/the-sword-swing#the-damage-one-number-two-curves-one-order))
— feeding `Player.blockUsingItem` and `BlocksAttacks.disable`. None
of it is shield-specific code any more.

The two multipliers after it almost never fire and are both pure tag lookups:
`DamageTypeTags.IS_FREEZING` against an entity in
`EntityTypeTags.FREEZE_HURTS_EXTRA_TYPES` multiplies by five, and
`DamageTypeTags.DAMAGES_HELMET` against a helmeted victim calls
`LivingEntity.hurtHelmet` and multiplies by 0.75.

## Ten ticks in which nothing shows, and ten that protect nothing

`LivingEntity.damageCooldownTime` is set to 20 by a hit that lands in full and counted
down once a tick — from `LivingEntity.baseTick` for everything except a
`ServerPlayer`, and from `ServerPlayer.tick` for players, earlier in the tick.
`LivingEntity.hurtDuration` and `LivingEntity.hurtTime` are set to 10, so the
red flash covers half of it.

**It is the flashing half that is invulnerable.** The test is
`LivingEntity.damageCooldownTime` still being *above* ten, which is exactly the ten
ticks the flash is showing; once the counter falls to ten the next hit takes
the ordinary branch, lands in full, and resets both numbers. The second half
of what everyone calls the invulnerability window protects nothing at all.

Inside the first half, then, unless the type carries
`DamageTypeTags.BYPASSES_COOLDOWN`, the incoming damage is compared against
`LivingEntity.lastHurt` — what the last hit was worth — and only the excess
is applied. A hit that is not bigger returns before any hurt sound, damage
packet, knockback of the victim or combat entry. A hit that *is* bigger applies the difference and
clears a local *took full damage* flag, and everything downstream sits inside
a test of that flag: no `ServerLevel.broadcastDamageEvent`, no
`Entity.markHurt`, no `LivingEntity.dealDefaultKnockback`, no hurt sound, no
reset of the flash. So the first hit in each window is the one everyone sees;
a later, stronger one lands its excess with no flash for anyone watching,
though its lower health still goes out, and a victim's own client, which
deduces a hit from the drop, flashes anyway.

`LivingEntity.resolveMobResponsibleForDamage` and
`LivingEntity.resolvePlayerResponsibleForDamage` sit outside that test and run
on the silent *stronger* partial hit as well as the full one — only the
weaker hit, which returns before them, leaves no damage and no attribution. They write
`LivingEntity.lastHurtByMob` and `LivingEntity.lastHurtByPlayer` (with its
hundred-tick `LivingEntity.lastHurtByPlayerMemoryTime` countdown), crediting a
tamed `Wolf`'s work to its owner. `LivingEntity.lastDamageSource` and
`LivingEntity.lastDamageStamp` are set beside them, but only when the hit
counted for something.

## Armour, and why big hits punch through it

`LivingEntity.actuallyHurt` is where the number meets the victim's gear.
`LivingEntity.getDamageAfterArmorAbsorb` first calls `LivingEntity.hurtArmor`
— which is **empty on `LivingEntity`** and overridden only by `Player`,
`Horse` and `Wolf`. A skeleton in full iron never wears its armour out. Where
it is implemented it routes to `LivingEntity.doHurtEquipment`: one durability
point per four damage, minimum one, per piece, and each piece must separately
be `Equippable.damageOnHurt`, damageable, and pass `ItemStack.canBeHurtBy`.

### The armour formula, in the order it is applied

Then `CombatRules.getDamageAfterAbsorb` does the arithmetic. Effective armour
is the armour points, reduced by *the incoming damage divided by (two plus a
quarter of toughness)*, then clamped between `CombatRules.MIN_ARMOR_RATIO`
(0.2) of the nominal points and `CombatRules.MAX_ARMOR` (20); the fraction taken
off is that effective armour over `CombatRules.ARMOR_PROTECTION_DIVIDER`, which
is **25**. **Big hits punch through armour by
design**: the subtraction is what makes a 40-damage hit see less armour than a
6-damage one, and `Attributes.ARMOR_TOUGHNESS` is exactly the term that slows
it down. Full iron is 15 points and no toughness, so a 6-damage hit sees 12
effective armour, 48 per cent off, 3.12 left. Breach moves the resulting
fraction through `EnchantmentHelper.modifyArmorEffectiveness` first.

`LivingEntity.getDamageAfterMagicAbsorb` then applies Resistance and sums
`EnchantmentHelper.getDamageProtection` across every equipment slot.
Protection is not a class: it is
`EnchantmentEffectComponents.DAMAGE_PROTECTION` holding a conditional value
effect, confined to armour by its own *slots* declaration in the JSON rather
than by the helper, worth one point per level per piece — so Protection II on
four pieces is 8. `CombatRules.getDamageAfterMagicAbsorb` caps that sum at 20
and takes *sum over 25* off. 3.12 becomes about 2.12.

**Armour is capped twice and floored once.** Effective armour never drops
below a fifth of nominal and never counts above 20, and protection points cap
at 20 as well — so armour alone tops out at 80 per cent reduction, protection
at 80 per cent of what is left, 96 per cent combined — so armour alone can
never take a hit to nothing. An effect can: Resistance at amplifier four
multiplies by zero.
What survives comes off absorption first; then, unless absorption took it all,
`CombatTracker.recordDamage` files a `CombatEntry`, and health takes the rest. `Player.actuallyHurt`
overrides the whole method to add food exhaustion (`DamageType.exhaustion`,
0.1 for an arrow) and the damage statistics.

## Telling everyone, and what a block replaces

The arithmetic is over and the number has landed. What follows is an order,
and two of its steps are the ones players notice going missing:

```mermaid
sequenceDiagram
    participant AA as AbstractArrow
    participant SP as ServerPlayer
    participant CT as CombatTracker
    participant SL as ServerLevel
    participant CPL as ClientPacketListener

    AA->>SP: hurtOrSimulate, the arrow's source and 6.0
    SP->>SP: ServerPlayer.hurtServer, canHarmPlayer and teams
    SP->>SP: Player.hurtServer, the creative gate and difficulty
    SP->>SP: LivingEntity.hurtServer, the gates and the multipliers
    SP->>SP: i-frames, where a partial hit clears the flag
    SP->>SP: actuallyHurt, absorption first
    SP->>CT: recordDamage, one CombatEntry
    SP->>SP: then setHealth
    SP->>SP: resolveMobResponsible<br/>ForDamage
    SP->>SP: resolvePlayer<br/>ResponsibleForDamage
    SP->>SL: broadcastDamageEvent, full hits and nothing blocked
    SL-->>CPL: ClientboundDamageEventPacket, every tracker and the victim
    SP->>SP: markHurt, then dealDefaultKnockback
    SP->>SP: indicateDamage, skipped if anything was blocked
    SP-->>CPL: ClientboundHurtAnimationPacket, that one player
    SP->>SP: dead? then checkTotemDeath<br/>Protection
```

*One lane for the victim, because `ServerPlayer` and `LivingEntity` are one
object: the three hurtServer messages at the top are one virtual call going
down the override chain. `ServerLevel.broadcastDamageEvent` comes before the knockback, not after — and the
last message is where [the next section](#death-or-not) takes over.*

`ServerLevel.broadcastDamageEvent` sends the type, three entity ids — the
victim, the causing entity and the direct one — and an
optional position to every tracking player *and the victim*, and it runs
**before** the knockback, not after. A successful block replaces it entirely:
if the blocking component absorbed anything, `BlocksAttacks.onBlocked` plays
the block sound and **no damage event is broadcast at all**, so a blocked hit
puts no flash on anyone else's screen. Only then does `Entity.markHurt` queue the
velocity packet, and `LivingEntity.dealDefaultKnockback` compute a direction
(from the projectile for a projectile, from the source position otherwise)
for `LivingEntity.knockback`, which scales it by one minus
`Attributes.KNOCKBACK_RESISTANCE`. `ServerPlayer.indicateDamage` ends that
call, and is skipped when anything was blocked. The hurt sound comes after
all of it — after the death check, not with the flash.

Six packets carry the hit itself, beside the sound packets. `ClientboundDamageEventPacket` (type holder,
causing and direct entity ids, optional position) and
`ClientboundSetEntityMotionPacket` go to every tracker, and to the victim
when it is a player,
`ClientboundHurtAnimationPacket` and `ClientboundSetHealthPacket` only ever to
one player about themselves, `ClientboundSetEntityDataPacket` carries
`LivingEntity.DATA_HEALTH_ID` for a mob, and `ClientboundEntityEventPacket`
carries one byte — 3 for death, 60 for the poof, 35 for a totem. Inbound,
only the respawn command.

**The damage amount never crosses the wire.** The client picks a flash, and for
your own player a sound, from the type and infers magnitude from health — and only for your own
player, in `LocalPlayer.hurtTo`, the one place a hit is deduced from a health
*drop*. `LivingEntity.handleDamageEvent` sets `LivingEntity.damageCooldownTime` to 20
and the flash to 10 and plays the sound (which only your own player's hurt
is heard from; everyone else's comes from the server), touching health not at
all.

## Death, or not

If health has reached zero, `LivingEntity.checkTotemDeathProtection` looks for
`DataComponents.DEATH_PROTECTION` in either hand — unless the source is
`DamageTypeTags.BYPASSES_INVULNERABILITY`, which is why `/kill` cannot be
totemed — and on a hit consumes one, sets health to one, applies
`DeathProtection`'s effects and broadcasts byte 35.

Otherwise `LivingEntity.die` runs, and its order matters:

```mermaid
flowchart TD
    Z["health has reached zero"]
    T{"DEATH_PROTECTION in a hand, and the source does not bypass?"}
    TOT["consume one, health to one, byte 35"]
    D["LivingEntity.die: kill credit, then LivingEntity.handleKillingBlow"]
    V{"no causing entity, or Entity.killedEntity agrees?"}
    L["the death game event, LivingEntity.dropAllDeathLoot, the wither rose"]
    B["the entity-event byte, to every watcher"]
    P["Pose.DYING"]
    Z --> T
    T -- "yes" --> TOT
    T -- "no" --> D
    D --> V
    V -- "yes" --> L
    V -- "no" --> B
    L --> B
    B --> P
```

*The diamond in the middle is a veto one other entity holds over this one's
loot. The two boxes below it are what the veto cannot reach: the byte goes to
every watcher either way, and the pose is set after the byte, not with it.*

Kill credit is read
from the attribution references written a few lines earlier, and
`LivingEntity.handleKillingBlow` sets `LivingEntity.dead`. Then — with a causing entity, **only if
`Entity.killedEntity` on it agrees**; with none, unconditionally — the death
game event fires,
`LivingEntity.dropAllDeathLoot` runs and the wither rose is planted. The
entity-event byte sits *outside* that veto and goes out to every watcher
**before** `Pose.DYING` is set — the byte first, the pose after.

Loot needs a *recent* player. `LivingEntity.dropAllDeathLoot` reads *killed by
a player* off `LivingEntity.lastHurtByPlayerMemoryTime` still being above
zero, so an attribution older than a hundred ticks costs the loot context its
`LootContextParams.LAST_DAMAGE_PLAYER` and its luck, and costs the experience
drop entirely unless the mob is an always-dropper. `LivingEntity.shouldDropLoot`
gates loot on `GameRules.MOB_DROPS` and on not being a baby — but
`Monster.shouldDropLoot` drops the baby condition, which is why baby zombies
and piglins do drop. `LivingEntity.shouldDropExperience` mirrors it. Only
`LivingEntity.dropEquipment` is outside both.

## The death screen, and what the client does alone

**`ServerPlayer.die` never calls up.** It reimplements the sequence, so
`LivingEntity.handleKillingBlow` never runs and `LivingEntity.dead` stays
**false** on a dead player for the whole death screen. It reads the message
from the combat log at the top and calls `CombatTracker.recheckStatus` at the
bottom, so the log survives long enough to be read.
`GameRules.SHOW_DEATH_MESSAGES` gates more than the chat line: with the rule
off the message is never assembled ([text
components](../foundations/text-components#built-on-the-server-in-no-language)
owns the assembling) and `ClientboundPlayerCombatKillPacket`
carries an **empty** component, so the death screen still opens and says
nothing. `ServerPlayer.die` also forgives neutral mobs under
`GameRules.FORGIVE_DEAD_PLAYERS`, drops the inventory through
`Player.dropEquipment` unless `GameRules.KEEP_INVENTORY`, and calls
`ServerGamePacketListenerImpl.markClientUnloadedAfterDeath`. `DeathScreen`
opens unless `GameRules.IMMEDIATE_RESPAWN`, and the object that comes back —
a new `ServerPlayer` wearing the old one's id and connection — belongs to [players and
sessions](../server/players-and-sessions#the-object-and-the-reference-that-outlives-it).

Two things then happen without a packet of their own. **The client kills mobs on its own,
from one byte**: `LivingEntity.handleEntityEvent` for byte 3 sets a non-player
entity's health to zero and runs `LivingEntity.die` locally, so the twenty
tick animation in `LivingEntity.tickDeath` is client-driven, not a
consequence of a health update. And **`CombatTracker` clears itself** — after
`CombatTracker.RESET_DAMAGE_STATUS_TIME` out of combat or
`CombatTracker.RESET_COMBAT_STATUS_TIME` in it. Four places call the check: a
twenty-tick timer in `LivingEntity.tick`, the top of
`CombatTracker.recordDamage`, `LivingEntity.remove`, and `ServerPlayer.die` — so a
hit after a long lull discards the old log before filing its entry.

### Who gets the credit for a fall

The log is not read in order, and the rule that reads it is the reason for
*was doomed to fall by*. `CombatTracker.getMostSignificantFall` walks the
entries looking for the biggest fall, and when it finds one it credits **the
entry before it** — the hit logged just before the fall's own entry — taking
the fall entry itself only when the fall is the first thing in the log. It
keeps a second candidate beside that, the biggest-damage entry that carries a
`FallLocation`. Then the threshold: the fall counts only if it was **more than
five** blocks, and the alternative only if *its damage* was more than five;
below both, the tracker returns nothing and the death message falls back to
the ordinary one for the killing blow. So a skeleton's arrow and then a
four-block fall that kills you is *hit the ground too hard while trying to
escape* the skeleton (the source's own message, crediting the last mob that
hurt you), and the same arrow before a ten-block fall is *doomed to fall by*
the skeleton — same two entries, one number apart. The `FallLocation` is what turns the credited entry into the
wording (*fell off some vines*, *fell off a ladder*, *fell while climbing*),
and building the sentence out of it belongs to [text
components](../foundations/text-components#built-on-the-server-in-no-language).

## Everything that calls it

`Entity.hurt` and `Entity.hurtOrSimulate` are deprecated final wrappers over
the abstract method: the second picks a side and returns `Entity.hurtClient`
off a client level, the first does nothing there. `Entity.hurtClient` has
ten declarations counting the base, and every one only ever answers *did
this connect* — including `RemotePlayer`, which returns true unconditionally
so a client-side arrow can play its own effects without knowing any numbers.

Environmental damage is ticked from more places than *base tick* suggests.
Fire (once per twenty fire ticks) is in `Entity.baseTick`, lava (four at a
time) in `Entity.lavaHurt`, and suffocation, world-border and drowning damage
in `LivingEntity.baseTick`. **Freezing and cramming are not**: freezing is in
`LivingEntity.aiStep` every forty ticks, and cramming inside
`LivingEntity.pushEntities`, called near the end of the same method under
`GameRules.MAX_ENTITY_CRAMMING`, just before the drowning a water-sensitive
mob takes in water or rain.

## Twenty-two classes with no pipeline at all

Everything above this line is `LivingEntity`'s, and none of it is inherited.
`Entity.hurtServer` is **abstract**: there is no default behaviour anywhere in
the tree, so every branch answers for itself. **Fifty-five** files override it
— a fifty-sixth, `Entity` itself, only declares it — thirty-three of them
`LivingEntity` and its descendants, `ArmorStand` among them, a `LivingEntity` despite
having no AI ([entity
anatomy](entity-anatomy#the-tree-and-the-class-that-was-inserted-into-it)).
The other **twenty-two** are not living entities at all, and none of them runs
armour, i-frames, absorption, the combat tracker or the death sequence itself.

Six patterns cover all twenty-two, and the sharpest are the ones that read the
damage *number* — only four classes do. `ItemEntity` and `ExperienceOrb` keep a
plain integer of health and subtract from it. `VehicleEntity` adds *damage ×
10* to an accumulator that loses one a tick and breaks past 40, which is why
any hit over four damage breaks a minecart at once and smaller ones must land
close together, and `MinecartTNT`
inherits that accumulator after its own override has looked at the arrow rather
than the number. For the other
eighteen the answer is a yes or a no: ten do nothing whatever, two resend their motion and nothing else,
five are destroyed by one hit of any size (an unfixed frame holding something loses only its item to the first) — an `EndCrystal` among them, and it
is **immune to the `EnderDragon` that eats it** — and `EnderDragonPart` reads
nothing, forwarding the whole call, number included, to its parent. Which class
does which is [the non-living damage
table](../../reference/non-living-damage).

> **For a 1.21-era reader.** The hurt cooldown is
> `LivingEntity.damageCooldownTime`. *invulnerableTime* on `Entity` is now a
> separate timer of full invulnerability that no hit sets: a skeleton trap
> gives the horses it adds and every skeleton rider sixty ticks of it, a cushion broken by lightning
> gives the item it drops twenty, a conversion carries it over, and
> `Entity.isInvulnerable` is true while it runs.

## Where to look

`LivingEntity.hurtServer` is the whole first half of this page in one method,
and the two overrides that reach it first — `ServerPlayer.hurtServer` and
`Player.hurtServer`, over the abstract `Entity.hurtServer` — are the gates.
Then `LivingEntity.actuallyHurt` and the two `CombatRules` statics it reaches,
which are short and settle every argument about armour. `DamageSource` and `DamageType` are the *what hit you*, and
`DamageTypeTags` is where nearly every branch on the page lives, so
read the tag file before the type file. For death:
`LivingEntity.die` and then `ServerPlayer.die`, which does not call it, with
`CombatTracker` and `FallLocation` for the message. Two doors:
`BlocksAttacks`, the component that replaced shield code, and `VehicleEntity`,
the clearest of the twenty-two branches that inherit none of this. For the
numbers as attributes — armour, toughness, knockback resistance — see
[attributes](attributes#forty-numbers-every-one-of-them-clamped).

---

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