Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
5a7bf1b
Start working on custom entity API (for real this time)
eclipseisoffline Oct 24, 2025
f4156c6
Split EntityDefinition up into EntityDefinition and VanillaEntityDefi…
eclipseisoffline Oct 24, 2025
0b8678e
Allow creating custom entity types from API
eclipseisoffline Oct 24, 2025
d843745
Further refactor EntityDefinition, create a Base class
eclipseisoffline Oct 25, 2025
7fe8992
Work on exposing custom entity definitions in the API
eclipseisoffline Oct 27, 2025
e398c54
Add EntityDefinition#is
eclipseisoffline Oct 27, 2025
a3869cf
Implement CustomEntityDefinition, part one
eclipseisoffline Oct 27, 2025
11e6b50
Move CustomEntityDefinition into custom package
onebeastchris Nov 10, 2025
6fab587
CustomEntityDefinition should extend GeyserEntityDefinition
onebeastchris Nov 17, 2025
3392510
Separate BedrockEntityDefinition from Entity classes
onebeastchris Nov 17, 2025
c57f250
EntityDefinition -> EntityTypeDefinition
onebeastchris Nov 22, 2025
142cbae
Continue splitting bedrock entities from java types
onebeastchris Nov 23, 2025
8ff763b
Width, height and offset should be tied to the Java entity type; and …
onebeastchris Nov 25, 2025
b2739e1
More work on events, closer to working
onebeastchris Nov 26, 2025
52b76f5
Fix startup
onebeastchris Nov 26, 2025
8f8e3be
Expose geyserId in API, add SessionAttachParrotsEvent
onebeastchris Nov 27, 2025
9e6b133
Rename SessionAttachParrotsEvent -> ServerAttachParrotsEvent, fill in…
onebeastchris Nov 27, 2025
75d5f07
Apply some suggestions
onebeastchris Nov 27, 2025
5a16517
Another couple changes, start designing an entity data system to set …
onebeastchris Nov 27, 2025
460305a
Api design goes brrr
onebeastchris Nov 30, 2025
b26b9d1
Implement dirty entities to send updates once a tick
onebeastchris Nov 30, 2025
37f1285
Fix NPE in test
onebeastchris Nov 30, 2025
a648650
Attempt to add feature branch publishing
onebeastchris Nov 30, 2025
a497d3d
API polishing; properly initialize height/width
onebeastchris Nov 30, 2025
a3b3c72
Refactor: unify offset handling, always store Java entity position
onebeastchris Dec 1, 2025
f3070f7
Remove unused offsets
onebeastchris Dec 1, 2025
8a79001
Remove debug print, validate that entity definitions have been regist…
onebeastchris Dec 1, 2025
d4f0713
Set up feature branch publishing and vertical offset applying
onebeastchris Dec 1, 2025
899bd29
correct javadoc
onebeastchris Dec 1, 2025
a55e7b8
Merge branch 'master' into feature/custom-entities-api
onebeastchris Dec 4, 2025
8509bf1
Merge branch 'master' into feature/custom-entities-api
onebeastchris Dec 9, 2025
7efcda1
Merge remote-tracking branch 'upstream/feature/custom-entities-api' i…
onebeastchris Dec 10, 2025
b1c1c42
Merge remote-tracking branch 'upstream/master' into this-is-the-entit…
onebeastchris Dec 10, 2025
d5bdb7f
Merge branch 'master' into feature/custom-entities-api
onebeastchris Dec 10, 2025
a1d4f3e
Change entity definition log level to debug for missing definitions (…
QuickGlare Dec 12, 2025
494420e
Fix villager inventories not showing up
onebeastchris Dec 13, 2025
ec23593
Fix interaction range check
onebeastchris Dec 16, 2025
9f05f1e
Merge remote-tracking branch 'upstream/master' into feature/custom-en…
onebeastchris Dec 16, 2025
199737d
Expose entity hitboxes in API, store bedrock position to avoid re-cal…
onebeastchris Dec 16, 2025
2916f3f
Minor cleanup
onebeastchris Dec 17, 2025
adf4063
Log unknown implementations of GeyserEntityDefinition
onebeastchris Dec 19, 2025
927b72f
Use position setter instead of directly setting entity position
onebeastchris Dec 21, 2025
9aefb36
Fix client crashing related to sending & unlocking smithing recipes
onebeastchris Dec 22, 2025
ac29b54
Merge in upstream, we are on 1.21.11 now
onebeastchris Dec 24, 2025
a2003d1
Merge remote-tracking branch 'upstream/master' into feature/custom-en…
onebeastchris Jan 10, 2026
7ef5998
Merge upstream
onebeastchris Jan 10, 2026
053a505
Merge remote-tracking branch 'upstream/master' into feature/custom-en…
onebeastchris Jan 11, 2026
ea8d896
Fix hitbox querying, fix offset handling for boats
onebeastchris Jan 12, 2026
a52405c
Fix entity lerping
onebeastchris Jan 12, 2026
6f31e26
Merge remote-tracking branch 'upstream/master' into feature/custom-en…
onebeastchris Jan 25, 2026
9bb0d31
Merge remote-tracking branch 'upstream/master' into feature/custom-en…
onebeastchris Jan 26, 2026
af9a456
Merge remote-tracking branch 'upstream/master' into feature/custom-en…
onebeastchris Jan 26, 2026
c0cac81
Remove bedrockPosition variable again, simpler to only store one sour…
onebeastchris Jan 26, 2026
3e6fdbc
Merge remote-tracking branch 'upstream/master' into feature/custom-en…
onebeastchris Feb 2, 2026
cdd11e7
Address issues
onebeastchris Feb 2, 2026
25ddf22
Merge remote-tracking branch 'upstream/master' into feature/custom-en…
onebeastchris Feb 5, 2026
241cb4c
Bump mcpl
onebeastchris Feb 5, 2026
513a921
Merge branch 'master' into feature/custom-entities-api
onebeastchris Feb 5, 2026
03b3463
Merge remote-tracking branch 'upstream/master' into feature/custom-en…
onebeastchris Feb 7, 2026
8d39a39
make it build again
onebeastchris Feb 7, 2026
906dd28
Merge remote-tracking branch 'upstream/master' into feature/custom-en…
onebeastchris Feb 9, 2026
d792f0e
Partially address review
onebeastchris Feb 9, 2026
91a4c19
Merge remote-tracking branch 'upstream/master' into feature/custom-en…
onebeastchris Feb 10, 2026
b964780
fix le test
onebeastchris Feb 11, 2026
5b9d645
Merge branch 'master' into feature/custom-entities-api
onebeastchris Feb 16, 2026
beb2498
Fix: ResourcePackClientResponsePacket's may contain empty pack lists …
onebeastchris Feb 28, 2026
7d1a16a
Fix debug log formatting calls
onebeastchris Feb 28, 2026
45d98e8
Merge remote-tracking branch 'upstream/master' into feature/custom-en…
onebeastchris Feb 28, 2026
bddacf7
Minor fixes, reviews, etc
onebeastchris Feb 28, 2026
c35cd1d
Support setting empty hitbox
onebeastchris Mar 4, 2026
05c8c39
Merge branch 'master' into feature/custom-entities-api
onebeastchris Mar 6, 2026
43a3fef
Merge remote-tracking branch 'upstream/master' into feature/custom-en…
onebeastchris Mar 14, 2026
0f9ad38
Reviews and comments
onebeastchris Mar 14, 2026
d9e0c6b
Improve height / width handling
onebeastchris Mar 15, 2026
a21d9e8
Allow custom height / width to be 0
onebeastchris Mar 15, 2026
61fbc7a
Merge remote-tracking branch 'upstream/master' into feature/custom-en…
onebeastchris Mar 20, 2026
93ddfc7
Merge remote-tracking branch 'upstream/master' into feature/custom-en…
onebeastchris Mar 20, 2026
34b1d98
Likely fix entity registration
onebeastchris Mar 20, 2026
ee0a40a
Merge branch 'master' into feature/custom-entities-api
onebeastchris Mar 26, 2026
e634ed6
Merge remote-tracking branch 'upstream/master' into feature/custom-en…
onebeastchris Mar 28, 2026
ee610d3
Merge remote-tracking branch 'upstream/feature/custom-entities-api' i…
onebeastchris Mar 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,19 @@

package org.geysermc.geyser.api.connection;

import org.checkerframework.checker.index.qual.NonNegative;
import org.checkerframework.checker.index.qual.Positive;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.api.connection.Connection;
import org.geysermc.geyser.api.bedrock.camera.CameraData;
import org.geysermc.geyser.api.bedrock.camera.CameraShake;
import org.geysermc.geyser.api.command.CommandSource;
import org.geysermc.geyser.api.entity.EntityData;
import org.geysermc.geyser.api.entity.type.GeyserEntity;
import org.geysermc.geyser.api.entity.type.player.GeyserPlayerEntity;
import org.geysermc.geyser.api.skin.SkinData;

import java.util.NoSuchElementException;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;

/**
* Represents a player connection used in Geyser.
Expand All @@ -58,7 +54,7 @@ public interface GeyserConnection extends Connection, CommandSource {

/**
* Exposes the {@link EntityData} for this connection.
* It allows you to get entities by their Java entity ID, show emotes, and get the player entity.
* It allows you to look up other entities through various methods.
*
* @return the EntityData for this connection.
*/
Expand Down Expand Up @@ -166,15 +162,6 @@ public interface GeyserConnection extends Connection, CommandSource {
*/
void sendSkin(@NonNull UUID player, @NonNull SkinData skinData);

/**
* @param javaId the Java entity ID to look up.
* @return a {@link GeyserEntity} if present in this connection's entity tracker.
* @deprecated Use {@link EntityData#entityByJavaId(int)} instead
*/
@Deprecated
@NonNull
CompletableFuture<@Nullable GeyserEntity> entityByJavaId(@NonNegative int javaId);

/**
* Displays a player entity as emoting to this client.
*
Expand Down
18 changes: 17 additions & 1 deletion api/src/main/java/org/geysermc/geyser/api/entity/EntityData.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,29 @@
*/
public interface EntityData {

/**
* @deprecated use {@link #byJavaId(int)}
*/
@Deprecated
@NonNull CompletableFuture<@Nullable GeyserEntity> entityByJavaId(@NonNegative int javaId);

/**
* Returns a {@link GeyserEntity} to e.g. make them play an emote.
*
* @param javaId the Java entity ID to look up
* @return a {@link GeyserEntity} if present in this connection's entity tracker
*/
@NonNull CompletableFuture<@Nullable GeyserEntity> entityByJavaId(@NonNegative int javaId);
@Nullable GeyserEntity byJavaId(@NonNegative int javaId);

/**
* Returns a {@link GeyserEntity} to e.g. update entity properties.
*/
@Nullable GeyserEntity byUuid(@NonNull UUID javaUuid);

/**
* Returns a {@link GeyserEntity} based on a Geyser entity id
*/
@Nullable GeyserEntity byGeyserId(@NonNegative long geyserId);

/**
* (Un)locks the client's movement inputs, so that they cannot move.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright (c) 2025 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/

package org.geysermc.geyser.api.entity.custom;

import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.api.GeyserApi;
import org.geysermc.geyser.api.entity.definition.GeyserEntityDefinition;
import org.geysermc.geyser.api.util.Identifier;

/**
* Represents a custom entity definition for a non-vanilla, custom Bedrock entity.
*/
public interface CustomEntityDefinition extends GeyserEntityDefinition {

@Override
default boolean vanilla() {
return false;
}

/**
* Creates or retrieves a GeyserEntityDefinition by the Bedrock entity type identifier.
*
* @param identifier the Bedrock entity identifier
* @return the CustomEntityDefinition
*/
static @NonNull CustomEntityDefinition of(@NonNull Identifier identifier) {
if (identifier.vanilla()) {
throw new IllegalArgumentException("Use GeyserEntityDefinition#of for vanilla entity lookups!");
}
return GeyserApi.api().provider(CustomEntityDefinition.class, identifier);
}

/**
* Creates or retrieves a GeyserEntityDefinition by the Bedrock entity type identifier.
*
* @param identifier the Bedrock entity identifier, in string format
* @return the CustomEntityDefinition
*/
static @NonNull CustomEntityDefinition of(@NonNull String identifier) {
return of(Identifier.of(identifier));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* Copyright (c) 2025 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/

package org.geysermc.geyser.api.entity.custom;

import org.checkerframework.checker.index.qual.NonNegative;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.api.entity.definition.GeyserEntityDefinition;
import org.geysermc.geyser.api.entity.definition.JavaEntityType;
import org.geysermc.geyser.api.event.lifecycle.GeyserDefineEntitiesEvent;
import org.geysermc.geyser.api.util.Identifier;

/**
* Represents a custom Minecraft: Java Edition entity type.
* This can only be used with modded servers!
*/
public interface CustomJavaEntityType extends JavaEntityType {

@Override
default boolean vanilla() {
return false;
}

interface Builder {

/**
* The entity type's identifier. It cannot be in the Minecraft namespace
* for custom entities!
*
* @param entityType the identifier
* @return this builder
*/
Builder type(Identifier entityType);

/**
* The entity type's numeric network id.
* @param javaId the java id
* @return this builder
*/
Builder javaId(int javaId);

/**
* The width of this entity.
* @param width the width of this entity
* @return this builder
*/
Builder width(@NonNegative float width);

/**
* The height of this entity
* @param height the height
* @return this builder
*/
Builder height(@NonNegative float height);

/**
* The default Bedrock edition entity definition.
* You can define custom Bedrock entities, or use vanilla definitions
* obtainable via the {@link GeyserDefineEntitiesEvent#entities()} collection.
* This entity has to be registered before calling this method!
*
* @param defaultBedrockDefinition the default Bedrock definition
* @return this builder
*/
Builder definition(@Nullable GeyserEntityDefinition defaultBedrockDefinition);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright (c) 2025 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/

package org.geysermc.geyser.api.entity.data;

import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.api.GeyserApi;
import org.geysermc.geyser.api.entity.type.GeyserEntity;

/**
* Represents a type of entity data that can be sent for an entity.
* <p>
* Entity data types define the kind of value stored for a particular piece of metadata,
* such as a {@code Byte}, {@code Integer}, {@code Float}; and the name associated with them.
* <p>
* Unlike custom items or blocks, it is possible to update entity metadata at runtime,
* which can be done using {@link GeyserEntity#update(GeyserEntityDataType, Object)}.
*
* @param <T> the value type associated with this entity data type
*/
public interface GeyserEntityDataType<T> {

/**
* Gets the Java class representing the value type associated with this data type.
*
* @return the class of the value used by this entity data type
*/
@NonNull Class<T> typeClass();

/**
* Gets the unique name of this data type.
* <p>
* The name is used internally to identify and register the data type so it can be
* referenced when reading or writing entity metadata.
*
* @return the name of this entity data type
*/
@NonNull String name();

/**
* For API usage only; use the types defined in {@link GeyserEntityDataTypes}
*/
static <T> GeyserEntityDataType<T> of(@NonNull Class<T> typeClass, @NonNull String name) {
return GeyserApi.api().provider(GeyserEntityDataType.class, typeClass, name);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright (c) 2025 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/

package org.geysermc.geyser.api.entity.data;

import org.geysermc.geyser.api.entity.data.types.Hitbox;

/**
* Contains commonly used {@link GeyserEntityDataType} constants for built-in entity
* metadata fields.
* <p>
* These data types define the structure of certain primitive or numeric metadata
* values that can be used for Bedrock entities. Each constant is backed by a
* pre-registered entity data type that can be used when reading or writing metadata
* through the Geyser API.
*/
public final class GeyserEntityDataTypes {

/**
* Represents a single-byte value used for color types
* (e.g., sheep wool color).
*/
public static final GeyserEntityDataType<Byte> COLOR =
GeyserEntityDataType.of(Byte.class, "color");

/**
* Represents a numeric variant index that can be queried in resource packs.
*/
public static final GeyserEntityDataType<Integer> VARIANT =
GeyserEntityDataType.of(Integer.class, "variant");

/**
* Represents the entity's width.
*/
public static final GeyserEntityDataType<Float> WIDTH =
GeyserEntityDataType.of(Float.class, "width");

/**
* Represents the entity's height.
*/
public static final GeyserEntityDataType<Float> HEIGHT =
GeyserEntityDataType.of(Float.class, "height");

/**
* Represents the entity's vertical offset.
*/
public static final GeyserEntityDataType<Float> VERTICAL_OFFSET =
GeyserEntityDataType.of(Float.class, "vertical_offset");

/**
* Represents the scale multiplier.
*/
public static final GeyserEntityDataType<Float> SCALE =
GeyserEntityDataType.of(Float.class, "scale");

/**
* Represents custom hitboxes for entities
*/
public static final GeyserListEntityDataType<Hitbox> HITBOXES =
GeyserListEntityDataType.of(Hitbox.class, "hitboxes");

private GeyserEntityDataTypes() {
// no-op
}
}
Loading
Loading