Skip to content

These docs were made completely by AI, so they might be right, or wrong, you'll need to test them yourself. This was made for a easier understanding of everything. So use at your own risk. If anything is wrong, please don't hurt to make a PR on the page you have a problem with. ON GITHUB

Entities

The LCE entity system covers every dynamic object in the world: players, mobs, items, projectiles, vehicles, and special objects like lightning bolts and experience orbs. Each entity lives in its own header and source file under Minecraft.World/.

The entity class hierarchy branches out from the root Entity class, with Mob being the main branch for living creatures.

Entity (abstract)
├── Mob (living entities)
│ ├── PathfinderMob (AI-driven navigation)
│ │ ├── AgableMob (can age / breed)
│ │ │ ├── Animal (+ Creature interface)
│ │ │ │ ├── Cow
│ │ │ │ │ └── MushroomCow
│ │ │ │ ├── Pig
│ │ │ │ ├── Sheep
│ │ │ │ ├── Chicken
│ │ │ │ └── TamableAnimal
│ │ │ │ ├── Wolf
│ │ │ │ └── Ozelot
│ │ │ └── Villager (+ Npc, Merchant interfaces)
│ │ ├── Monster (+ Enemy interface)
│ │ │ ├── Zombie
│ │ │ │ └── PigZombie
│ │ │ ├── Skeleton
│ │ │ ├── Creeper
│ │ │ ├── Spider
│ │ │ │ └── CaveSpider
│ │ │ ├── EnderMan
│ │ │ ├── Silverfish
│ │ │ ├── Blaze
│ │ │ └── Giant
│ │ ├── WaterAnimal (+ Creature interface)
│ │ │ └── Squid
│ │ └── Golem (+ Creature interface)
│ │ ├── VillagerGolem (Iron Golem)
│ │ └── SnowMan (Snow Golem)
│ ├── Slime (+ Enemy interface)
│ │ └── LavaSlime (Magma Cube)
│ ├── FlyingMob
│ │ └── Ghast (+ Enemy interface)
│ ├── BossMob
│ │ └── EnderDragon
│ └── Player (+ CommandSender interface)
├── ItemEntity (dropped items)
├── ExperienceOrb
├── HangingEntity (abstract)
│ ├── Painting
│ └── ItemFrame
├── GlobalEntity
│ └── LightningBolt
├── PrimedTnt
├── FallingTile (falling sand/gravel)
├── Minecart
├── Boat
├── EnderCrystal
└── Projectiles (Arrow, Fireball, SmallFireball, Snowball,
ThrownEnderpearl, EyeOfEnderSignal, ThrownPotion,
ThrownExpBottle, DragonFireball)

Each base class adds a layer of functionality:

Base ClassWhat It Adds
EntityPosition, motion, rotation, bounding box, fire, water, air supply, synched data, save/load, collision, riding
MobHealth, death, AI (GoalSelector), effects, equipment, look/move/jump controls, pathfinding, sensing, knockback, sounds
PathfinderMobA* navigation with configurable range (default 16 blocks), attack target tracking, walk target scoring, wander support
AgableMobBaby/adult system with an age timer, getBreedOffspring() for producing babies
AnimalLove mode, breeding, food items, despawn protection, grass-block spawn checks
TamableAnimalOwner tracking, tame/sit flags, getOwner(), sitting state via synched data
MonsterHostile behavior, burns in daylight, dark spawn checks via isDarkEnoughToSpawn(), attack damage, difficulty scaling
FlyingMobNo gravity, flying movement physics, no fall damage
BossMobBoss bar, special death handling

A few empty or near-empty classes act as markers for classification:

InterfaceFilePurpose
CreatureCreature.hMarks non-hostile living entities
EnemyEnemy.hMarks hostile entities; defines XP reward constants
NpcNpc.hMarks NPC entities (extends Creature)
CommandSenderCommandSender.hAllows sending commands (used by Player)
MerchantMerchant.hTrading interface (implemented by Villager)

Defined in Class.h, the eINSTANCEOF enum replaces Java’s instanceof with a bitfield-based type system. 4J Studios added this to skip dynamic casts on console hardware. Every entity class overrides virtual eINSTANCEOF GetType() to return its type constant.

The values are set up as a bitfield so a single bitwise AND can check category membership:

Bit / MaskCategoryPurpose
0x100eTYPE_WATERANIMALWater creatures
0x200eTYPE_ANIMALLand animals
0x400eTYPE_MONSTERHostile monsters
0x800eTYPE_ENEMYEnemy marker
0x1000eTYPE_VILLAGERGOLEMIron Golem (not a shared category bit; SnowMan uses animal bits instead)
0x2000eTYPE_AGABLE_MOBAgeable/breedable mobs
0x8000eTYPE_PLAYERPlayers
0x40000eTYPE_PROJECTILEProjectiles
0x80000eTYPE_ANIMALS_SPAWN_LIMIT_CHECKAnimals counted for spawn limits
0x100000eTYPE_OTHERSMisc entities (no category bits)

Specific mob types combine these category bits. For example, eTYPE_COW = 0x82201 has the ANIMALS_SPAWN_LIMIT_CHECK, AGABLE_MOB, and ANIMAL bits set, while eTYPE_CHICKEN = 0x2206 doesn’t have the ANIMALS_SPAWN_LIMIT_CHECK bit because chickens have a separate spawn cap.

Because the types are bitfields, you can check category membership with a simple AND:

// Check if an entity is any kind of monster
if ((entity->GetType() & eTYPE_MONSTER) == eTYPE_MONSTER) { ... }
// Check if it's a specific type
if (entity->GetType() == eTYPE_ZOMBIE) { ... }
// MeleeAttackGoal uses this to filter targets
if (attackType != eTYPE_NOTSET && (attackType & bestTarget->GetType()) != attackType)
return false;

This is way faster than dynamic_cast on console hardware, which is the whole reason 4J added it.

Registered in EntityIO::staticCtor(), each entity has a string ID and a numeric ID for network serialization:

Numeric IDString IDeINSTANCEOFClass
1ItemeTYPE_ITEMENTITYItemEntity
2XPOrbeTYPE_EXPERIENCEORBExperienceOrb
9PaintingeTYPE_PAINTINGPainting
10ArroweTYPE_ARROWArrow
11SnowballeTYPE_SNOWBALLSnowball
12FireballeTYPE_FIREBALLFireball
13SmallFireballeTYPE_SMALL_FIREBALLSmallFireball
14ThrownEnderpearleTYPE_THROWNENDERPEARLThrownEnderpearl
15EyeOfEnderSignaleTYPE_EYEOFENDERSIGNALEyeOfEnderSignal
16ThrownPotioneTYPE_THROWNPOTIONThrownPotion
17ThrownExpBottleeTYPE_THROWNEXPBOTTLEThrownExpBottle
18ItemFrameeTYPE_ITEM_FRAMEItemFrame
20PrimedTnteTYPE_PRIMEDTNTPrimedTnt
21FallingSandeTYPE_FALLINGTILEFallingTile
40MinecarteTYPE_MINECARTMinecart
41BoateTYPE_BOATBoat
48MobeTYPE_MOBMob
49MonstereTYPE_MONSTERMonster
50CreepereTYPE_CREEPERCreeper
51SkeletoneTYPE_SKELETONSkeleton
52SpidereTYPE_SPIDERSpider
53GianteTYPE_GIANTGiant
54ZombieeTYPE_ZOMBIEZombie
55SlimeeTYPE_SLIMESlime
56GhasteTYPE_GHASTGhast
57PigZombieeTYPE_PIGZOMBIEPigZombie
58EndermaneTYPE_ENDERMANEnderMan
59CaveSpidereTYPE_CAVESPIDERCaveSpider
60SilverfisheTYPE_SILVERFISHSilverfish
61BlazeeTYPE_BLAZEBlaze
62LavaSlimeeTYPE_LAVASLIMELavaSlime
63EnderDragoneTYPE_ENDERDRAGONEnderDragon
90PigeTYPE_PIGPig
91SheepeTYPE_SHEEPSheep
92CoweTYPE_COWCow
93ChickeneTYPE_CHICKENChicken
94SquideTYPE_SQUIDSquid
95WolfeTYPE_WOLFWolf
96MushroomCoweTYPE_MUSHROOMCOWMushroomCow
97SnowManeTYPE_SNOWMANSnowMan
98OzeloteTYPE_OZELOTOzelot
99VillagerGolemeTYPE_VILLAGERGOLEMVillagerGolem
120VillagereTYPE_VILLAGERVillager
200EnderCrystaleTYPE_ENDER_CRYSTALEnderCrystal
1000DragonFireballeTYPE_DRAGON_FIREBALLDragonFireball

Entities with spawn egg colors are registered through the overloaded setId() that takes eMinecraftColour parameters and a name ID, populating EntityIO::idsSpawnableInCreative.

EntityIO (EntityIO.h / EntityIO.cpp) is the entity factory and registry. It keeps several parallel lookup maps:

MapKeyValuePurpose
idCreateMapwstring (string ID)entityCreateFnCreate entity by string ID
numCreateMapint (numeric ID)entityCreateFnCreate entity by numeric ID
classIdMapeINSTANCEOFwstringGet string ID from type enum
classNumMapeINSTANCEOFintGet numeric ID from type enum
numClassMapinteINSTANCEOFGet type enum from numeric ID
idNumMapwstringintGet numeric ID from string ID

Each entity class has a static create(Level *level) factory function stored as a function pointer (entityCreateFn). The key creation methods are:

  • newEntity(wstring id, Level*): Create by string ID (used when loading from NBT)
  • loadStatic(CompoundTag*, Level*): Load from NBT tag (reads the "id" string, creates the entity, then calls entity->load())
  • newById(int id, Level*): Create by numeric ID (used in network packets)
  • newByEnumType(eINSTANCEOF, Level*): Create by type enum (used by the mob spawner)

If getId() can’t find a string ID, it defaults to numeric ID 90 (Pig). This is a fun little fallback. If your entity type isn’t registered properly, it just becomes a pig.

SynchedEntityData (SynchedEntityData.h) is the system that syncs entity state from server to client using a compact binary protocol.

Type ConstantValueC++ Type
TYPE_BYTE0byte
TYPE_SHORT1short
TYPE_INT2int
TYPE_FLOAT3float
TYPE_STRING4wstring
TYPE_ITEMINSTANCE5shared_ptr<ItemInstance>
TYPE_POS6Pos*

Each data entry is keyed by an ID. The ID and type are packed into a single byte:

  • Bits 0-4: Data item ID (max value MAX_ID_VALUE = ~TYPE_MASK & 0xFF = 31)
  • Bits 5-7: Data type (0-6)
  • EOF marker: 0x7F
  • Max string length: 64 characters

Each DataItem stores its value as separate typed fields rather than a generic Object like Java. The 4J port just keeps value_byte, value_int, value_short, value_wstring, and value_itemInstance as separate members. This avoids any boxing/unboxing overhead on console hardware.

The SynchedEntityData class itself stores items in an unordered_map<int, shared_ptr<DataItem>> keyed by data ID. It provides typed getters: getByte(), getShort(), getInteger(), getFloat(), getString(), getItemInstance(), and getPos().

Each entity calls defineSynchedData() (a pure virtual in Entity) to register its synched fields. The base Entity defines:

IDTypeField
0byteDATA_SHARED_FLAGS_ID, a bitfield of shared flags
1shortDATA_AIR_SUPPLY_ID, air supply

Mob adds:

IDTypeField
8intDATA_EFFECT_COLOR_ID, potion effect color

AgableMob adds:

IDTypeField
12intDATA_AGE_ID, entity age

Animal adds:

IDTypeField
13intDATA_IN_LOVE, love/breeding state

Specific mobs define additional IDs starting from 16:

MobID(s)Fields
Creeper16, 17Swell direction, is powered
Spider16Climbing flags
Zombie12, 13, 14Baby, villager, converting
EnderMan16, 17, 18Carry item ID, carry data, creepy state
Ghast16Is charging
Blaze16Flags (charged state)
Pig16Has saddle
Sheep16Wool color and sheared state
Wolf18, 19, 20Health, interested, collar color
TamableAnimal16, 17Flags (tame/sitting), owner UUID
Villager16Profession ID
VillagerGolem16Flags (player-created)
Slime16Size
EnderDragon16, 17Synched health, synched action
Player16, 17Player flags, running state
Minecart16, 17, 18, 19Fuel, hurt, hurt direction, damage
Boat17, 18, 19Hurt, hurt direction, damage
ItemEntity10The item stack

The base Entity class uses a single byte at ID 0 as a bitfield:

BitConstantMeaning
0FLAG_ONFIREEntity is on fire
1FLAG_SNEAKINGEntity is sneaking
2FLAG_RIDINGEntity is riding another
3FLAG_SPRINTINGEntity is sprinting
4FLAG_USING_ITEMEntity is using an item
5FLAG_INVISIBLEEntity is invisible
6FLAG_IDLEANIMIdle animation state
7FLAG_EFFECT_WEAKENEDWeakened by potion (4J addition for the cure villager tooltip)

These flags are read/written through getSharedFlag(bit) and setSharedFlag(bit, value). Both are protected methods, so only Entity and its friends (like Gui) can use them directly. Public accessors like isSneaking(), isSprinting(), isInvisible() wrap these.

Each DataItem has a dirty flag. When a value changes through set(), the item gets marked dirty. packDirty() returns only the changed items for delta updates. packAll() serializes everything (used on initial sync). The SetEntityDataPacket carries these updates over the network.

The SynchedEntityData class also tracks a global m_isDirty flag so the server can quickly check if any data changed without scanning every item.

Every entity has an axis-aligned bounding box (AABB *bb) that defines its collision volume. The setSize(float w, float h) method sets bbWidth and bbHeight, then rebuilds the AABB around the entity’s current position.

Two key virtual methods control entity-to-entity collision:

  • getCollideBox(): Returns the AABB that other entities collide with when moving. Most entities return nullptr (no collision). Boat and Minecart override this to return their AABB so players can ride into them.
  • getCollideAgainstBox(Entity): Returns the AABB used when checking if two entities are overlapping for push physics. Boat and Minecart return their AABB here too.

Entity::move(xa, ya, za) is the core movement method. It does:

  1. Check if stuck in a web (cuts speed to 5% if so)
  2. Get all tile collision boxes from the level in the movement path
  3. Resolve Y axis first, then X, then Z against those boxes
  4. Also check entity collision boxes (getCollideAgainstBox)
  5. Update the AABB to the new position
  6. Set onGround, horizontalCollision, verticalCollision flags
  7. Play step sounds, check fall damage, check inside tiles (portals, tripwires, etc.)
  8. Apply friction and web stuck slowdown

The noEntityCubes parameter (a 4J addition) lets the movement skip entity collision boxes for performance in certain situations.

When entities overlap, Entity::push(Entity) applies separation forces. The force is based on the overlap distance. isPushable() controls whether an entity can be pushed at all. Mobs are pushable, dropped items are not.

DamageSource (DamageSource.h) represents what caused the damage. It uses static singleton instances for environmental damage and factory methods for entity-caused damage.

SourceDescriptionProperties
inFireStanding in fireFire
onFireBurningFire, bypasses armor
lavaIn lavaFire
inWallSuffocating in a blockBypasses armor
drownDrowningBypasses armor
starveStarvationBypasses armor
cactusCactus damage
fallFall damageBypasses armor
outOfWorldFalling into the voidBypasses armor, bypasses invulnerability
genericSourceGeneric damageBypasses armor
explosionExplosionScales with difficulty
controlledExplosionPlayer-caused explosion
magicMagic damageBypasses armor, magic
dragonbreathDragon breathBypasses armor
witherWither effectBypasses armor
anvilFalling anvil
fallingBlockFalling block
MethodReturnsPurpose
mobAttack(Mob)EntityDamageSourceMelee mob attack
playerAttack(Player)EntityDamageSourcePlayer melee attack
arrow(Arrow, Entity)IndirectEntityDamageSourceArrow damage
fireball(Fireball, Entity)IndirectEntityDamageSourceFireball damage
thrown(Entity, Entity)IndirectEntityDamageSourceThrown projectile damage
indirectMagic(Entity, Entity)IndirectEntityDamageSourceIndirect magic damage
thorns(Entity)EntityDamageSourceThorns enchantment damage
PropertyMethodEffect
_bypassArmorisBypassArmor()Damage ignores armor
_bypassInvulisBypassInvul()Damage ignores invulnerability frames
isFireSourceisFire()Source is fire-based
_isProjectileisProjectile()Source is a projectile
_scalesWithDifficultyscalesWithDifficulty()Damage scales with difficulty
_isMagicisMagic()Magic damage
exhaustiongetFoodExhaustion()Food exhaustion caused (default EXHAUSTION_ATTACK, set to 0 when bypassArmor is called)
DamageSource
└── EntityDamageSource (damage from an entity)
└── IndirectEntityDamageSource (damage from a projectile with an owner)

EntityDamageSource stores a shared_ptr<Entity> to the attacker. getEntity() returns it. scalesWithDifficulty() returns true for mob attacks but false for player attacks.

IndirectEntityDamageSource stores both the direct entity (the projectile) and the owner. getDirectEntity() returns the projectile, getEntity() returns the owner. This is how kill credit goes to the player who shot an arrow, not the arrow itself.

When Mob::hurt() is called, the damage goes through several stages:

  1. hurtArmor(damage): Reduces durability on the mob’s armor items.
  2. getDamageAfterArmorAbsorb(source, damage): Reduces damage based on getArmorValue() (0-20 scale). Skipped if source.isBypassArmor().
  3. getDamageAfterMagicAbsorb(source, damage): Applies enchantment-based damage reduction. Skipped if source.isBypassArmor().
  4. actuallyHurt(source, damage): Applies the final damage to health.

Player overrides getArmorValue() to compute armor value from equipped ArmorItem pieces and overrides hurtArmor() to damage the inventory armor items.

4J Studios added EEntityDamageType for tracking player death stats:

Enum ValueCause
eEntityDamageType_EntityKilled by entity
eEntityDamageType_FallFall damage
eEntityDamageType_FireFire
eEntityDamageType_LavaLava
eEntityDamageType_WaterDrowning
eEntityDamageType_SuffocateSuffocation
eEntityDamageType_OutOfWorldVoid
eEntityDamageType_CactusCactus

Defined in MobType.h, this enum is used by damage enchantments to apply bonus damage:

ValueMeaning
UNDEFINEDDefault
UNDEADUndead mobs (Zombie, Skeleton, PigZombie)
ARTHROPODArthropods (Spider, CaveSpider, Silverfish)

Mobs override getMobType() to return the right value. For example, Zombie::getMobType() returns UNDEAD, and Spider::getMobType() returns ARTHROPOD.

Entity IDs are split into two ranges (a 4J console optimization):

  • Small IDs (0-2047): For network-tracked entities. Allocated from a bitfield (entityIdUsedFlags[2048/32]) on the server thread only. Only needs 11 bits in network packets.
  • Large IDs (2048+): For particles and other non-tracked entities. Assigned from an incrementing counter that wraps at 0x7FFFFFF back to 2048.

Thread-local storage (TlsGetValue(tlsIdx)) makes sure small IDs are only allocated from the server thread.

Every entity constructor follows this pattern:

  1. Call Entity(level, useSmallId) which runs _init(useSmallId) to assign an entity ID
  2. Call defineSynchedData() to register synched fields. This is done in the most-derived constructor because virtual dispatch doesn’t work in base constructors in C++.
  3. Set health = getMaxHealth() after synched data is ready
  4. Set up texture, bounding box size, and navigation options
  5. Register AI goals (for mobs)

The zombie constructor is a good example:

Zombie::Zombie(Level *level) : Monster(level)
{
this->defineSynchedData();
health = getMaxHealth();
this->textureIdx = TN_MOB_ZOMBIE;
runSpeed = 0.23f;
attackDamage = 4;
setSize(bbWidth, bbHeight);
getNavigation()->setCanOpenDoors(true);
// AI goals...
goalSelector.addGoal(0, new FloatGoal(this));
goalSelector.addGoal(1, new BreakDoorGoal(this));
// ... etc
}

The core update loop:

  1. Entity::tick(): Calls baseTick(), the entry point for per-tick updates.
  2. Entity::baseTick(): Handles:
    • Fire timer and fire damage (lavaHurt(), burn())
    • Water state (updateInWaterState())
    • Air supply (drowning): decreases by 1 per tick when submerged, deals 2 damage every tick at 0 supply. Total air supply is 20 * 15 = 300 ticks (15 seconds).
    • Web stuck state
    • Portal handling
    • Tick counter increment
  3. Mob::tick(): Adds on top of the base with:
    • superTick() for base Entity tick
    • AI step (aiStep())
    • Body rotation updates
    • Effect ticking (tickEffects())
    • Death handling (tickDeath() when deathTime > 0)
  4. Mob::aiStep(): Handles:
    • Despawn checking (checkDespawn())
    • Sensing updates (sensing->tick() clears the seen/unseen caches each tick)
    • Target selection
    • Goal selector ticks (goalSelector.tick(), targetSelector.tick())
    • Navigation and movement controls (lookControl->tick(), moveControl->tick(), jumpControl->tick())
    • Travel physics (travel())

Entities serialize to NBT CompoundTag structures:

Entity::save(CompoundTag*) writes:

  • "id": String entity type ID (from EntityIO)
  • Then calls saveWithoutId():
    • "Pos": DoubleList of x, y, z
    • "Motion": DoubleList of xd, yd, zd (clamped to abs <= 10.0 on load)
    • "Rotation": FloatList of yRot, xRot
    • "FallDistance": float
    • "Fire": short (fire timer)
    • "Air": short (air supply)
    • "OnGround": boolean
    • Then calls addAdditonalSaveData() (virtual, overridden by each entity)

Entity::load(CompoundTag*) reads:

  • Position, motion, rotation from the lists above
  • Clamps motion values to abs <= 10.0
  • Reads fall distance, fire, air supply, on-ground state
  • Calls readAdditionalSaveData() (virtual, overridden by each entity)

EntityIO::loadStatic(CompoundTag*, Level*) is the entry point for loading any entity from NBT. It reads the "id" string, creates the entity through the factory, then calls entity->load().

  1. Mob::die(DamageSource*): Called when health reaches zero:
    • Awards XP to the killing player (if lastHurtByPlayer is set)
    • Calls dropDeathLoot() to spawn item drops
    • Calls dropRareDeathLoot() for rare loot (affected by Looting enchantment)
    • Awards kill score via sourceEntity->awardKillScore()
    • Notifies the killer via sourceEntity->killed()
  2. Mob::tickDeath(): Called each tick while deathTime counts up:
    • Increments deathTime
    • At deathTime == 20, calls remove() to despawn the entity
  3. Entity::remove(): Marks the entity as removed = true, freeing its small ID.

Mob::checkDespawn() runs every tick through aiStep(). The 4J console version adds despawn protection for animals:

  • Animals default to despawnProtected = true when spawned
  • Animal::updateDespawnProtectedState() tracks how far an animal has wandered using m_minWanderX/Z and m_maxWanderX/Z
  • If an animal wanders more than MAX_WANDER_DISTANCE (20 tiles) from where it was last protected, it loses protection and can be despawned
  • The “extra wandering” system (Entity::tickExtraWandering()) periodically picks up to 3 entities at a time (EXTRA_WANDER_MAX) to wander for 30 seconds (EXTRA_WANDER_TICKS), figuring out whether they’re enclosed in a farm
  • isExtraWanderingEnabled() and getWanderingQuadrant() are used by RandomStrollGoal to make these chosen entities wander in a specific direction

Several goals also call setDespawnProtected() when they detect a nearby player, like TemptGoal and BegGoal. The idea is: if a player is interacting with this mob, don’t despawn it.

MobSpawner (MobSpawner.h / MobSpawner.cpp) handles natural mob spawning. The console version differs quite a bit from Java edition.

Defined in MobCategory (MobCategory.h), each category has a spawn material and hard cap:

CategoryFriendlyMaterialHard Limit
monsterNoAir50
creatureYesAir50
waterCreatureYesWater5
creature_wolfYesAir8
creature_chickenYesAir8
creature_mushroomcowYesAir2

4J Studios broke wolves, chickens, and mooshrooms into separate categories so they could control spawning more precisely. Breeding and spawn eggs let you go past the base limits:

EntityNatural+ Breeding+ Spawn Egg
Animals (total)507090
Chickens81626
Wolves81626
Mooshrooms22230
Monsters5070
Squid513
Villagers353550
Snow Golems16
Iron Golems16

MobSpawner::tick() runs each server tick:

  1. Build the chunk poll set: Iterates outward from each player in a spiral (radius 8 chunks). Chunks at the edge are flagged to prevent spawning at the boundary.
  2. For each mob category: Check if the global count is below the hard limit.
  3. For each eligible chunk: Pick a random position. If the position works:
    • Must be at least MIN_SPAWN_DISTANCE (24 blocks) from any player
    • Must be at least 24 blocks from the world spawn
    • Must pass isSpawnPositionOk() checks
  4. 50% rule: No single mob type can take more than 50% of its category’s total limit (prevents one type from taking over).
  5. Special rules:
    • Ghasts are capped at 4
    • Endermen in The End get a higher cap, scaled by difficulty
  6. Post-spawn: finalizeMobSettings() handles special cases:
    • 1% chance for a Spider to spawn with a Skeleton jockey
    • Sheep get a random wool color
    • Ocelots have a 1-in-7 chance to spawn with 2 kittens

Different mob types have different spawn requirements:

  • Monsters: Must pass isDarkEnoughToSpawn() (light level check) and canSpawn() (block checks)
  • Animals: Need a grass block below and light level >= 9
  • Water mobs: Need deep, wide water: 5 blocks deep and at least 5 blocks wide in all cardinal directions
  • Custom checks: Any mob can override canSpawn() for special conditions

Each biome has lists of mobs that can spawn there, stored as MobSpawnerData objects with a type, weight, and min/max group size. The base Biome constructor sets up default lists (zombies, skeletons, spiders for monsters; sheep, pigs, cows, chickens for friendlies). Specific biomes override or extend these.

MobSpawner::attackSleepingPlayers() runs when players try to sleep. It pathfinds from a random position to the player’s bed:

  • Eligible enemy types: Spider, Zombie, Skeleton
  • Uses PathFinder to check if a valid path exists to the bed
  • If a path is found, the mob is placed at the bed and the player gets woken up

EntityEvent (EntityEvent.h) defines byte constants for client-side event notifications sent through EntityEventPacket:

ConstantValueEvent
JUMP1Entity jumped
HURT2Entity was hurt
DEATH3Entity died
START_ATTACKING4Started attacking
STOP_ATTACKING5Stopped attacking
TAMING_FAILED6Taming attempt failed
TAMING_SUCCEEDED7Taming succeeded
SHAKE_WETNESS8Wolf shaking off water
USE_ITEM_COMPLETE9Finished using item
EAT_GRASS10Sheep eating grass
OFFER_FLOWER11Iron Golem offering flower
LOVE_HEARTS12Love heart particles
VILLAGER_ANGRY13Angry villager particles
VILLAGER_HAPPY14Happy villager particles
WITCH_HAT_MAGIC15Witch hat magic effect
ZOMBIE_CONVERTING16Zombie converting to villager
FIREWORKS_EXPLODE17Fireworks explosion
IN_LOVE_HEARTS18In-love heart particles

Events are broadcast with level->broadcastEntityEvent(entity, eventId) on the server side. The client receives them through handleEntityEvent(byte) which each entity overrides to trigger the right visual effect. For example, the Zombie handles ZOMBIE_CONVERTING to play the remedy sound effect.

Player (Player.h) extends Mob and adds a lot of extra functionality.

ConstantValuePurpose
MAX_NAME_LENGTH20Maximum player name length (16 + 4)
MAX_HEALTH20Maximum health points
SWING_DURATION6Arm swing animation ticks
SLEEP_DURATION100Ticks required to sleep
WAKE_UP_DURATION10Wake-up animation ticks
DEATHFADE_DURATION21Death fade animation ticks (4J addition)

The EPlayerGamePrivileges enum (a 4J addition) is a bitfield stored in an unsigned int that controls trust-based permissions:

PrivilegeBitDescription
CannotMine0Prevents mining
CannotBuild1Prevents placing blocks
CannotAttackMobs2Prevents attacking mobs
CannotAttackPlayers3Prevents attacking players
Op4Operator status
CanFly5Flight permission
ClassicHunger6Classic hunger mode
Invisible7Invisibility
Invulnerable8Invulnerability
CreativeMode9Creative mode (network transfer only)
CannotAttackAnimals10Prevents attacking animals
CanUseDoorsAndSwitches11Door/switch permission
CanUseContainers12Container access permission
CanToggleInvisible13Can toggle invisibility
CanToggleFly14Can toggle flight
CanToggleClassicHunger15Can toggle classic hunger
CanTeleport16Can teleport
  • Inventory: shared_ptr<Inventory> inventory and an Ender Chest inventory (PlayerEnderChestContainer)
  • Food system: FoodData tracks hunger, saturation, and exhaustion
  • Experience: experienceLevel, totalExperience, experienceProgress
  • Sleeping: Full bed sleeping system with BedSleepingResult enum (OK, NOT_POSSIBLE_HERE, NOT_POSSIBLE_NOW, TOO_FAR_AWAY, OTHER_PROBLEM, NOT_SAFE)
  • Abilities: Abilities object for game mode abilities (fly, instabuild, etc.)
  • Custom skins: EDefaultSkins (8 default skins), custom skin IDs, custom capes
  • Fishing: shared_ptr<FishingHook> fishing
  • Guest system: isGuest() for guest players
  • Map visibility: canShowOnMaps() respects invisible privilege
  • XUID/UUID: Platform-specific player identification

Player::getArmorValue() adds up the defense values from all equipped ArmorItem pieces. getArmorCoverPercentage() calculates what percentage of armor slots are filled, which is used for enchantment calculations.

Mobs use a goal-based AI system through GoalSelector (GoalSelector.h). Each Mob has two selectors:

  • goalSelector: Behavior goals (movement, interaction, idle actions)
  • targetSelector: Target selection goals (who to attack)

Goals get wrapped in InternalGoal objects with a priority number. Each tick, the selector:

  1. Checks which goals can start (canUseInSystem())
  2. Checks which running goals can keep going (canContinueToUse())
  3. Checks co-existence rules (canCoExist()) between goals

Lower priority numbers take precedence. Goals are added with addGoal(priority, goal).

Each Mob creates several control objects in its constructor:

ControlClassPurpose
lookControlLookControlHead rotation toward targets. Has setLookAt(entity, yMax, xMax) and setLookAt(x, y, z, yMax, xMax). Ticks every frame to smoothly rotate the head toward the wanted position.
moveControlMoveControlMovement velocity and direction. setWantedPosition(x, y, z, speed) tells the mob where to go. On tick, it calculates the rotation and sets the mob’s speed. Stops if distance is less than MIN_SPEED_SQR. Triggers jump if target is above.
jumpControlJumpControlJump triggering. jump() sets a flag, tick() triggers the actual jump.
bodyControlBodyControlBody rotation alignment
navigationPathNavigationA* pathfinding (configurable range, defaults to 16 blocks)
sensingSensingLine-of-sight checks with per-tick caching. Maintains seen and unseen lists that are cleared every tick.

The Sensing class is a simple optimization. Every tick, it clears its seen and unseen entity lists. When canSee(target) is called, it first checks the cache. If the target isn’t cached, it calls mob->canSee(target) (which does a raycast) and caches the result. This way, if multiple goals check visibility on the same target in the same tick, the raycast only happens once.

MobHealthInheritsSpecial Features
Cow10AnimalMilkable with bucket
MushroomCow10CowShearable for mushrooms
Pig10AnimalSaddleable, controllable; lightning converts to PigZombie
Sheep8AnimalShearable wool, dyeable; eats grass to regrow
Chicken4AnimalNo fall damage, lays eggs
Squid10WaterAnimalWater-only, tentacle animation
Wolf8/20TamableAnimalTameable, sittable, dyeable collar, angry mode
Ozelot10TamableAnimalTameable, 4 cat types, no fall damage
Villager20AgableMob + Npc + Merchant5 professions, trading, breeding
MobHealthInheritsSpecial Features
Zombie20MonsterBaby variant, villager variant, villager conversion
PigZombie20ZombieAnger system, alerts nearby PigZombies, carries gold sword
Skeleton20MonsterCarries bow, UNDEAD mob type
Creeper20MonsterSwell/explode mechanic, powered by lightning
Spider16MonsterWall climbing, ARTHROPOD mob type, jockey host
CaveSpider12SpiderSmaller, applies poison on hit
EnderMan40MonsterTeleportation, block carrying, aggro on eye contact
Silverfish8MonsterCalls friends when hurt, ARTHROPOD mob type
Blaze20MonsterFlying attacks, fire projectiles, always lit
Giant100MonsterGiant zombie, no AI
SlimevariesMob + EnemySize-based health, splits on death
LavaSlimevariesSlimeNether variant, has armor, fire immune
Ghast10FlyingMob + EnemyFlying, shoots fireballs
MobHealthInheritsSpecial Features
VillagerGolem100GolemVillage defense, no fall damage, offers flowers
SnowMan4GolemThrows snowballs, leaves snow trail
MobHealthInheritsSpecial Features
EnderDragonvariesBossMobMulti-part entity (head, neck, body, tail, wings), ender crystal healing, pathfinding AI with holding pattern / strafe / landing / sitting states
EntityClassKey Features
ItemEntityEntityDropped items. Has a 5-minute lifetime (LIFETIME = 5 * 60 * 20). Merges with nearby identical items. DATA_ITEM at synch ID 10 holds the item stack. Has health (destroyed by fire, lava, explosions).
ExperienceOrbEntityXP orbs. Attracted to nearby players. Has an age and value.
PaintingHangingEntityWall art. Picks from available motifs based on wall size.
ItemFrameHangingEntityHolds an item on a wall. Can rotate the displayed item.
LightningBoltGlobalEntityLightning strike. Global entities are visible to all players regardless of distance. Lasts a few ticks, sets nearby blocks on fire.
PrimedTntEntityTicking TNT. Fuse timer counts down, then explodes.
FallingTileEntityFalling sand/gravel. Checks block below each tick, places itself when landing.
MinecartEntity + ContainerRideable/chest/furnace types (all in one class via type field). Follows rails, has physics for powered rails and slopes. Synch IDs 16-19 for fuel, hurt, hurt direction, damage.
BoatEntityWater vehicle. Has acceleration and speed physics. Breaks on collision (drops planks and sticks). Synch IDs 17-19 for hurt, hurt direction, damage.
EnderCrystalEntityHeals the Ender Dragon. Explodes when destroyed.
EntityDescription
ArrowShot by skeletons and players. Sticks in blocks. Has pickup rules. Tracks its owner for kill credit.
FireballShot by Ghasts. Explodes on impact. Can be deflected by hitting it.
SmallFireballShot by Blazes. Sets blocks on fire. Smaller explosion than Fireball.
SnowballThrown by players and Snow Golems. Deals knockback, 3 damage to Blazes.
ThrownEnderpearlTeleports the thrower to the impact point. Deals 5 fall damage to the thrower.
EyeOfEnderSignalFloats toward the nearest stronghold. Breaks or drops after a short flight.
ThrownPotionSplash potion. Applies effects in an area on impact.
ThrownExpBottleDrops XP orbs on impact.
DragonFireballShot by the Ender Dragon. Leaves lingering damage area.

These are the most important virtual methods that entity subclasses override:

MethodDeclared InPurpose
GetType()EntityReturns eINSTANCEOF enum for type checking
defineSynchedData()EntityRegister synched data fields
tick()EntityPer-tick update
baseTick()EntityCore tick logic (fire, water, air)
hurt(DamageSource*, int)EntityTake damage
die(DamageSource*)MobHandle death
getMaxHealth()MobReturn maximum HP (pure virtual)
aiStep()MobAI and physics update
canSpawn()MobValidate spawn position
readAdditionalSaveData(CompoundTag*)EntityLoad entity-specific NBT data
addAdditonalSaveData(CompoundTag*)EntitySave entity-specific NBT data
getDeathLoot()MobReturn item ID dropped on death
dropDeathLoot(bool, int)MobSpawn death drops
dropRareDeathLoot(int)MobSpawn rare drops (Looting-affected)
getAmbientSound()MobReturn ambient sound ID
getHurtSound()MobReturn hurt sound ID
getDeathSound()MobReturn death sound ID
useNewAi()MobWhether to use goal-based AI (returns false by default!)
getMobType()MobReturn MobType for enchantment bonuses
interact(Player)EntityHandle player right-click interaction
finalizeMobSpawn()MobPost-spawn initialization
removeWhenFarAway()MobWhether to despawn when distant
getExperienceReward(Player)MobXP dropped when killed by player
getBreedOffspring(AgableMob)AgableMobCreate baby entity for breeding
getWalkTargetValue(int, int, int)PathfinderMobScore a position for wandering (monsters prefer dark, animals prefer grass)
isDarkEnoughToSpawn()MonsterLight level check for natural spawning
canBeControlledByRider()MobWhether a riding player can steer (Pig with carrot on stick)
isFood(ItemInstance)AnimalWhether an item triggers love mode
canMate(Animal)AnimalWhether two animals can breed together

Entity state gets communicated through several packet types:

PacketPurpose
AddEntityPacketSpawn a non-mob entity
AddMobPacketSpawn a mob entity
AddPlayerPacketSpawn a player entity
AddGlobalEntityPacketSpawn a global entity (lightning)
AddPaintingPacketSpawn a painting
AddExperienceOrbPacketSpawn an experience orb
RemoveEntitiesPacketDespawn entities
MoveEntityPacketFull position/rotation update
MoveEntityPacketSmallDelta position update
TeleportEntityPacketAbsolute position teleport
SetEntityDataPacketSynched entity data update
SetEntityMotionPacketVelocity update
SetEquippedItemPacketEquipment change
SetRidingPacketMount/dismount
RotateHeadPacketHead rotation update
EntityEventPacketEntity event (hurt, death, etc.)
AnimatePacketAnimation trigger
InteractPacketPlayer interaction with entity
MovePlayerPacketPlayer position update

MC adds a bunch of new entity types that LCEMP doesn’t have:

EntityTypeNumeric IDNotes
WitchMonster66Ranged potion attacks, uses RangedAttackGoal
WitherBossBoss64Second boss mob, multi-part entity like the Ender Dragon
BatAmbient65First ambient creature type, uses new AmbientCreature base class
EntityHorseAnimal100Covers horses, donkeys, mules, skeleton horses, and zombie horses (TYPE_DONKEY, TYPE_MULE, TYPE_SKELETON, TYPE_UNDEAD variants)
EntityNumeric IDNotes
LeashFenceKnotEntity8Invisible entity on a fence post that holds a lead
FireworksRocketEntity22Fireworks rocket projectile
MinecartChest43Chest minecart
MinecartFurnace44Powered minecart
MinecartTNT45TNT minecart
MinecartHopper46Hopper minecart
MinecartSpawner47Spawner minecart

In LCEMP, there’s a single Minecart class (ID 40) and Boat class (ID 41). MC splits minecarts into typed subclasses with a shared MinecartContainer base for the ones that hold items.

MC adds several base classes that don’t exist in LCEMP:

  • AmbientCreature: Base class for ambient mobs like bats. Sits between PathfinderMob and specific ambient entities.
  • MultiEntityMob / MultiEntityMobPart: For multi-part entities. LCEMP handled the Ender Dragon’s parts differently.
  • LivingEntity: MC seems to be starting to split Mob responsibilities. This file exists in MC but not LCEMP.
  • Projectile: A shared interface/base for projectile entities.
  • OwnableEntity: Interface for entities that can be owned (used by horses and tameable animals).

MC adds a full attribute system for mobs. Instead of hardcoded health/speed/damage values, mobs register attributes with modifiers:

  • SharedMonsterAttributes defines standard attributes like MAX_HEALTH, FOLLOW_RANGE, KNOCKBACK_RESISTANCE, MOVEMENT_SPEED, ATTACK_DAMAGE
  • AttributeModifier can add, multiply, or scale attribute values
  • BaseAttributeMap / ServersideAttributeMap manage per-entity attribute instances
  • UpdateAttributesPacket syncs attribute values to clients

LCEMP doesn’t have any of this. Health and speed are just direct member variables on the Mob class.

MC adds CombatEntry and CombatTracker classes for tracking combat events (who hit whom, when, with what). This feeds into death messages and the scoreboard system. LCEMP just has the basic DamageSource system.

MC adds EntitySelector / PlayerSelector for command-style entity targeting (@a, @e, @p, @r). This works with the command block system that MC adds.