Skip to content

Conversation

@onebeastchris
Copy link
Member

@onebeastchris onebeastchris commented Nov 25, 2025

Introducing: Custom Entities!

tl;dr: with this PR, you can summon custom bedrock entities that replace the vanilla mapping

Additions

  • CustomEntityDefinition / GeyserEntityDefinition: Representations of custom, and vanilla Bedrock entities. Unlike custom blocks/items, bedrock entities have fewer properties that are defined in advance; it's just the identifier, and the Bedrock Entity Properties. Setting entity properties was introduced in a previous PR; and works the same way.

  • JavaEntityType: Represents a vanilla Java entity type, with the width / height / type identifier, as well as the default Bedrock entity associated with it. Similarly, CustomJavaEntityType represents a non-vanilla Java entity - however, that part of the API still needs some more work and should be regarded as unstable.

  • GeyserEntityDataType / GeyserEntityDataTypes: These are representations of various Bedrock entity metadata types, such as scale, width, height, variant, or color. Further, vertical_offset has been added as a "custom" data type to allow setting a vertical entity offset.

  • The GeyserEntity class has seen major additions! You can now query the entities' associated Bedrock entity definition, Java position, the Geyser id, UUID, or update / query the aforementioned data types.

  • You can now look up GeyserEntity instances using the entity UUID or Geyser entity ID, additionally to the Java entity id.

New Events

  • GeyserDefineEntitiesEvent: Allows registering custom Bedrock entities and querying existing entities.

  • SessionSpawnEntityEvent: Base entity spawn event extended by the server events. With it, you can set a pre-spawn consumer, and switch the Bedrock entity definition, or cancel the entity spawn outright.

  • ServerAttachParrotsEvent: Called every time a parrot is spawned on the player entity

  • ServerSpawnEntityEvent: Called for every non-player entity that is spawned by the Java server. Within this event, you can query the Java entity type, uuid, and entity id (and also have access to the methods provided by the SessionSpawnEntityEvent!

Here's some example code of the API in action:
https://gist.github.com/onebeastchris/1521ab585669792a79a9558d9d069834

image image

Internal changes:

  • Bedrock entity definitions are now split from the Java entity definitions.
  • There is now a EntitySpawnContext that is passed in entity constructors - instead of many arguments. This should make it easier to add new entities, call events, or add more arguments in the future
  • Entity offsets are now properly handled in the base Entity class - no more hacks in TntEntity and the like!

TO-DO's:

  • Finish VanillaEntityBases split; potentially allow non-vanilla entities to extend those?
  • Debug logging for modifications
  • Sensible limits for scale / height / width
  • Docs

EXPERIMENTAL downloads:

Copilot AI review requested due to automatic review settings November 25, 2025 21:38
@onebeastchris onebeastchris added Work in Progress The issue is currently being worked on. PR: Feature When a PR implements a new feature API The issue/feature request relates to the Geyser API labels Nov 25, 2025
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements a Custom Entity API for Geyser, refactoring entity creation to use a context-based approach instead of individual constructor parameters. The changes enable support for custom entities while modernizing the entity type system.

Key Changes:

  • Introduced EntitySpawnContext as a unified way to pass entity creation parameters
  • Renamed EntityDefinition to EntityTypeDefinition for clarity
  • Changed EntityType to BuiltinEntityType to distinguish vanilla entities from custom ones
  • Added new registries for custom entities and Bedrock entity definitions
  • Refactored 100+ entity class constructors to use the new context pattern

Reviewed changes

Copilot reviewed 192 out of 193 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
gradle/libs.versions.toml Updated mcprotocollib version to feature branch for custom entities
Test files Updated mock entity creation to use EntitySpawnContext
StatisticsUtils.java Changed entity name translation to use GeyserEntityType
EntityUtils.java Refactored entity type comparisons from switch to if-else with .is() method
Translator classes Updated to use BuiltinEntityType and new entity creation patterns
Session/cache classes Updated entity instantiation with EntitySpawnContext
Registry classes Added new registries for custom entity support
Entity hierarchy All entity constructors refactored to accept EntitySpawnContext

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.

Copilot AI review requested due to automatic review settings November 27, 2025 21:13
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 222 out of 223 changed files in this pull request and generated 11 comments.

Comments suppressed due to low confidence (1)

core/src/main/java/org/geysermc/geyser/session/GeyserSession.java:610


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.

Copilot AI review requested due to automatic review settings December 19, 2025 20:31
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot reviewed 243 out of 244 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI review requested due to automatic review settings December 22, 2025 23:16
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 244 out of 245 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

…tities-api

# Conflicts:
#	core/src/main/java/org/geysermc/geyser/entity/type/Entity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/player/AvatarEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/player/MannequinEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/player/SkullPlayerEntity.java
#	core/src/main/java/org/geysermc/geyser/skin/SkinManager.java
#	core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockNetworkStackLatencyTranslator.java
#	core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaRemoveMobEffectTranslator.java
#	core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java
Copilot AI review requested due to automatic review settings January 10, 2026 20:31
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot reviewed 248 out of 249 changed files in this pull request and generated 5 comments.

Comments suppressed due to low confidence (1)

core/src/main/java/org/geysermc/geyser/session/GeyserSession.java:625


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

}

List<Hitbox> boxes = new ArrayList<>();
List<NbtMap> hitboxes = metaDataMap.getList("Hitxboxes", NbtType.COMPOUND);
Copy link

Copilot AI Jan 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in NBT key name: "Hitxboxes" should be "Hitboxes" (note the extra 'x')

Copilot uses AI. Check for mistakes.
…tities-api

# Conflicts:
#	core/src/main/java/org/geysermc/geyser/entity/VanillaEntities.java
#	core/src/main/java/org/geysermc/geyser/entity/spawn/EntitySpawnContext.java
#	core/src/main/java/org/geysermc/geyser/entity/type/AbstractArrowEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/BoatEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/Entity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/FireballEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/FishingHookEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/InteractionEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/LeashKnotEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/MinecartEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/TNTEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/TextDisplayEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/ThrowableEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/ThrowableItemEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/WitherSkullEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/living/AbstractFishEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/living/AgeableEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/living/MagmaCubeEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/living/SquidEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SnifferEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/CamelEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/AbstractMerchantEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/living/monster/EnderDragonEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/living/monster/EnderDragonPartEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ShulkerEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/SpellcasterIllagerEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/player/AvatarEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java
#	core/src/main/java/org/geysermc/geyser/level/physics/CollisionManager.java
#	core/src/main/java/org/geysermc/geyser/session/cache/EntityCache.java
#	core/src/main/java/org/geysermc/geyser/session/cache/FormCache.java
#	core/src/main/java/org/geysermc/geyser/session/cache/SkullCache.java
#	core/src/main/java/org/geysermc/geyser/session/cache/WorldBorder.java
#	core/src/main/java/org/geysermc/geyser/translator/inventory/MerchantInventoryTranslator.java
#	core/src/main/java/org/geysermc/geyser/translator/level/block/entity/VaultBlockEntityTranslator.java
#	core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/input/BedrockMovePlayer.java
#	core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaAddEntityTranslator.java
#	core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaEntityEventTranslator.java
#	core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerInfoUpdateTranslator.java
#	core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerPositionTranslator.java
#	core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaGameEventTranslator.java
#	core/src/test/java/org/geysermc/geyser/scoreboard/network/util/GeyserMockContextScoreboard.java
Copilot AI review requested due to automatic review settings January 12, 2026 00:52
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 133 out of 135 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

core/src/main/java/org/geysermc/geyser/entity/type/Entity.java:105

  • This method overrides GeyserEntity.uuid; it is advisable to add an Override annotation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

return NbtMap.builder().putList("Hitboxes", NbtType.COMPOUND, list).build();
}

public static class Builder implements Hitbox.Builder {
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Builder has the same name as its supertype org.geysermc.geyser.api.entity.data.types.Hitbox$Builder.

Copilot uses AI. Check for mistakes.
…tities-api

# Conflicts:
#	core/src/main/java/org/geysermc/geyser/entity/VanillaEntities.java
#	core/src/main/java/org/geysermc/geyser/entity/type/DisplayBaseEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/MinecartEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/TextDisplayEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ShulkerEntity.java
#	core/src/main/java/org/geysermc/geyser/entity/type/player/AvatarEntity.java
#	core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java
Copilot AI review requested due to automatic review settings January 26, 2026 21:07
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 133 out of 134 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 419 to 435
@Override
public void moveAbsolute(Vector3f position, float yaw, float pitch, float headYaw, boolean isOnGround, boolean teleported) {
public void moveAbsolute(Vector3f javaPosition, float yaw, float pitch, float headYaw, boolean isOnGround, boolean teleported) {
// It's vanilla behaviour to lerp if the position is within 64 blocks, however we also check if the position is close enough to the player
// position to see if it can actually affect anything to save network.
if (shouldLerp() && position.distanceSquared(this.position) < 4096 && position.distanceSquared(session.getPlayerEntity().position()) < 4096) {
if (shouldLerp() && javaPosition.distanceSquared(javaPosition) < 4096 && javaPosition.distanceSquared(session.getPlayerEntity().position()) < 4096) {
this.dirtyPitch = this.dirtyYaw = this.dirtyHeadYaw = true;

setYaw(yaw);
setPitch(pitch);
setHeadYaw(headYaw);
setOnGround(isOnGround);

this.lerpPosition = position;
this.lerpPosition = javaPosition;
this.lerpSteps = 3;
} else {
super.moveAbsolute(position, yaw, pitch, headYaw, isOnGround, teleported);
super.moveAbsolute(javaPosition, yaw, pitch, headYaw, isOnGround, teleported);
}
Copy link

Copilot AI Jan 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In moveAbsolute, the distance check for deciding whether to lerp is incorrect: javaPosition.distanceSquared(javaPosition) always returns 0, so the first half of the condition is effectively always true. This both defeats the intended 64-block range guard and can lead to unnecessary interpolation behavior; the comparison should be against the entity’s current position (e.g., javaPosition.distanceSquared(position())).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

API The issue/feature request relates to the Geyser API PR: Feature When a PR implements a new feature PR: Needs Testing When a PR needs testing but is currently not under review Work in Progress The issue is currently being worked on.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants