mirror of
https://github.com/GeyserMC/Geyser.git
synced 2026-01-06 15:41:50 +00:00
Work on exposing custom entity definitions in the API
This commit is contained in:
@@ -55,15 +55,13 @@ import java.util.function.BiConsumer;
|
||||
@ToString(callSuper = true)
|
||||
public abstract class EntityDefinition<T extends Entity> extends EntityDefinitionBase<T> {
|
||||
private final EntityFactory<T> factory;
|
||||
private final GeyserEntityType entityType;
|
||||
private final String bedrockIdentifier;
|
||||
private final GeyserEntityProperties registeredProperties;
|
||||
|
||||
public EntityDefinition(EntityFactory<T> factory, GeyserEntityType entityType, String bedrockIdentifier,
|
||||
public EntityDefinition(EntityFactory<T> factory, String bedrockIdentifier,
|
||||
float width, float height, float offset, GeyserEntityProperties registeredProperties, List<EntityMetadataTranslator<? super T, ?, ?>> translators) {
|
||||
super(width, height, offset, translators);
|
||||
this.factory = factory;
|
||||
this.entityType = entityType;
|
||||
this.bedrockIdentifier = bedrockIdentifier;
|
||||
this.registeredProperties = registeredProperties;
|
||||
}
|
||||
@@ -72,8 +70,6 @@ public abstract class EntityDefinition<T extends Entity> extends EntityDefinitio
|
||||
@Accessors(fluent = true, chain = true)
|
||||
public static abstract class Builder<T extends Entity> extends EntityDefinitionBase.Builder<T> {
|
||||
protected final EntityFactory<T> factory;
|
||||
@Setter(AccessLevel.NONE)
|
||||
protected GeyserEntityType type;
|
||||
protected String bedrockIdentifier;
|
||||
@Setter(AccessLevel.NONE)
|
||||
protected GeyserEntityProperties.Builder propertiesBuilder;
|
||||
@@ -91,15 +87,6 @@ public abstract class EntityDefinition<T extends Entity> extends EntityDefinitio
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the bedrock identifier as well
|
||||
*/
|
||||
public Builder<T> type(GeyserEntityType type) {
|
||||
this.type = type;
|
||||
this.bedrockIdentifier = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<T> width(float width) {
|
||||
return (Builder<T>) super.width(width);
|
||||
@@ -137,13 +124,5 @@ public abstract class EntityDefinition<T extends Entity> extends EntityDefinitio
|
||||
propertiesBuilder.add(propertyType);
|
||||
return this;
|
||||
}
|
||||
|
||||
protected void validateTypeAndIdentifier() {
|
||||
if (type == null) {
|
||||
throw new IllegalStateException("Missing entity type!");
|
||||
} else if (bedrockIdentifier == null) {
|
||||
bedrockIdentifier = type.javaIdentifier().toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,9 @@ public class EntityDefinitionBase<T extends Entity> {
|
||||
return new Builder<>(clazz);
|
||||
}
|
||||
|
||||
public static <T extends Entity> Builder<T> baseInherited(EntityDefinitionBase<? super T> parent) {
|
||||
// Unused param so Java knows what entity we're talking about
|
||||
@SuppressWarnings("unused")
|
||||
public static <T extends Entity> Builder<T> baseInherited(Class<T> clazz, EntityDefinitionBase<? super T> parent) {
|
||||
return new Builder<>(parent.width(), parent.height(), parent.offset(), new ObjectArrayList<>(parent.translators()));
|
||||
}
|
||||
|
||||
@@ -97,7 +99,8 @@ public class EntityDefinitionBase<T extends Entity> {
|
||||
}
|
||||
|
||||
// Unused param so Java knows what entity we're talking about
|
||||
protected Builder(@SuppressWarnings("unused") Class<T> clazz) {
|
||||
@SuppressWarnings("unused")
|
||||
protected Builder(Class<T> clazz) {
|
||||
this();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* 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.entity;
|
||||
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
|
||||
import org.geysermc.geyser.entity.type.BoatEntity;
|
||||
import org.geysermc.geyser.entity.type.ChestBoatEntity;
|
||||
import org.geysermc.geyser.entity.type.DisplayBaseEntity;
|
||||
import org.geysermc.geyser.entity.type.Entity;
|
||||
import org.geysermc.geyser.entity.type.FireballEntity;
|
||||
import org.geysermc.geyser.entity.type.HangingEntity;
|
||||
import org.geysermc.geyser.entity.type.LivingEntity;
|
||||
import org.geysermc.geyser.entity.type.ThrowableItemEntity;
|
||||
import org.geysermc.geyser.entity.type.living.AbstractFishEntity;
|
||||
import org.geysermc.geyser.entity.type.living.AgeableEntity;
|
||||
import org.geysermc.geyser.entity.type.living.MobEntity;
|
||||
import org.geysermc.geyser.entity.type.living.animal.horse.AbstractHorseEntity;
|
||||
import org.geysermc.geyser.entity.type.living.animal.tameable.TameableEntity;
|
||||
import org.geysermc.geyser.entity.type.living.monster.BasePiglinEntity;
|
||||
import org.geysermc.geyser.entity.type.living.monster.raid.RaidParticipantEntity;
|
||||
import org.geysermc.geyser.entity.type.living.monster.raid.SpellcasterIllagerEntity;
|
||||
import org.geysermc.geyser.entity.type.player.AvatarEntity;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.MetadataTypes;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.FloatEntityMetadata;
|
||||
|
||||
public final class EntityDefinitionBases {
|
||||
public static final EntityDefinitionBase<Entity> ENTITY;
|
||||
public static final EntityDefinitionBase<DisplayBaseEntity> DISPLAY;
|
||||
public static final EntityDefinitionBase<FireballEntity> FIREBALL;
|
||||
public static final EntityDefinitionBase<ThrowableItemEntity> THROWABLE;
|
||||
public static final EntityDefinitionBase<HangingEntity> HANGING;
|
||||
public static final EntityDefinitionBase<BoatEntity> BOAT;
|
||||
public static final EntityDefinitionBase<ChestBoatEntity> CHEST_BOAT;
|
||||
public static final EntityDefinitionBase<LivingEntity> LIVING_ENTITY;
|
||||
public static final EntityDefinitionBase<AvatarEntity> AVATAR;
|
||||
public static final EntityDefinitionBase<MobEntity> MOB;
|
||||
public static final EntityDefinitionBase<AbstractFishEntity> FISH;
|
||||
public static final EntityDefinitionBase<BasePiglinEntity> PIGLIN;
|
||||
public static final EntityDefinitionBase<RaidParticipantEntity> RAID_PARTICIPANT;
|
||||
public static final EntityDefinitionBase<SpellcasterIllagerEntity> SPELLCASTER;
|
||||
public static final EntityDefinitionBase<AgeableEntity> AGEABLE;
|
||||
public static final EntityDefinitionBase<AbstractHorseEntity> HORSE;
|
||||
public static final EntityDefinitionBase<TameableEntity> TAMABLE;
|
||||
|
||||
static {
|
||||
ENTITY = EntityDefinition.baseBuilder(Entity.class)
|
||||
.addTranslator(MetadataTypes.BYTE, Entity::setFlags)
|
||||
.addTranslator(MetadataTypes.INT, Entity::setAir) // Air/bubbles
|
||||
.addTranslator(MetadataTypes.OPTIONAL_COMPONENT, Entity::setDisplayName)
|
||||
.addTranslator(MetadataTypes.BOOLEAN, Entity::setDisplayNameVisible)
|
||||
.addTranslator(MetadataTypes.BOOLEAN, Entity::setSilent)
|
||||
.addTranslator(MetadataTypes.BOOLEAN, Entity::setGravity)
|
||||
.addTranslator(MetadataTypes.POSE, (entity, entityMetadata) -> entity.setPose(entityMetadata.getValue()))
|
||||
.addTranslator(MetadataTypes.INT, Entity::setFreezing)
|
||||
.build();
|
||||
DISPLAY = EntityDefinitionBase.baseInherited(DisplayBaseEntity.class, ENTITY)
|
||||
.addTranslator(null) // Interpolation delay
|
||||
.addTranslator(null) // Transformation interpolation duration
|
||||
.addTranslator(null) // Position/Rotation interpolation duration
|
||||
.addTranslator(MetadataTypes.VECTOR3, DisplayBaseEntity::setTranslation) // Translation
|
||||
.addTranslator(null) // Scale
|
||||
.addTranslator(null) // Left rotation
|
||||
.addTranslator(null) // Right rotation
|
||||
.addTranslator(null) // Billboard render constraints
|
||||
.addTranslator(null) // Brightness override
|
||||
.addTranslator(null) // View range
|
||||
.addTranslator(null) // Shadow radius
|
||||
.addTranslator(null) // Shadow strength
|
||||
.addTranslator(null) // Width
|
||||
.addTranslator(null) // Height
|
||||
.addTranslator(null) // Glow color override
|
||||
.build();
|
||||
FIREBALL = EntityDefinitionBase.baseInherited(FireballEntity.class, ENTITY)
|
||||
.addTranslator(null) // Item
|
||||
.build();
|
||||
THROWABLE = EntityDefinitionBase.baseInherited(ThrowableItemEntity.class, ENTITY)
|
||||
.addTranslator(MetadataTypes.ITEM_STACK, ThrowableItemEntity::setItem)
|
||||
.build();
|
||||
HANGING = EntityDefinitionBase.baseInherited(HangingEntity.class, ENTITY)
|
||||
.addTranslator(MetadataTypes.DIRECTION, HangingEntity::setDirectionMetadata)
|
||||
.build();
|
||||
BOAT = EntityDefinitionBase.baseInherited(BoatEntity.class, ENTITY)
|
||||
.height(0.6f).width(1.6f)
|
||||
.offset(0.35f)
|
||||
.addTranslator(MetadataTypes.INT, (boatEntity, entityMetadata) -> boatEntity.getDirtyMetadata().put(EntityDataTypes.HURT_TICKS, entityMetadata.getValue())) // Time since last hit
|
||||
.addTranslator(MetadataTypes.INT, (boatEntity, entityMetadata) -> boatEntity.getDirtyMetadata().put(EntityDataTypes.HURT_DIRECTION, entityMetadata.getValue())) // Rocking direction
|
||||
.addTranslator(MetadataTypes.FLOAT, (boatEntity, entityMetadata) ->
|
||||
// 'Health' in Bedrock, damage taken in Java - it makes motion in Bedrock
|
||||
boatEntity.getDirtyMetadata().put(EntityDataTypes.STRUCTURAL_INTEGRITY, 40 - ((int) ((FloatEntityMetadata) entityMetadata).getPrimitiveValue())))
|
||||
.addTranslator(MetadataTypes.BOOLEAN, BoatEntity::setPaddlingLeft)
|
||||
.addTranslator(MetadataTypes.BOOLEAN, BoatEntity::setPaddlingRight)
|
||||
.addTranslator(MetadataTypes.INT, (boatEntity, entityMetadata) -> boatEntity.getDirtyMetadata().put(EntityDataTypes.BOAT_BUBBLE_TIME, entityMetadata.getValue())) // May not actually do anything
|
||||
.build();
|
||||
CHEST_BOAT = EntityDefinitionBase.baseInherited(ChestBoatEntity.class, BOAT)
|
||||
.build();
|
||||
LIVING_ENTITY = EntityDefinitionBase.baseInherited(LivingEntity.class, ENTITY)
|
||||
.addTranslator(MetadataTypes.BYTE, LivingEntity::setLivingEntityFlags)
|
||||
.addTranslator(MetadataTypes.FLOAT, LivingEntity::setHealth)
|
||||
.addTranslator(MetadataTypes.PARTICLES, LivingEntity::setParticles)
|
||||
.addTranslator(MetadataTypes.BOOLEAN,
|
||||
(livingEntity, entityMetadata) -> livingEntity.getDirtyMetadata().put(EntityDataTypes.EFFECT_AMBIENCE, (byte) (((BooleanEntityMetadata) entityMetadata).getPrimitiveValue() ? 1 : 0)))
|
||||
.addTranslator(null) // Arrow count
|
||||
.addTranslator(null) // Stinger count
|
||||
.addTranslator(MetadataTypes.OPTIONAL_BLOCK_POS, LivingEntity::setBedPosition)
|
||||
.build();
|
||||
AVATAR = EntityDefinitionBase.baseInherited(AvatarEntity.class, LIVING_ENTITY)
|
||||
.height(1.8f).width(0.6f)
|
||||
.offset(1.62f)
|
||||
.addTranslator(null) // Player main hand
|
||||
.addTranslator(MetadataTypes.BYTE, AvatarEntity::setSkinVisibility)
|
||||
.build();
|
||||
MOB = EntityDefinitionBase.baseInherited(MobEntity.class, LIVING_ENTITY)
|
||||
.addTranslator(MetadataTypes.BYTE, MobEntity::setMobFlags)
|
||||
.build();
|
||||
FISH = EntityDefinitionBase.baseInherited(AbstractFishEntity.class, MOB)
|
||||
.addTranslator(null) // From bucket
|
||||
.build();
|
||||
PIGLIN = EntityDefinitionBase.baseInherited(BasePiglinEntity.class, MOB)
|
||||
.addTranslator(MetadataTypes.BOOLEAN, BasePiglinEntity::setImmuneToZombification)
|
||||
.build();
|
||||
RAID_PARTICIPANT = EntityDefinitionBase.baseInherited(RaidParticipantEntity.class, MOB)
|
||||
.addTranslator(null) // Celebrating //TODO
|
||||
.build();
|
||||
SPELLCASTER = EntityDefinitionBase.baseInherited(SpellcasterIllagerEntity.class, RAID_PARTICIPANT)
|
||||
.addTranslator(MetadataTypes.BYTE, SpellcasterIllagerEntity::setSpellType)
|
||||
.build();
|
||||
AGEABLE = EntityDefinitionBase.baseInherited(AgeableEntity.class, MOB)
|
||||
.addTranslator(MetadataTypes.BOOLEAN, AgeableEntity::setBaby)
|
||||
.build();
|
||||
HORSE = EntityDefinitionBase.baseInherited(AbstractHorseEntity.class, AGEABLE)
|
||||
.addTranslator(MetadataTypes.BYTE, AbstractHorseEntity::setHorseFlags)
|
||||
.build();
|
||||
TAMABLE = EntityDefinitionBase.baseInherited(TameableEntity.class, AGEABLE)
|
||||
.addTranslator(MetadataTypes.BYTE, TameableEntity::setTameableFlags)
|
||||
.addTranslator(MetadataTypes.OPTIONAL_LIVING_ENTITY_REFERENCE, TameableEntity::setOwner)
|
||||
.build();
|
||||
}
|
||||
|
||||
private EntityDefinitionBases() {
|
||||
}
|
||||
}
|
||||
@@ -337,7 +337,7 @@ public final class EntityDefinitions {
|
||||
public static final VanillaEntityDefinition<WitherSkullEntity> WITHER_SKULL_DANGEROUS;
|
||||
|
||||
static {
|
||||
EntityDefinition<Entity> entityBase = VanillaEntityDefinition.builder(Entity::new)
|
||||
EntityDefinitionBase<Entity> entityBase = EntityDefinition.baseBuilder(Entity.class)
|
||||
.addTranslator(MetadataTypes.BYTE, Entity::setFlags)
|
||||
.addTranslator(MetadataTypes.INT, Entity::setAir) // Air/bubbles
|
||||
.addTranslator(MetadataTypes.OPTIONAL_COMPONENT, Entity::setDisplayName)
|
||||
@@ -432,7 +432,7 @@ public final class EntityDefinitions {
|
||||
.addTranslator(MetadataTypes.INT, TNTEntity::setFuseLength)
|
||||
.build();
|
||||
|
||||
VanillaEntityDefinition<DisplayBaseEntity> displayBase = VanillaEntityDefinition.inherited(DisplayBaseEntity::new, entityBase)
|
||||
EntityDefinitionBase<DisplayBaseEntity> displayBase = EntityDefinitionBase.baseInherited(DisplayBaseEntity.class, entityBase)
|
||||
.addTranslator(null) // Interpolation delay
|
||||
.addTranslator(null) // Transformation interpolation duration
|
||||
.addTranslator(null) // Position/Rotation interpolation duration
|
||||
@@ -469,7 +469,7 @@ public final class EntityDefinitions {
|
||||
.addTranslator(MetadataTypes.BOOLEAN, InteractionEntity::setResponse)
|
||||
.build();
|
||||
|
||||
VanillaEntityDefinition<FireballEntity> fireballBase = VanillaEntityDefinition.inherited(FireballEntity::new, entityBase)
|
||||
EntityDefinitionBase<FireballEntity> fireballBase = EntityDefinitionBase.baseInherited(FireballEntity.class, entityBase)
|
||||
.addTranslator(null) // Item
|
||||
.build();
|
||||
FIREBALL = VanillaEntityDefinition.inherited(FireballEntity::new, fireballBase)
|
||||
@@ -481,7 +481,7 @@ public final class EntityDefinitions {
|
||||
.heightAndWidth(0.3125f)
|
||||
.build();
|
||||
|
||||
VanillaEntityDefinition<ThrowableItemEntity> throwableItemBase = VanillaEntityDefinition.inherited(ThrowableItemEntity::new, entityBase)
|
||||
EntityDefinitionBase<ThrowableItemEntity> throwableItemBase = EntityDefinitionBase.baseInherited(ThrowableItemEntity.class, entityBase)
|
||||
.addTranslator(MetadataTypes.ITEM_STACK, ThrowableItemEntity::setItem)
|
||||
.build();
|
||||
EGG = VanillaEntityDefinition.inherited(ThrowableEggEntity::new, throwableItemBase)
|
||||
@@ -525,7 +525,7 @@ public final class EntityDefinitions {
|
||||
.heightAndWidth(0.3125f)
|
||||
.build();
|
||||
|
||||
VanillaEntityDefinition<AbstractArrowEntity> abstractArrowBase = VanillaEntityDefinition.inherited(AbstractArrowEntity::new, entityBase)
|
||||
EntityDefinitionBase<AbstractArrowEntity> abstractArrowBase = EntityDefinitionBase.baseInherited(AbstractArrowEntity.class, entityBase)
|
||||
.addTranslator(MetadataTypes.BYTE, AbstractArrowEntity::setArrowFlags)
|
||||
.addTranslator(null) // "Piercing level"
|
||||
.addTranslator(null) // If the arrow is in the ground
|
||||
@@ -535,7 +535,7 @@ public final class EntityDefinitions {
|
||||
.heightAndWidth(0.25f)
|
||||
.addTranslator(MetadataTypes.INT, ArrowEntity::setPotionEffectColor)
|
||||
.build();
|
||||
SPECTRAL_ARROW = VanillaEntityDefinition.inherited(abstractArrowBase.factory(), abstractArrowBase)
|
||||
SPECTRAL_ARROW = VanillaEntityDefinition.inherited(AbstractArrowEntity::new, abstractArrowBase)
|
||||
.type(BuiltinEntityType.SPECTRAL_ARROW)
|
||||
.heightAndWidth(0.25f)
|
||||
.bedrockIdentifier("minecraft:arrow")
|
||||
@@ -547,7 +547,7 @@ public final class EntityDefinitions {
|
||||
.addTranslator(MetadataTypes.BOOLEAN, (tridentEntity, entityMetadata) -> tridentEntity.setFlag(EntityFlag.ENCHANTED, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue()))
|
||||
.build();
|
||||
|
||||
VanillaEntityDefinition<HangingEntity> hangingEntityBase = VanillaEntityDefinition.<HangingEntity>inherited(null, entityBase)
|
||||
EntityDefinitionBase<HangingEntity> hangingEntityBase = EntityDefinitionBase.baseInherited(HangingEntity.class, entityBase)
|
||||
.addTranslator(MetadataTypes.DIRECTION, HangingEntity::setDirectionMetadata)
|
||||
.build();
|
||||
|
||||
@@ -613,7 +613,7 @@ public final class EntityDefinitions {
|
||||
|
||||
// Boats
|
||||
{
|
||||
VanillaEntityDefinition<BoatEntity> boatBase = VanillaEntityDefinition.<BoatEntity>inherited(null, entityBase)
|
||||
EntityDefinitionBase<BoatEntity> boatBase = EntityDefinitionBase.baseInherited(BoatEntity.class, entityBase)
|
||||
.height(0.6f).width(1.6f)
|
||||
.offset(0.35f)
|
||||
.addTranslator(MetadataTypes.INT, (boatEntity, entityMetadata) -> boatEntity.getDirtyMetadata().put(EntityDataTypes.HURT_TICKS, entityMetadata.getValue())) // Time since last hit
|
||||
@@ -637,7 +637,7 @@ public final class EntityDefinitions {
|
||||
SPRUCE_BOAT = buildBoat(boatBase, BuiltinEntityType.SPRUCE_BOAT, BoatEntity.BoatVariant.SPRUCE);
|
||||
PALE_OAK_BOAT = buildBoat(boatBase, BuiltinEntityType.PALE_OAK_BOAT, BoatEntity.BoatVariant.PALE_OAK);
|
||||
|
||||
VanillaEntityDefinition<ChestBoatEntity> chestBoatBase = VanillaEntityDefinition.<ChestBoatEntity>inherited(null, boatBase)
|
||||
EntityDefinitionBase<ChestBoatEntity> chestBoatBase = EntityDefinitionBase.baseInherited(ChestBoatEntity.class, boatBase)
|
||||
.build();
|
||||
|
||||
ACACIA_CHEST_BOAT = buildChestBoat(chestBoatBase, BuiltinEntityType.ACACIA_CHEST_BOAT, BoatEntity.BoatVariant.ACACIA);
|
||||
@@ -652,7 +652,7 @@ public final class EntityDefinitions {
|
||||
PALE_OAK_CHEST_BOAT = buildChestBoat(chestBoatBase, BuiltinEntityType.PALE_OAK_CHEST_BOAT, BoatEntity.BoatVariant.PALE_OAK);
|
||||
}
|
||||
|
||||
VanillaEntityDefinition<LivingEntity> livingEntityBase = VanillaEntityDefinition.inherited(LivingEntity::new, entityBase)
|
||||
EntityDefinitionBase<LivingEntity> livingEntityBase = EntityDefinitionBase.baseInherited(LivingEntity.class, entityBase)
|
||||
.addTranslator(MetadataTypes.BYTE, LivingEntity::setLivingEntityFlags)
|
||||
.addTranslator(MetadataTypes.FLOAT, LivingEntity::setHealth)
|
||||
.addTranslator(MetadataTypes.PARTICLES, LivingEntity::setParticles)
|
||||
@@ -675,7 +675,7 @@ public final class EntityDefinitions {
|
||||
.addTranslator(MetadataTypes.ROTATIONS, ArmorStandEntity::setRightLegRotation)
|
||||
.build();
|
||||
|
||||
VanillaEntityDefinition<AvatarEntity> avatarEntityBase = VanillaEntityDefinition.<AvatarEntity>inherited(null, livingEntityBase)
|
||||
EntityDefinitionBase<AvatarEntity> avatarEntityBase = EntityDefinitionBase.baseInherited(AvatarEntity.class, livingEntityBase)
|
||||
.height(1.8f).width(0.6f)
|
||||
.offset(1.62f)
|
||||
.addTranslator(null) // Player main hand
|
||||
@@ -697,7 +697,7 @@ public final class EntityDefinitions {
|
||||
.addTranslator(MetadataTypes.OPTIONAL_UNSIGNED_INT, PlayerEntity::setRightParrot)
|
||||
.build();
|
||||
|
||||
VanillaEntityDefinition<MobEntity> mobEntityBase = VanillaEntityDefinition.inherited(MobEntity::new, livingEntityBase)
|
||||
EntityDefinitionBase<MobEntity> mobEntityBase = EntityDefinitionBase.baseInherited(MobEntity.class, livingEntityBase)
|
||||
.addTranslator(MetadataTypes.BYTE, MobEntity::setMobFlags)
|
||||
.build();
|
||||
|
||||
@@ -907,10 +907,10 @@ public final class EntityDefinitions {
|
||||
.type(BuiltinEntityType.MAGMA_CUBE)
|
||||
.build();
|
||||
|
||||
VanillaEntityDefinition<AbstractFishEntity> abstractFishEntityBase = VanillaEntityDefinition.inherited(AbstractFishEntity::new, mobEntityBase)
|
||||
EntityDefinitionBase<AbstractFishEntity> abstractFishEntityBase = EntityDefinitionBase.baseInherited(AbstractFishEntity.class, mobEntityBase)
|
||||
.addTranslator(null) // From bucket
|
||||
.build();
|
||||
COD = VanillaEntityDefinition.inherited(abstractFishEntityBase.factory(), abstractFishEntityBase)
|
||||
COD = VanillaEntityDefinition.inherited(AbstractFishEntity::new, abstractFishEntityBase)
|
||||
.type(BuiltinEntityType.COD)
|
||||
.height(0.25f).width(0.5f)
|
||||
.build();
|
||||
@@ -919,7 +919,7 @@ public final class EntityDefinitions {
|
||||
.heightAndWidth(0.7f)
|
||||
.addTranslator(MetadataTypes.INT, PufferFishEntity::setPufferfishSize)
|
||||
.build();
|
||||
SALMON = VanillaEntityDefinition.inherited(abstractFishEntityBase.factory(), abstractFishEntityBase)
|
||||
SALMON = VanillaEntityDefinition.inherited(AbstractFishEntity::new, abstractFishEntityBase)
|
||||
.type(BuiltinEntityType.SALMON)
|
||||
.height(0.5f).width(0.7f)
|
||||
.addTranslator(null) // Scale/variant - TODO
|
||||
@@ -935,7 +935,7 @@ public final class EntityDefinitions {
|
||||
.addTranslator(MetadataTypes.INT, TropicalFishEntity::setFishVariant)
|
||||
.build();
|
||||
|
||||
VanillaEntityDefinition<BasePiglinEntity> abstractPiglinEntityBase = VanillaEntityDefinition.inherited(BasePiglinEntity::new, mobEntityBase)
|
||||
EntityDefinitionBase<BasePiglinEntity> abstractPiglinEntityBase = EntityDefinitionBase.baseInherited(BasePiglinEntity.class, mobEntityBase)
|
||||
.addTranslator(MetadataTypes.BOOLEAN, BasePiglinEntity::setImmuneToZombification)
|
||||
.build();
|
||||
PIGLIN = VanillaEntityDefinition.inherited(PiglinEntity::new, abstractPiglinEntityBase)
|
||||
@@ -945,23 +945,23 @@ public final class EntityDefinitions {
|
||||
.addTranslator(MetadataTypes.BOOLEAN, PiglinEntity::setChargingCrossbow)
|
||||
.addTranslator(MetadataTypes.BOOLEAN, PiglinEntity::setDancing)
|
||||
.build();
|
||||
PIGLIN_BRUTE = VanillaEntityDefinition.inherited(abstractPiglinEntityBase.factory(), abstractPiglinEntityBase)
|
||||
PIGLIN_BRUTE = VanillaEntityDefinition.inherited(BasePiglinEntity::new, abstractPiglinEntityBase)
|
||||
.type(BuiltinEntityType.PIGLIN_BRUTE)
|
||||
.height(1.95f).width(0.6f)
|
||||
.build();
|
||||
|
||||
VanillaEntityDefinition<RaidParticipantEntity> raidParticipantEntityBase = VanillaEntityDefinition.inherited(RaidParticipantEntity::new, mobEntityBase)
|
||||
EntityDefinitionBase<RaidParticipantEntity> raidParticipantEntityBase = EntityDefinitionBase.baseInherited(RaidParticipantEntity.class, mobEntityBase)
|
||||
.addTranslator(null) // Celebrating //TODO
|
||||
.build();
|
||||
VanillaEntityDefinition<SpellcasterIllagerEntity> spellcasterEntityBase = VanillaEntityDefinition.inherited(SpellcasterIllagerEntity::new, raidParticipantEntityBase)
|
||||
EntityDefinitionBase<SpellcasterIllagerEntity> spellcasterEntityBase = EntityDefinitionBase.baseInherited(SpellcasterIllagerEntity.class, raidParticipantEntityBase)
|
||||
.addTranslator(MetadataTypes.BYTE, SpellcasterIllagerEntity::setSpellType)
|
||||
.build();
|
||||
EVOKER = VanillaEntityDefinition.inherited(spellcasterEntityBase.factory(), spellcasterEntityBase)
|
||||
EVOKER = VanillaEntityDefinition.inherited(SpellcasterIllagerEntity::new, spellcasterEntityBase)
|
||||
.type(BuiltinEntityType.EVOKER)
|
||||
.height(1.95f).width(0.6f)
|
||||
.bedrockIdentifier("minecraft:evocation_illager")
|
||||
.build();
|
||||
ILLUSIONER = VanillaEntityDefinition.inherited(spellcasterEntityBase.factory(), spellcasterEntityBase)
|
||||
ILLUSIONER = VanillaEntityDefinition.inherited(SpellcasterIllagerEntity::new, spellcasterEntityBase)
|
||||
.type(BuiltinEntityType.ILLUSIONER)
|
||||
.height(1.95f).width(0.6f)
|
||||
.bedrockIdentifier("minecraft:evocation_illager")
|
||||
@@ -981,7 +981,7 @@ public final class EntityDefinitions {
|
||||
.height(1.8f).width(0.6f)
|
||||
.offset(1.62f)
|
||||
.build();
|
||||
WITCH = VanillaEntityDefinition.inherited(raidParticipantEntityBase.factory(), raidParticipantEntityBase)
|
||||
WITCH = VanillaEntityDefinition.inherited(RaidParticipantEntity::new, raidParticipantEntityBase)
|
||||
.type(BuiltinEntityType.WITCH)
|
||||
.height(1.8f).width(0.6f)
|
||||
.offset(1.62f)
|
||||
@@ -989,7 +989,7 @@ public final class EntityDefinitions {
|
||||
.build();
|
||||
}
|
||||
|
||||
VanillaEntityDefinition<AgeableEntity> ageableEntityBase = VanillaEntityDefinition.inherited(AgeableEntity::new, mobEntityBase)
|
||||
EntityDefinitionBase<AgeableEntity> ageableEntityBase = EntityDefinitionBase.baseInherited(AgeableEntity.class, mobEntityBase)
|
||||
.addTranslator(MetadataTypes.BOOLEAN, AgeableEntity::setBaby)
|
||||
.build();
|
||||
|
||||
@@ -1164,7 +1164,7 @@ public final class EntityDefinitions {
|
||||
|
||||
// Horses
|
||||
{
|
||||
VanillaEntityDefinition<AbstractHorseEntity> abstractHorseEntityBase = VanillaEntityDefinition.inherited(AbstractHorseEntity::new, ageableEntityBase)
|
||||
EntityDefinitionBase<AbstractHorseEntity> abstractHorseEntityBase = EntityDefinitionBase.baseInherited(AbstractHorseEntity.class, ageableEntityBase)
|
||||
.addTranslator(MetadataTypes.BYTE, AbstractHorseEntity::setHorseFlags)
|
||||
.build();
|
||||
CAMEL = VanillaEntityDefinition.inherited(CamelEntity::new, abstractHorseEntityBase)
|
||||
@@ -1186,14 +1186,14 @@ public final class EntityDefinitions {
|
||||
.type(BuiltinEntityType.ZOMBIE_HORSE)
|
||||
.height(1.6f).width(1.3965f)
|
||||
.build();
|
||||
VanillaEntityDefinition<ChestedHorseEntity> chestedHorseEntityBase = VanillaEntityDefinition.inherited(ChestedHorseEntity::new, abstractHorseEntityBase)
|
||||
EntityDefinitionBase<ChestedHorseEntity> chestedHorseEntityBase = EntityDefinitionBase.baseInherited(ChestedHorseEntity.class, abstractHorseEntityBase)
|
||||
.addTranslator(MetadataTypes.BOOLEAN, (horseEntity, entityMetadata) -> horseEntity.setFlag(EntityFlag.CHESTED, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue()))
|
||||
.build();
|
||||
DONKEY = VanillaEntityDefinition.inherited(chestedHorseEntityBase.factory(), chestedHorseEntityBase)
|
||||
DONKEY = VanillaEntityDefinition.inherited(ChestedHorseEntity::new, chestedHorseEntityBase)
|
||||
.type(BuiltinEntityType.DONKEY)
|
||||
.height(1.6f).width(1.3965f)
|
||||
.build();
|
||||
MULE = VanillaEntityDefinition.inherited(chestedHorseEntityBase.factory(), chestedHorseEntityBase)
|
||||
MULE = VanillaEntityDefinition.inherited(ChestedHorseEntity::new, chestedHorseEntityBase)
|
||||
.type(BuiltinEntityType.MULE)
|
||||
.height(1.6f).width(1.3965f)
|
||||
.build();
|
||||
@@ -1209,7 +1209,7 @@ public final class EntityDefinitions {
|
||||
.build();
|
||||
}
|
||||
|
||||
VanillaEntityDefinition<TameableEntity> tameableEntityBase = VanillaEntityDefinition.<TameableEntity>inherited(null, ageableEntityBase) // No factory, is abstract
|
||||
EntityDefinitionBase<TameableEntity> tameableEntityBase = EntityDefinitionBase.baseInherited(TameableEntity.class, ageableEntityBase)
|
||||
.addTranslator(MetadataTypes.BYTE, TameableEntity::setTameableFlags)
|
||||
.addTranslator(MetadataTypes.OPTIONAL_LIVING_ENTITY_REFERENCE, TameableEntity::setOwner)
|
||||
.build();
|
||||
@@ -1246,7 +1246,7 @@ public final class EntityDefinitions {
|
||||
Registries.JAVA_ENTITY_IDENTIFIERS.get().put("minecraft:marker", null); // We don't need an entity definition for this as it is never sent over the network
|
||||
}
|
||||
|
||||
private static VanillaEntityDefinition<BoatEntity> buildBoat(VanillaEntityDefinition<BoatEntity> base, BuiltinEntityType BuiltinEntityType, BoatEntity.BoatVariant variant) {
|
||||
private static VanillaEntityDefinition<BoatEntity> buildBoat(EntityDefinitionBase<BoatEntity> base, BuiltinEntityType BuiltinEntityType, BoatEntity.BoatVariant variant) {
|
||||
return VanillaEntityDefinition.inherited((session, javaId, bedrockId, uuid, definition, position, motion, yaw, pitch, headYaw) ->
|
||||
new BoatEntity(session, javaId, bedrockId, uuid, definition, position, motion, yaw, variant), base)
|
||||
.type(BuiltinEntityType)
|
||||
@@ -1254,7 +1254,7 @@ public final class EntityDefinitions {
|
||||
.build();
|
||||
}
|
||||
|
||||
private static VanillaEntityDefinition<ChestBoatEntity> buildChestBoat(VanillaEntityDefinition<ChestBoatEntity> base, BuiltinEntityType BuiltinEntityType, BoatEntity.BoatVariant variant) {
|
||||
private static VanillaEntityDefinition<ChestBoatEntity> buildChestBoat(EntityDefinitionBase<ChestBoatEntity> base, BuiltinEntityType BuiltinEntityType, BoatEntity.BoatVariant variant) {
|
||||
return VanillaEntityDefinition.inherited((session, javaId, bedrockId, uuid, definition, position, motion, yaw, pitch, headYaw) ->
|
||||
new ChestBoatEntity(session, javaId, bedrockId, uuid, definition, position, motion, yaw, variant), base)
|
||||
.type(BuiltinEntityType)
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* 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.entity;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.checkerframework.checker.index.qual.Positive;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.geyser.api.entity.CustomEntityDefinition;
|
||||
import org.geysermc.geyser.api.entity.JavaEntityType;
|
||||
import org.geysermc.geyser.api.predicate.MinecraftPredicate;
|
||||
import org.geysermc.geyser.api.predicate.PredicateStrategy;
|
||||
import org.geysermc.geyser.api.predicate.context.entity.EntitySpawnContext;
|
||||
import org.geysermc.geyser.entity.factory.EntityFactory;
|
||||
import org.geysermc.geyser.entity.properties.GeyserEntityProperties;
|
||||
import org.geysermc.geyser.entity.properties.type.PropertyType;
|
||||
import org.geysermc.geyser.entity.type.Entity;
|
||||
import org.geysermc.geyser.registry.Registries;
|
||||
import org.geysermc.geyser.translator.entity.EntityMetadataTranslator;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.MetadataType;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
@Getter
|
||||
@Accessors(fluent = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class GeyserCustomEntityDefinition<T extends Entity> extends EntityDefinition<T> implements CustomEntityDefinition {
|
||||
private final List<MinecraftPredicate<? super EntitySpawnContext>> predicates;
|
||||
private final PredicateStrategy predicateStrategy;
|
||||
|
||||
public GeyserCustomEntityDefinition(EntityFactory<T> factory, String bedrockIdentifier, List<MinecraftPredicate<? super EntitySpawnContext>> predicates, PredicateStrategy predicateStrategy,
|
||||
float width, float height, float offset, GeyserEntityProperties registeredProperties, List<EntityMetadataTranslator<? super T, ?, ?>> translators) {
|
||||
super(factory, bedrockIdentifier, width, height, offset, registeredProperties, translators);
|
||||
this.predicates = predicates;
|
||||
this.predicateStrategy = predicateStrategy;
|
||||
}
|
||||
|
||||
public static Builder<?> inherited(String bedrockIdentifier, JavaEntityType vanillaType) {
|
||||
if (!vanillaType.vanilla()) {
|
||||
throw new IllegalArgumentException("vanillaType must be a vanilla entity type, was: " + vanillaType);
|
||||
}
|
||||
VanillaEntityDefinition<?> parent = Registries.ENTITY_DEFINITIONS.get(vanillaType);
|
||||
if (parent == null) {
|
||||
throw new IllegalArgumentException("No vanilla entity definition registered for vanilla entity type " + vanillaType);
|
||||
}
|
||||
// TODO fix the rawtypes/unchecked
|
||||
return new Builder<>(bedrockIdentifier, parent.factory(), parent.width(), parent.height(), parent.offset(), new ObjectArrayList(parent.translators()));
|
||||
}
|
||||
|
||||
public static class Builder<T extends Entity> extends EntityDefinition.Builder<T> implements CustomEntityDefinition.Builder {
|
||||
protected List<MinecraftPredicate<? super EntitySpawnContext>> predicates;
|
||||
protected PredicateStrategy predicateStrategy = PredicateStrategy.AND;
|
||||
|
||||
protected Builder(EntityFactory<T> factory, String bedrockIdentifier) {
|
||||
super(factory);
|
||||
this.bedrockIdentifier = Objects.requireNonNull(bedrockIdentifier, "bedrockIdentifier must not be null");
|
||||
}
|
||||
|
||||
protected Builder(String bedrockIdentifier, EntityFactory<T> factory, float width, float height, float offset, List<EntityMetadataTranslator<? super T, ?, ?>> translators) {
|
||||
super(factory, width, height, offset, translators);
|
||||
this.bedrockIdentifier = Objects.requireNonNull(bedrockIdentifier, "bedrockIdentifier must not be null");
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityDefinition.Builder<T> bedrockIdentifier(String bedrockIdentifier) {
|
||||
throw new UnsupportedOperationException("bedrockIdentifier should be immutable");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<T> width(@Positive float width) {
|
||||
return (Builder<T>) super.width(width);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<T> height(@Positive float height) {
|
||||
return (Builder<T>) super.height(height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<T> heightAndWidth(@Positive float value) {
|
||||
return (Builder<T>) super.heightAndWidth(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<T> offset(@Positive float offset) {
|
||||
return (Builder<T>) super.offset(offset);
|
||||
}
|
||||
|
||||
public Builder<T> predicate(@NonNull MinecraftPredicate<? super EntitySpawnContext> predicate) {
|
||||
predicates.add(Objects.requireNonNull(predicate, "predicate must not be null"));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<T> predicateStrategy(@NonNull PredicateStrategy strategy) {
|
||||
predicateStrategy = Objects.requireNonNull(strategy, "strategy must not be null");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<T> property(PropertyType<?, ?> propertyType) {
|
||||
return (Builder<T>) super.property(propertyType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <U, EM extends EntityMetadata<U, ? extends MetadataType<U>>> Builder<T> addTranslator(MetadataType<U> type, BiConsumer<T, EM> translateFunction) {
|
||||
return (Builder<T>) super.addTranslator(type, translateFunction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<T> addTranslator(EntityMetadataTranslator<T, ?, ?> translator) {
|
||||
return (Builder<T>) super.addTranslator(translator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeyserCustomEntityDefinition<T> build() {
|
||||
if (predicates.isEmpty()) {
|
||||
throw new IllegalStateException("predicates must not be empty!");
|
||||
}
|
||||
return new GeyserCustomEntityDefinition<>(factory, bedrockIdentifier, predicates, predicateStrategy, width, height, offset, propertiesBuilder.build(), translators);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,6 +72,11 @@ public record GeyserEntityType(Identifier javaIdentifier, int javaId) implements
|
||||
return javaIdentifier.equals(UNREGISTERED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean vanilla() {
|
||||
return VANILLA.containsValue(this);
|
||||
}
|
||||
|
||||
public boolean is(EntityType type) {
|
||||
return javaId == type.id();
|
||||
}
|
||||
|
||||
@@ -48,21 +48,24 @@ import java.util.function.BiConsumer;
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class VanillaEntityDefinition<T extends Entity> extends EntityDefinition<T> {
|
||||
private final GeyserEntityType entityType;
|
||||
|
||||
public VanillaEntityDefinition(EntityFactory<T> factory, GeyserEntityType entityType, String bedrockIdentifier,
|
||||
float width, float height, float offset, GeyserEntityProperties registeredProperties, List<EntityMetadataTranslator<? super T, ?, ?>> translators) {
|
||||
super(factory, entityType, bedrockIdentifier, width, height, offset, registeredProperties, translators);
|
||||
super(factory, bedrockIdentifier, width, height, offset, registeredProperties, translators);
|
||||
this.entityType = entityType;
|
||||
}
|
||||
|
||||
public static <T extends Entity> Builder<T> builder(EntityFactory<T> factory) {
|
||||
return new Builder<>(factory);
|
||||
}
|
||||
|
||||
public static <T extends Entity> Builder<T> inherited(EntityFactory<T> factory, EntityDefinition<? super T> parent) {
|
||||
public static <T extends Entity> Builder<T> inherited(EntityFactory<T> factory, EntityDefinitionBase<? super T> parent) {
|
||||
return new Builder<>(factory, parent.width(), parent.height(), parent.offset(), new ObjectArrayList<>(parent.translators()));
|
||||
}
|
||||
|
||||
public static class Builder<T extends Entity> extends EntityDefinition.Builder<T> {
|
||||
protected GeyserEntityType type;
|
||||
|
||||
protected Builder(EntityFactory<T> factory) {
|
||||
super(factory);
|
||||
@@ -72,8 +75,13 @@ public class VanillaEntityDefinition<T extends Entity> extends EntityDefinition<
|
||||
super(factory, width, height, offset, translators);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the bedrock identifier as well
|
||||
*/
|
||||
public Builder<T> type(BuiltinEntityType type) {
|
||||
return (Builder<T>) super.type(GeyserEntityType.ofVanilla(type));
|
||||
this.type = GeyserEntityType.ofVanilla(type);
|
||||
this.bedrockIdentifier = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -121,6 +129,14 @@ public class VanillaEntityDefinition<T extends Entity> extends EntityDefinition<
|
||||
return build(true);
|
||||
}
|
||||
|
||||
private void validateTypeAndIdentifier() {
|
||||
if (type == null) {
|
||||
throw new IllegalStateException("Missing entity type!");
|
||||
} else if (bedrockIdentifier == null) {
|
||||
bedrockIdentifier = type.javaIdentifier().toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param register whether to register this entity in the Registries for entity types. Generally this should be
|
||||
* set to false if we're not expecting this entity to spawn from the network.
|
||||
|
||||
@@ -38,7 +38,7 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.PotionMixData;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.api.entity.JavaEntityType;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.entity.VanillaEntityDefinition;
|
||||
import org.geysermc.geyser.inventory.recipe.GeyserRecipe;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
import org.geysermc.geyser.pack.ResourcePackHolder;
|
||||
@@ -65,14 +65,12 @@ import org.geysermc.geyser.translator.level.event.LevelEventTranslator;
|
||||
import org.geysermc.geyser.translator.sound.SoundInteractionTranslator;
|
||||
import org.geysermc.geyser.translator.sound.SoundTranslator;
|
||||
import org.geysermc.mcprotocollib.network.packet.Packet;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.event.LevelEvent;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.particle.ParticleType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
@@ -126,7 +124,8 @@ public final class Registries {
|
||||
* A map containing all entity types and their respective Geyser definitions
|
||||
*/
|
||||
// Is a Reference2ObjectMap since GeyserEntityType, the implementation of JavaEntityType, only ever keeps one instance per registered entity type
|
||||
public static final SimpleMappedRegistry<JavaEntityType, EntityDefinition<?>> ENTITY_DEFINITIONS = SimpleMappedRegistry.create(RegistryLoaders.empty(Reference2ObjectOpenHashMap::new));
|
||||
// TODO rename to VANILLA_ENTITY_DEFINITIONS
|
||||
public static final SimpleMappedRegistry<JavaEntityType, VanillaEntityDefinition<?>> ENTITY_DEFINITIONS = SimpleMappedRegistry.create(RegistryLoaders.empty(Reference2ObjectOpenHashMap::new));
|
||||
|
||||
/**
|
||||
* A registry holding a list of all the known entity properties to be sent to the client after start game.
|
||||
@@ -136,7 +135,7 @@ public final class Registries {
|
||||
/**
|
||||
* A map containing all Java entity identifiers and their respective Geyser definitions
|
||||
*/
|
||||
public static final SimpleMappedRegistry<String, EntityDefinition<?>> JAVA_ENTITY_IDENTIFIERS = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new));
|
||||
public static final SimpleMappedRegistry<String, VanillaEntityDefinition<?>> JAVA_ENTITY_IDENTIFIERS = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new));
|
||||
|
||||
/**
|
||||
* A registry containing all the Java packet translators.
|
||||
|
||||
@@ -34,6 +34,7 @@ import org.geysermc.geyser.api.block.custom.component.GeometryComponent;
|
||||
import org.geysermc.geyser.api.block.custom.component.MaterialInstance;
|
||||
import org.geysermc.geyser.api.block.custom.nonvanilla.JavaBlockState;
|
||||
import org.geysermc.geyser.api.command.Command;
|
||||
import org.geysermc.geyser.api.entity.CustomEntityDefinition;
|
||||
import org.geysermc.geyser.api.entity.JavaEntityType;
|
||||
import org.geysermc.geyser.api.event.EventRegistrar;
|
||||
import org.geysermc.geyser.api.extension.Extension;
|
||||
@@ -46,6 +47,7 @@ import org.geysermc.geyser.api.pack.option.PriorityOption;
|
||||
import org.geysermc.geyser.api.pack.option.SubpackOption;
|
||||
import org.geysermc.geyser.api.pack.option.UrlFallbackOption;
|
||||
import org.geysermc.geyser.api.util.Identifier;
|
||||
import org.geysermc.geyser.entity.GeyserCustomEntityDefinition;
|
||||
import org.geysermc.geyser.entity.GeyserEntityType;
|
||||
import org.geysermc.geyser.event.GeyserEventRegistrar;
|
||||
import org.geysermc.geyser.extension.command.GeyserExtensionCommand;
|
||||
@@ -113,6 +115,7 @@ public class ProviderRegistryLoader implements RegistryLoader<Map<Class<?>, Prov
|
||||
|
||||
// entities
|
||||
providers.put(JavaEntityType.class, args -> args.length == 1 ? GeyserEntityType.ofVanilla((Identifier) args[0]) : GeyserEntityType.createCustom((Identifier) args[0], (int) args[1]));
|
||||
providers.put(CustomEntityDefinition.class, args -> GeyserCustomEntityDefinition.inherited((String) args[0], (JavaEntityType) args[1]));
|
||||
|
||||
return providers;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user