Entity refactor bug fixes and other 1.18 changes

This commit is contained in:
Camotoy 2021-11-18 20:44:03 -05:00
parent 11997ed82b
commit e0a7887f3f
No known key found for this signature in database
GPG Key ID: 7EEFB66FE798081F
60 changed files with 243 additions and 301 deletions

View File

@ -40,7 +40,7 @@ public class AbstractArrowEntity extends Entity {
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
// Set the correct texture if using the resource pack
dirtyMetadata.getFlags().setFlag(EntityFlag.BRIBED, definition.entityType() == EntityType.SPECTRAL_ARROW);
setFlag(EntityFlag.BRIBED, definition.entityType() == EntityType.SPECTRAL_ARROW);
setMotion(motion);
}

View File

@ -45,7 +45,7 @@ public class EnderCrystalEntity extends Entity {
protected void initializeMetadata() {
super.initializeMetadata();
// Bedrock 1.16.100+ - prevents the entity from appearing on fire itself when fire is underneath it
dirtyMetadata.getFlags().setFlag(EntityFlag.FIRE_IMMUNE, true);
setFlag(EntityFlag.FIRE_IMMUNE, true);
}
public void setBlockTarget(EntityMetadata<Position> entityMetadata) {

View File

@ -32,7 +32,6 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEnti
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityDataMap;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlags;
import com.nukkitx.protocol.bedrock.packet.AddEntityPacket;
@ -83,13 +82,15 @@ public class Entity {
protected float boundingBoxHeight;
@Setter(AccessLevel.NONE)
protected float boundingBoxWidth;
@Setter(AccessLevel.NONE)
protected String nametag = "";
/* Metadata end */
protected LongOpenHashSet passengers = new LongOpenHashSet();
/**
* A container to store temporary metadata before it's sent to Bedrock.
*/
protected final EntityDataMap dirtyMetadata = new EntityDataMap();
protected final GeyserDirtyMetadata dirtyMetadata = new GeyserDirtyMetadata();
/**
* The entity flags for the Bedrock entity.
* These must always be saved - if flags are updated and the other values aren't present, the Bedrock client will
@ -146,15 +147,13 @@ public class Entity {
addEntityPacket.setPosition(position);
addEntityPacket.setMotion(motion);
addEntityPacket.setRotation(getBedrockRotation());
addEntityPacket.setEntityType(definition.bedrockId());
addEntityPacket.getMetadata().putFlags(flags)
.putAll(dirtyMetadata);
addEntityPacket.getMetadata().putFlags(flags);
dirtyMetadata.apply(addEntityPacket.getMetadata());
addAdditionalSpawnData(addEntityPacket);
valid = true;
session.sendUpstreamPacket(addEntityPacket);
dirtyMetadata.clear();
flagsDirty = false;
session.getConnector().getLogger().debug("Spawned entity " + getClass().getName() + " at location " + position + " with id " + geyserId + " (java id " + entityId + ")");
@ -293,15 +292,15 @@ public class Entity {
return;
}
if (!dirtyMetadata.isEmpty() || flagsDirty) {
if (dirtyMetadata.hasEntries() || flagsDirty) {
SetEntityDataPacket entityDataPacket = new SetEntityDataPacket();
entityDataPacket.setRuntimeEntityId(geyserId);
entityDataPacket.getMetadata().putFlags(flags);
entityDataPacket.getMetadata().putAll(dirtyMetadata);
if (flagsDirty) {
entityDataPacket.getMetadata().putFlags(flags);
flagsDirty = false;
}
dirtyMetadata.apply(entityDataPacket.getMetadata());
session.sendUpstreamPacket(entityDataPacket);
dirtyMetadata.clear();
flagsDirty = false;
}
}
@ -343,9 +342,9 @@ public class Entity {
public void setDisplayName(EntityMetadata<Component> entityMetadata) {
Component name = entityMetadata.getValue();
if (name != null) {
String displayName = MessageTranslator.convertMessage(name, session.getLocale());
dirtyMetadata.put(EntityData.NAMETAG, displayName);
} else if (!dirtyMetadata.getString(EntityData.NAMETAG).isEmpty()) { //TODO
nametag = MessageTranslator.convertMessage(name, session.getLocale());
dirtyMetadata.put(EntityData.NAMETAG, nametag);
} else if (!nametag.isEmpty()) {
// Clear nametag
dirtyMetadata.put(EntityData.NAMETAG, "");
}
@ -376,14 +375,24 @@ public class Entity {
*/
protected void setDimensions(Pose pose) {
// No flexibility options for basic entities
if (boundingBoxHeight != definition.height() || boundingBoxWidth != definition.width()) {
boundingBoxWidth = definition.width();
boundingBoxHeight = definition.height();
dirtyMetadata.put(EntityData.BOUNDING_BOX_WIDTH, boundingBoxWidth);
setBoundingBoxHeight(definition.height());
setBoundingBoxWidth(definition.width());
}
public void setBoundingBoxHeight(float height) {
if (height != boundingBoxHeight) {
boundingBoxHeight = height;
dirtyMetadata.put(EntityData.BOUNDING_BOX_HEIGHT, boundingBoxHeight);
}
}
public void setBoundingBoxWidth(float width) {
if (width != boundingBoxWidth) {
boundingBoxWidth = width;
dirtyMetadata.put(EntityData.BOUNDING_BOX_WIDTH, boundingBoxWidth);
}
}
/**
* Set a float from 0-1 - how strong the "frozen" overlay should be on screen.
*/
@ -396,6 +405,10 @@ public class Entity {
return freezingPercentage;
}
public void setRiderSeatPosition(Vector3f position) {
dirtyMetadata.put(EntityData.RIDER_SEAT_POSITION, position);
}
/**
* If true, the entity should be shaking on the client's end.
*

View File

@ -46,7 +46,7 @@ import java.util.function.BiConsumer;
*
* @param <T> the entity type this definition represents
*/
public record EntityDefinition<T extends Entity>(EntityFactory<T> factory, EntityType entityType, int bedrockId, String identifier,
public record EntityDefinition<T extends Entity>(EntityFactory<T> factory, EntityType entityType, String identifier,
float width, float height, float offset, List<EntityMetadataTranslator<? super T, ?>> translators) {
public static <T extends Entity> Builder<T> inherited(BaseEntityFactory<T> factory, EntityDefinition<? super T> parent) {
@ -54,7 +54,7 @@ public record EntityDefinition<T extends Entity>(EntityFactory<T> factory, Entit
}
public static <T extends Entity> Builder<T> inherited(EntityFactory<T> factory, EntityDefinition<? super T> parent) {
return new Builder<>(factory, parent.entityType, parent.bedrockId, parent.identifier, parent.width, parent.height, parent.offset, new ObjectArrayList<>(parent.translators));
return new Builder<>(factory, parent.entityType, parent.identifier, parent.width, parent.height, parent.offset, new ObjectArrayList<>(parent.translators));
}
public static <T extends Entity> Builder<T> builder(EntityFactory<T> factory) {
@ -66,7 +66,6 @@ public record EntityDefinition<T extends Entity>(EntityFactory<T> factory, Entit
public static class Builder<T extends Entity> {
private final EntityFactory<T> factory;
private EntityType type;
private int bedrockId;
private String identifier;
private float width;
private float height;
@ -78,10 +77,9 @@ public record EntityDefinition<T extends Entity>(EntityFactory<T> factory, Entit
translators = new ObjectArrayList<>();
}
public Builder(EntityFactory<T> factory, EntityType type, int bedrockId, String identifier, float width, float height, float offset, List<EntityMetadataTranslator<? super T, ?>> translators) {
public Builder(EntityFactory<T> factory, EntityType type, String identifier, float width, float height, float offset, List<EntityMetadataTranslator<? super T, ?>> translators) {
this.factory = factory;
this.type = type;
this.bedrockId = bedrockId;
this.identifier = identifier;
this.width = width;
this.height = height;
@ -129,10 +127,10 @@ public record EntityDefinition<T extends Entity>(EntityFactory<T> factory, Entit
if (identifier == null && type != null) {
identifier = "minecraft:" + type.name().toLowerCase(Locale.ROOT);
}
EntityDefinition<T> definition = new EntityDefinition<>(factory, type, bedrockId, identifier, width, height, offset, translators);
EntityDefinition<T> definition = new EntityDefinition<>(factory, type, identifier, width, height, offset, translators);
if (register && definition.entityType() != null) {
Registries.ENTITY_DEFINITIONS.get().putIfAbsent(definition.entityType(), definition);
Registries.JAVA_ENTITY_IDENTIFIERS.get().putIfAbsent(definition.identifier(), definition);
Registries.JAVA_ENTITY_IDENTIFIERS.get().putIfAbsent("minecraft:" + type.name().toLowerCase(Locale.ROOT), definition);
}
return definition;
}

View File

@ -33,7 +33,6 @@ import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import net.kyori.adventure.text.Component;
import org.geysermc.connector.entity.factory.BaseEntityFactory;
import org.geysermc.connector.entity.factory.EntityFactory;
import org.geysermc.connector.entity.factory.ExperienceOrbEntityFactory;
import org.geysermc.connector.entity.factory.PaintingEntityFactory;
import org.geysermc.connector.entity.living.*;
@ -52,6 +51,7 @@ import org.geysermc.connector.entity.living.monster.raid.SpellcasterIllagerEntit
import org.geysermc.connector.entity.living.monster.raid.VindicatorEntity;
import org.geysermc.connector.entity.player.PlayerEntity;
import org.geysermc.connector.network.translators.chat.MessageTranslator;
import org.geysermc.connector.registry.Registries;
public final class EntityDefinitions {
public static final EntityDefinition<AreaEffectCloudEntity> AREA_EFFECT_CLOUD;
@ -192,7 +192,6 @@ public final class EntityDefinitions {
{
AREA_EFFECT_CLOUD = EntityDefinition.inherited(AreaEffectCloudEntity::new, entityBase)
.type(EntityType.AREA_EFFECT_CLOUD)
.bedrockId(95)
.height(0.5f).width(1.0f)
.addTranslator(MetadataType.FLOAT, AreaEffectCloudEntity::setRadius)
.addTranslator(MetadataType.INT, (entity, entityMetadata) -> entity.getDirtyMetadata().put(EntityData.EFFECT_COLOR, entityMetadata.getValue()))
@ -201,7 +200,6 @@ public final class EntityDefinitions {
.build();
BOAT = EntityDefinition.inherited(BoatEntity::new, entityBase)
.type(EntityType.BOAT)
.bedrockId(90)
.height(0.6f).width(1.6f)
.offset(0.35f)
.addTranslator(MetadataType.INT, (boatEntity, entityMetadata) -> boatEntity.getDirtyMetadata().put(EntityData.HURT_TIME, entityMetadata.getValue())) // Time since last hit
@ -216,12 +214,10 @@ public final class EntityDefinitions {
.build();
DRAGON_FIREBALL = EntityDefinition.inherited(ItemedFireballEntity::new, entityBase)
.type(EntityType.DRAGON_FIREBALL)
.bedrockId(79)
.heightAndWidth(1.0f)
.build();
END_CRYSTAL = EntityDefinition.inherited(EnderCrystalEntity::new, entityBase)
.type(EntityType.END_CRYSTAL)
.bedrockId(71)
.heightAndWidth(2.0f)
.addTranslator(MetadataType.OPTIONAL_POSITION, EnderCrystalEntity::setBlockTarget)
.<Boolean>addTranslator(MetadataType.BOOLEAN,
@ -229,115 +225,94 @@ public final class EntityDefinitions {
.build();
EXPERIENCE_ORB = EntityDefinition.inherited((ExperienceOrbEntityFactory) ExpOrbEntity::new, entityBase)
.type(EntityType.EXPERIENCE_ORB)
.bedrockId(69)
.identifier("minecraft:xp_orb")
.build();
EVOKER_FANGS = EntityDefinition.inherited(entityBase.factory(), entityBase)
.type(EntityType.EVOKER_FANGS)
.bedrockId(103)
.height(0.8f).width(0.5f)
.identifier("minecraft:evocation_fang")
.build();
EYE_OF_ENDER = EntityDefinition.inherited(Entity::new, entityBase)
.type(EntityType.EYE_OF_ENDER)
.bedrockId(70)
.heightAndWidth(0.25f)
.identifier("minecraft:eye_of_ender_signal")
.build();
FALLING_BLOCK = EntityDefinition.inherited(new EntityFactory<FallingBlockEntity>() {
}, entityBase) // TODO
FALLING_BLOCK = EntityDefinition.<FallingBlockEntity>inherited(null, entityBase)
.type(EntityType.FALLING_BLOCK)
.bedrockId(66)
.heightAndWidth(0.98f)
.addTranslator(null) // "start block position"
.build();
FIREBALL = EntityDefinition.inherited(ItemedFireballEntity::new, entityBase)
.type(EntityType.FIREBALL)
.bedrockId(85)
.heightAndWidth(1.0f)
.build();
FIREWORK_ROCKET = EntityDefinition.inherited(FireworkEntity::new, entityBase)
.type(EntityType.FIREWORK_ROCKET)
.bedrockId(72)
.heightAndWidth(0.25f)
.identifier("minecraft:fireworks_rocket")
.addTranslator(MetadataType.ITEM, FireworkEntity::setFireworkItem)
.addTranslator(MetadataType.OPTIONAL_VARINT, FireworkEntity::setPlayerGliding)
.build();
FISHING_BOBBER = EntityDefinition.inherited(new EntityFactory<FishingHookEntity>() {
}, entityBase) //TODO
FISHING_BOBBER = EntityDefinition.<FishingHookEntity>inherited(null, entityBase)
.type(EntityType.FISHING_BOBBER)
.bedrockId(77)
.identifier("minecraft:fishing_book")
.addTranslator(MetadataType.INT, FishingHookEntity::setHookedEntity)
.build();
ITEM = EntityDefinition.inherited(ItemEntity::new, entityBase)
.type(EntityType.ITEM)
.bedrockId(64)
.heightAndWidth(0.25f)
.offset(0.125f)
.addTranslator(MetadataType.ITEM, ItemEntity::setItem)
.build();
LEASH_KNOT = EntityDefinition.inherited(LeashKnotEntity::new, entityBase)
.type(EntityType.LEASH_KNOT)
.bedrockId(88)
.height(0.5f).width(0.375f)
.build();
LIGHTNING_BOLT = EntityDefinition.inherited(LightningEntity::new, entityBase)
.type(EntityType.LIGHTNING_BOLT)
.bedrockId(93)
.build();
LLAMA_SPIT = EntityDefinition.inherited(ThrowableEntity::new, entityBase)
.type(EntityType.LLAMA_SPIT)
.bedrockId(102)
.heightAndWidth(0.25f)
.build();
PAINTING = EntityDefinition.inherited((PaintingEntityFactory) PaintingEntity::new, entityBase)
.type(EntityType.PAINTING)
.bedrockId(83)
.build();
PRIMED_TNT = EntityDefinition.inherited(TNTEntity::new, entityBase)
.type(EntityType.PRIMED_TNT)
.bedrockId(65)
.heightAndWidth(0.98f)
.identifier("minecraft:tnt")
.addTranslator(MetadataType.INT, TNTEntity::setFuseLength)
.build();
SHULKER_BULLET = EntityDefinition.inherited(ThrowableEntity::new, entityBase)
.type(EntityType.SHULKER_BULLET)
.bedrockId(76)
.heightAndWidth(0.3125f)
.build();
SMALL_FIREBALL = EntityDefinition.inherited(ItemedFireballEntity::new, entityBase)
.type(EntityType.SMALL_FIREBALL)
.bedrockId(94)
.heightAndWidth(0.3125f)
.build();
SNOWBALL = EntityDefinition.inherited(ThrowableItemEntity::new, entityBase)
.type(EntityType.SNOWBALL)
.bedrockId(81)
.heightAndWidth(0.25f)
.build();
THROWN_ENDERPEARL = EntityDefinition.inherited(ThrowableItemEntity::new, entityBase)
.type(EntityType.THROWN_ENDERPEARL)
.bedrockId(87)
.heightAndWidth(0.25f)
.identifier("minecraft:ender_pearl")
.build();
THROWN_EGG = EntityDefinition.inherited(ThrowableItemEntity::new, entityBase)
.type(EntityType.THROWN_EGG)
.bedrockId(82)
.heightAndWidth(0.25f)
.identifier("minecraft:egg")
.build();
THROWN_EXP_BOTTLE = EntityDefinition.inherited(ThrowableItemEntity::new, entityBase)
.type(EntityType.THROWN_EXP_BOTTLE)
.bedrockId(68)
.heightAndWidth(0.25f)
.identifier("minecraft:xp_bottle")
.build();
THROWN_POTION = EntityDefinition.inherited(ThrownPotionEntity::new, entityBase)
.type(EntityType.THROWN_POTION)
.bedrockId(86)
.heightAndWidth(0.25f)
.identifier("minecraft:splash_potion")
.addTranslator(MetadataType.ITEM, ThrownPotionEntity::setPotion)
@ -349,30 +324,26 @@ public final class EntityDefinitions {
.build();
ARROW = EntityDefinition.inherited(TippedArrowEntity::new, abstractArrowBase)
.type(EntityType.ARROW)
.bedrockId(80)
.heightAndWidth(0.25f)
.addTranslator(MetadataType.INT, TippedArrowEntity::setPotionEffectColor)
.build();
SPECTRAL_ARROW = EntityDefinition.inherited(abstractArrowBase.factory(), abstractArrowBase)
.type(EntityType.SPECTRAL_ARROW)
.bedrockId(80)
.heightAndWidth(0.25f)
.identifier("minecraft:arrow")
.build();
TRIDENT = EntityDefinition.inherited(TridentEntity::new, abstractArrowBase) // TODO remove class
.type(EntityType.TRIDENT)
.bedrockId(73)
.identifier("minecraft:thrown_trident")
.addTranslator(null) // Loyalty
.<Boolean>addTranslator(MetadataType.BOOLEAN, (tridentEntity, entityMetadata) -> tridentEntity.setFlag(EntityFlag.ENCHANTED, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue()))
.build();
// Item frames are handled differently as they are blocks, not items, in Bedrock
ITEM_FRAME = EntityDefinition.inherited(new EntityFactory<ItemFrameEntity>() {
}, entityBase) // TODO
ITEM_FRAME = EntityDefinition.<ItemFrameEntity>inherited(null, entityBase)
.type(EntityType.ITEM_FRAME)
.addTranslator(MetadataType.ITEM, ItemFrameEntity::setItemInFrame)
.addTranslator(MetadataType.ITEM, ItemFrameEntity::setItemRotation)
.addTranslator(MetadataType.INT, ItemFrameEntity::setItemRotation)
.build();
GLOW_ITEM_FRAME = EntityDefinition.inherited(ITEM_FRAME.factory(), ITEM_FRAME)
.type(EntityType.GLOW_ITEM_FRAME)
@ -380,7 +351,6 @@ public final class EntityDefinitions {
MINECART = EntityDefinition.inherited(MinecartEntity::new, entityBase)
.type(EntityType.MINECART)
.bedrockId(84)
.height(0.7f).width(0.98f)
.offset(0.35f)
.addTranslator(MetadataType.INT, (minecartEntity, entityMetadata) -> minecartEntity.getDirtyMetadata().put(EntityData.HEALTH, entityMetadata.getValue()))
@ -388,7 +358,7 @@ public final class EntityDefinitions {
.<Float>addTranslator(MetadataType.FLOAT, (minecartEntity, entityMetadata) ->
// Power in Java, time in Bedrock
minecartEntity.getDirtyMetadata().put(EntityData.HURT_TIME, Math.min((int) ((FloatEntityMetadata) entityMetadata).getPrimitiveValue(), 15)))
.addTranslator(MetadataType.BLOCK_STATE, MinecartEntity::setCustomBlock)
.addTranslator(MetadataType.INT, MinecartEntity::setCustomBlock)
.addTranslator(MetadataType.INT, MinecartEntity::setCustomBlockOffset)
.addTranslator(MetadataType.BOOLEAN, MinecartEntity::setShowCustomBlock)
.build();
@ -398,7 +368,6 @@ public final class EntityDefinitions {
.build();
MINECART_COMMAND_BLOCK = EntityDefinition.inherited(CommandBlockMinecartEntity::new, MINECART)
.type(EntityType.MINECART_COMMAND_BLOCK)
.bedrockId(100)
.identifier("minecraft:command_block_minecart")
.addTranslator(MetadataType.STRING, (entity, entityMetadata) -> entity.getDirtyMetadata().put(EntityData.COMMAND_BLOCK_COMMAND, entityMetadata.getValue()))
.<Component>addTranslator(MetadataType.CHAT, (entity, entityMetadata) -> entity.getDirtyMetadata().put(EntityData.COMMAND_BLOCK_LAST_OUTPUT, MessageTranslator.convertMessage(entityMetadata.getValue())))
@ -423,30 +392,27 @@ public final class EntityDefinitions {
WITHER_SKULL = EntityDefinition.inherited(WitherSkullEntity::new, entityBase)
.type(EntityType.WITHER_SKULL)
.bedrockId(89)
.heightAndWidth(0.3125f)
.addTranslator(MetadataType.BOOLEAN, WitherSkullEntity::setDangerous)
.build();
WITHER_SKULL_DANGEROUS = EntityDefinition.inherited(WITHER_SKULL.factory(), WITHER_SKULL)
.bedrockId(91)
.build(false);
}
EntityDefinition<LivingEntity> livingEntityBase = EntityDefinition.inherited(LivingEntity::new, entityBase)
.addTranslator(MetadataType.BYTE, LivingEntity::setLivingEntityFlags)
.addTranslator(MetadataType.FLOAT, LivingEntity::setHealth)
.<Float>addTranslator(MetadataType.FLOAT,
.<Float>addTranslator(MetadataType.INT,
(livingEntity, entityMetadata) -> livingEntity.getDirtyMetadata().put(EntityData.EFFECT_COLOR, entityMetadata.getValue()))
.<Boolean>addTranslator(MetadataType.BOOLEAN,
(livingEntity, entityMetadata) -> livingEntity.getDirtyMetadata().put(EntityData.EFFECT_AMBIENT, (byte) (((BooleanEntityMetadata) entityMetadata).getPrimitiveValue() ? 1 : 0)))
.addTranslator(null) // Arrow count
.addTranslator(null) // Stinger count
.addTranslator(MetadataType.POSITION, LivingEntity::setBedPosition)
.addTranslator(MetadataType.OPTIONAL_POSITION, LivingEntity::setBedPosition)
.build();
ARMOR_STAND = EntityDefinition.inherited(ArmorStandEntity::new, livingEntityBase)
.type(EntityType.ARMOR_STAND)
.bedrockId(61)
.height(1.975f).width(0.5f)
.addTranslator(MetadataType.BYTE, ArmorStandEntity::setArmorStandFlags)
.addTranslator(MetadataType.ROTATION, ArmorStandEntity::setHeadRotation)
@ -458,7 +424,6 @@ public final class EntityDefinitions {
.build();
PLAYER = EntityDefinition.<PlayerEntity>inherited(null, livingEntityBase)
.type(EntityType.PLAYER)
.bedrockId(63)
.height(1.8f).width(0.6f)
.offset(1.62f)
.addTranslator(MetadataType.FLOAT, PlayerEntity::setAbsorptionHearts)
@ -477,24 +442,20 @@ public final class EntityDefinitions {
{
BAT = EntityDefinition.inherited(BatEntity::new, mobEntityBase)
.type(EntityType.BAT)
.bedrockId(19)
.height(0.9f).width(0.5f)
.addTranslator(MetadataType.BYTE, BatEntity::setBatFlags)
.build();
BLAZE = EntityDefinition.inherited(BlazeEntity::new, mobEntityBase)
.type(EntityType.BLAZE)
.bedrockId(43)
.height(1.8f).width(0.6f)
.addTranslator(MetadataType.BYTE, BlazeEntity::setBlazeFlags)
.build();
CAVE_SPIDER = EntityDefinition.inherited(MonsterEntity::new, mobEntityBase)
.type(EntityType.CAVE_SPIDER)
.bedrockId(40)
.height(0.5f).width(0.7f)
.build();
CREEPER = EntityDefinition.inherited(CreeperEntity::new, mobEntityBase)
.type(EntityType.CREEPER)
.bedrockId(33)
.height(1.7f).width(0.6f)
.offset(1.62f)
.addTranslator(MetadataType.INT, CreeperEntity::setSwelling)
@ -503,7 +464,6 @@ public final class EntityDefinitions {
.build();
DOLPHIN = EntityDefinition.inherited(WaterEntity::new, mobEntityBase)
.type(EntityType.DOLPHIN)
.bedrockId(31)
.height(0.6f).width(0.9f)
//TODO check
.addTranslator(null) // treasure position
@ -512,7 +472,6 @@ public final class EntityDefinitions {
.build();
ENDERMAN = EntityDefinition.inherited(EndermanEntity::new, mobEntityBase)
.type(EntityType.ENDERMAN)
.bedrockId(38)
.height(2.9f).width(0.6f)
.addTranslator(MetadataType.BLOCK_STATE, EndermanEntity::setCarriedBlock)
.addTranslator(MetadataType.BOOLEAN, EndermanEntity::setScreaming)
@ -520,47 +479,40 @@ public final class EntityDefinitions {
.build();
ENDERMITE = EntityDefinition.inherited(MonsterEntity::new, mobEntityBase)
.type(EntityType.ENDERMITE)
.bedrockId(55)
.height(0.3f).width(0.4f)
.build();
ENDER_DRAGON = EntityDefinition.inherited(EnderDragonEntity::new, mobEntityBase)
.type(EntityType.ENDER_DRAGON)
.bedrockId(53)
.addTranslator(MetadataType.INT, EnderDragonEntity::setPhase)
.build();
GHAST = EntityDefinition.inherited(GhastEntity::new, mobEntityBase)
.type(EntityType.GHAST)
.bedrockId(41)
.heightAndWidth(4.0f)
.addTranslator(MetadataType.BOOLEAN, GhastEntity::setGhastAttacking)
.build();
GIANT = EntityDefinition.inherited(GiantEntity::new, mobEntityBase)
.type(EntityType.GIANT)
.bedrockId(32)
.height(1.8f).width(1.6f)
.offset(1.62f)
.identifier("minecraft:zombie")
.build();
IRON_GOLEM = EntityDefinition.inherited(IronGolemEntity::new, mobEntityBase)
.type(EntityType.IRON_GOLEM)
.bedrockId(20)
.height(2.7f).width(1.4f)
.addTranslator(null) // "is player created", which doesn't seem to do anything clientside
.build();
PHANTOM = EntityDefinition.inherited(PhantomEntity::new, mobEntityBase)
.type(EntityType.PHANTOM)
.bedrockId(58)
.height(0.5f).width(0.9f)
.offset(0.6f)
.addTranslator(MetadataType.INT, PhantomEntity::setPhantomScale)
.build();
SILVERFISH = EntityDefinition.inherited(MonsterEntity::new, mobEntityBase)
.type(EntityType.SILVERFISH)
.bedrockId(39)
.height(0.3f).width(0.4f)
.build();
SHULKER = EntityDefinition.inherited(ShulkerEntity::new, mobEntityBase)
.type(EntityType.SHULKER)
.bedrockId(54)
.heightAndWidth(1f)
.addTranslator(MetadataType.DIRECTION, ShulkerEntity::setAttachedFace)
.addTranslator(MetadataType.BYTE, ShulkerEntity::setShulkerHeight)
@ -568,44 +520,37 @@ public final class EntityDefinitions {
.build();
SKELETON = EntityDefinition.inherited(SkeletonEntity::new, mobEntityBase)
.type(EntityType.SKELETON)
.bedrockId(34)
.height(1.8f).width(0.6f)
.offset(1.62f)
.addTranslator(MetadataType.BOOLEAN, SkeletonEntity::setConvertingToStray)
.build();
SNOW_GOLEM = EntityDefinition.inherited(SnowGolemEntity::new, mobEntityBase)
.type(EntityType.SNOW_GOLEM)
.bedrockId(21)
.height(1.9f).width(0.7f)
.addTranslator(MetadataType.BYTE, SnowGolemEntity::setSnowGolemFlags)
.build();
SPIDER = EntityDefinition.inherited(SpiderEntity::new, mobEntityBase)
.type(EntityType.SPIDER)
.bedrockId(35)
.height(0.9f).width(1.4f)
.offset(1f)
.addTranslator(MetadataType.BYTE, SpiderEntity::setSpiderFlags)
.build();
SQUID = EntityDefinition.inherited(SquidEntity::new, mobEntityBase)
.type(EntityType.SQUID)
.bedrockId(17)
.heightAndWidth(0.8f)
.build();
STRAY = EntityDefinition.inherited(AbstractSkeletonEntity::new, mobEntityBase)
.type(EntityType.STRAY)
.bedrockId(46)
.height(1.8f).width(0.6f)
.offset(1.62f)
.build();
VEX = EntityDefinition.inherited(VexEntity::new, mobEntityBase)
.type(EntityType.VEX)
.bedrockId(105)
.height(0.8f).width(0.4f)
.addTranslator(MetadataType.BYTE, VexEntity::setVexFlags)
.build();
WITHER = EntityDefinition.inherited(WitherEntity::new, mobEntityBase)
.type(EntityType.WITHER)
.bedrockId(52)
.height(3.5f).width(0.9f)
.addTranslator(MetadataType.INT, WitherEntity::setTarget1)
.addTranslator(MetadataType.INT, WitherEntity::setTarget2)
@ -614,18 +559,15 @@ public final class EntityDefinitions {
.build();
WITHER_SKELETON = EntityDefinition.inherited(AbstractSkeletonEntity::new, mobEntityBase)
.type(EntityType.WITHER_SKELETON)
.bedrockId(48)
.height(2.4f).width(0.7f)
.build();
ZOGLIN = EntityDefinition.inherited(ZoglinEntity::new, mobEntityBase)
.type(EntityType.ZOGLIN)
.bedrockId(126)
.height(1.4f).width(1.3965f)
.addTranslator(MetadataType.BOOLEAN, ZoglinEntity::setBaby)
.build();
ZOMBIE = EntityDefinition.inherited(ZombieEntity::new, mobEntityBase)
.type(EntityType.ZOMBIE)
.bedrockId(32)
.height(1.8f).width(0.6f)
.offset(1.62f)
.addTranslator(MetadataType.BOOLEAN, ZombieEntity::setZombieBaby)
@ -634,7 +576,6 @@ public final class EntityDefinitions {
.build();
ZOMBIE_VILLAGER = EntityDefinition.inherited(ZombieVillagerEntity::new, ZOMBIE)
.type(EntityType.ZOMBIE_VILLAGER)
.bedrockId(44)
.height(1.8f).width(0.6f)
.offset(1.62f)
.identifier("minecraft:zombie_villager_v2")
@ -643,7 +584,6 @@ public final class EntityDefinitions {
.build();
ZOMBIFIED_PIGLIN = EntityDefinition.inherited(ZombifiedPiglinEntity::new, ZOMBIE) //TODO test how zombie entity metadata is handled?
.type(EntityType.ZOMBIFIED_PIGLIN)
.bedrockId(36)
.height(1.95f).width(0.6f)
.offset(1.62f)
.identifier("minecraft:zombie_pigman")
@ -651,36 +591,30 @@ public final class EntityDefinitions {
DROWNED = EntityDefinition.inherited(ZOMBIE.factory(), ZOMBIE)
.type(EntityType.DROWNED)
.bedrockId(110)
.height(1.95f).width(0.6f)
.build();
HUSK = EntityDefinition.inherited(ZOMBIE.factory(), ZOMBIE)
.type(EntityType.HUSK)
.bedrockId(47)
.build();
GUARDIAN = EntityDefinition.inherited(GuardianEntity::new, mobEntityBase)
.type(EntityType.GUARDIAN)
.bedrockId(49)
.heightAndWidth(0.85f)
.addTranslator(null) // Moving //TODO
.addTranslator(MetadataType.INT, GuardianEntity::setGuardianTarget)
.build();
ELDER_GUARDIAN = EntityDefinition.inherited(ElderGuardianEntity::new, GUARDIAN)
.type(EntityType.ELDER_GUARDIAN)
.bedrockId(50)
.heightAndWidth(1.9975f)
.build();
SLIME = EntityDefinition.inherited(SlimeEntity::new, mobEntityBase)
.type(EntityType.SLIME)
.bedrockId(37)
.heightAndWidth(0.51f)
.addTranslator(MetadataType.INT, SlimeEntity::setScale)
.build();
MAGMA_CUBE = EntityDefinition.inherited(MagmaCubeEntity::new, SLIME)
.type(EntityType.MAGMA_CUBE)
.bedrockId(42)
.build();
EntityDefinition<AbstractFishEntity> abstractFishEntityBase = EntityDefinition.inherited(AbstractFishEntity::new, mobEntityBase)
@ -688,25 +622,22 @@ public final class EntityDefinitions {
.build();
COD = EntityDefinition.inherited(abstractFishEntityBase.factory(), abstractFishEntityBase)
.type(EntityType.COD)
.bedrockId(112)
.height(0.25f).width(0.5f)
.build();
PUFFERFISH = EntityDefinition.inherited(PufferFishEntity::new, abstractFishEntityBase)
.type(EntityType.PUFFERFISH)
.bedrockId(108)
.heightAndWidth(0.7f)
.addTranslator(MetadataType.INT, PufferFishEntity::setPufferfishSize)
.build();
SALMON = EntityDefinition.inherited(abstractFishEntityBase.factory(), abstractFishEntityBase)
.type(EntityType.SALMON)
.bedrockId(109)
.height(0.5f).width(0.7f)
.build();
TROPICAL_FISH = EntityDefinition.inherited(TropicalFishEntity::new, abstractFishEntityBase)
.type(EntityType.TROPICAL_FISH)
.bedrockId(111)
.heightAndWidth(0.6f)
.identifier("minecraft:tropicalfish")
.addTranslator(MetadataType.INT, TropicalFishEntity::setFishVariant)
.build();
EntityDefinition<BasePiglinEntity> abstractPiglinEntityBase = EntityDefinition.inherited(BasePiglinEntity::new, mobEntityBase)
@ -714,7 +645,6 @@ public final class EntityDefinitions {
.build();
PIGLIN = EntityDefinition.inherited(PiglinEntity::new, abstractPiglinEntityBase)
.type(EntityType.PIGLIN)
.bedrockId(123)
.height(1.95f).width(0.6f)
.addTranslator(MetadataType.BOOLEAN, PiglinEntity::setBaby)
.addTranslator(MetadataType.BOOLEAN, PiglinEntity::setChargingCrossbow)
@ -722,7 +652,6 @@ public final class EntityDefinitions {
.build();
PIGLIN_BRUTE = EntityDefinition.inherited(abstractPiglinEntityBase.factory(), abstractPiglinEntityBase)
.type(EntityType.PIGLIN_BRUTE)
.bedrockId(127)
.height(1.95f).width(0.6f)
.build();
@ -739,37 +668,31 @@ public final class EntityDefinitions {
.build();
EVOKER = EntityDefinition.inherited(spellcasterEntityBase.factory(), spellcasterEntityBase)
.type(EntityType.EVOKER)
.bedrockId(104)
.height(1.95f).width(0.6f)
.identifier("minecraft:evocation_illager")
.build();
ILLUSIONER = EntityDefinition.inherited(spellcasterEntityBase.factory(), spellcasterEntityBase)
.type(EntityType.ILLUSIONER)
.bedrockId(104)
.height(1.95f).width(0.6f)
.identifier("minecraft:evocation_illager")
.build();
PILLAGER = EntityDefinition.inherited(PillagerEntity::new, raidParticipantEntityBase)
.type(EntityType.PILLAGER)
.bedrockId(114)
.height(1.8f).width(0.6f)
.offset(1.62f)
.addTranslator(null) // Charging; doesn't have an equivalent on Bedrock //TODO check
.build();
RAVAGER = EntityDefinition.inherited(raidParticipantEntityBase.factory(), raidParticipantEntityBase)
.type(EntityType.RAVAGER)
.bedrockId(59)
.height(1.9f).width(1.2f)
.build();
VINDICATOR = EntityDefinition.inherited(VindicatorEntity::new, raidParticipantEntityBase)
.type(EntityType.VINDICATOR)
.bedrockId(57)
.height(1.8f).width(0.6f)
.offset(1.62f)
.build();
WITCH = EntityDefinition.inherited(raidParticipantEntityBase.factory(), raidParticipantEntityBase)
.type(EntityType.WITCH)
.bedrockId(45)
.height(1.8f).width(0.6f)
.offset(1.62f)
.build();
@ -786,34 +709,30 @@ public final class EntityDefinitions {
.height(0.42f).width(0.7f)
.addTranslator(MetadataType.INT, AxolotlEntity::setVariant)
.addTranslator(MetadataType.BOOLEAN, AxolotlEntity::setPlayingDead)
.addTranslator(null) // From bucket
.build();
BEE = EntityDefinition.inherited(BeeEntity::new, ageableEntityBase)
.type(EntityType.BEE)
.bedrockId(122)
.heightAndWidth(0.6f)
.addTranslator(MetadataType.BYTE, BeeEntity::setBeeFlags)
.addTranslator(MetadataType.INT, BeeEntity::setAngerTime)
.build();
CHICKEN = EntityDefinition.inherited(ChickenEntity::new, ageableEntityBase)
.type(EntityType.CHICKEN)
.bedrockId(10)
.height(0.7f).width(0.4f)
.build();
COW = EntityDefinition.inherited(AnimalEntity::new, ageableEntityBase)
.type(EntityType.COW)
.bedrockId(11)
.height(1.4f).width(0.9f)
.build();
FOX = EntityDefinition.inherited(FoxEntity::new, ageableEntityBase)
.type(EntityType.FOX)
.bedrockId(121)
.height(0.5f).width(1.25f)
.addTranslator(MetadataType.INT, FoxEntity::setFoxVariant)
.addTranslator(MetadataType.BYTE, FoxEntity::setFoxFlags)
.build();
HOGLIN = EntityDefinition.inherited(HoglinEntity::new, ageableEntityBase)
.type(EntityType.HOGLIN)
.bedrockId(124)
.height(1.4f).width(1.3965f)
.addTranslator(MetadataType.BOOLEAN, HoglinEntity::setImmuneToZombification)
.build();
@ -824,19 +743,16 @@ public final class EntityDefinitions {
.build();
MOOSHROOM = EntityDefinition.inherited(MooshroomEntity::new, ageableEntityBase) // TODO remove class
.type(EntityType.MOOSHROOM)
.bedrockId(16)
.height(1.4f).width(0.9f)
.<String>addTranslator(MetadataType.STRING, (entity, entityMetadata) -> entity.getDirtyMetadata().put(EntityData.VARIANT, entityMetadata.getValue().equals("brown") ? 1 : 0))
.build();
OCELOT = EntityDefinition.inherited(OcelotEntity::new, ageableEntityBase)
.type(EntityType.OCELOT)
.bedrockId(22)
.height(0.35f).width(0.3f)
.<Boolean>addTranslator(MetadataType.BOOLEAN, (ocelotEntity, entityMetadata) -> ocelotEntity.setFlag(EntityFlag.TRUSTING, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue()))
.build();
PANDA = EntityDefinition.inherited(PandaEntity::new, ageableEntityBase)
.type(EntityType.PANDA)
.bedrockId(113)
.height(1.25f).width(1.125f)
.addTranslator(null) // Unhappy counter
.addTranslator(null) // Sneeze counter
@ -847,32 +763,27 @@ public final class EntityDefinitions {
.build();
PIG = EntityDefinition.inherited(PigEntity::new, ageableEntityBase)
.type(EntityType.PIG)
.bedrockId(12)
.heightAndWidth(0.9f)
.<Boolean>addTranslator(MetadataType.BOOLEAN, (pigEntity, entityMetadata) -> pigEntity.setFlag(EntityFlag.SADDLED, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue()))
.addTranslator(null) // Boost time
.build();
POLAR_BEAR = EntityDefinition.inherited(PolarBearEntity::new, ageableEntityBase)
.type(EntityType.POLAR_BEAR)
.bedrockId(28)
.height(1.4f).width(1.3f)
.<Boolean>addTranslator(MetadataType.BOOLEAN, (entity, entityMetadata) -> entity.setFlag(EntityFlag.STANDING, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue()))
.build();
RABBIT = EntityDefinition.inherited(RabbitEntity::new, ageableEntityBase)
.type(EntityType.RABBIT)
.bedrockId(18)
.height(0.5f).width(0.4f)
.addTranslator(MetadataType.INT, RabbitEntity::setRabbitVariant)
.build();
SHEEP = EntityDefinition.inherited(SheepEntity::new, ageableEntityBase)
.type(EntityType.SHEEP)
.bedrockId(13)
.heightAndWidth(0.9f)
.addTranslator(MetadataType.BYTE, SheepEntity::setSheepFlags)
.build();
STRIDER = EntityDefinition.inherited(StriderEntity::new, ageableEntityBase)
.type(EntityType.STRIDER)
.bedrockId(125)
.height(1.7f).width(0.9f)
.addTranslator(null) // Boost time
.addTranslator(MetadataType.BOOLEAN, StriderEntity::setCold)
@ -880,7 +791,6 @@ public final class EntityDefinitions {
.build();
TURTLE = EntityDefinition.inherited(TurtleEntity::new, ageableEntityBase)
.type(EntityType.TURTLE)
.bedrockId(74)
.height(0.4f).width(1.2f)
.addTranslator(MetadataType.BOOLEAN, TurtleEntity::setPregnant)
.addTranslator(MetadataType.BOOLEAN, TurtleEntity::setLayingEgg)
@ -891,7 +801,6 @@ public final class EntityDefinitions {
.build();
VILLAGER = EntityDefinition.inherited(VillagerEntity::new, abstractVillagerEntityBase)
.type(EntityType.VILLAGER)
.bedrockId(15)
.height(1.8f).width(0.6f)
.offset(1.62f)
.identifier("minecraft:villager_v2")
@ -899,7 +808,6 @@ public final class EntityDefinitions {
.build();
WANDERING_TRADER = EntityDefinition.inherited(abstractVillagerEntityBase.factory(), abstractVillagerEntityBase)
.type(EntityType.WANDERING_TRADER)
.bedrockId(118)
.height(1.8f).width(0.6f)
.offset(1.62f)
.build();
@ -913,18 +821,15 @@ public final class EntityDefinitions {
.build();
HORSE = EntityDefinition.inherited(HorseEntity::new, abstractHorseEntityBase)
.type(EntityType.HORSE)
.bedrockId(23)
.height(1.6f).width(1.3965f)
.addTranslator(MetadataType.BYTE, HorseEntity::setHorseVariant)
.addTranslator(MetadataType.INT, HorseEntity::setHorseVariant)
.build();
SKELETON_HORSE = EntityDefinition.inherited(abstractHorseEntityBase.factory(), abstractHorseEntityBase)
.type(EntityType.SKELETON_HORSE)
.bedrockId(26)
.height(1.6f).width(1.3965f)
.build();
ZOMBIE_HORSE = EntityDefinition.inherited(abstractHorseEntityBase.factory(), abstractHorseEntityBase)
.type(EntityType.ZOMBIE_HORSE)
.bedrockId(27)
.height(1.6f).width(1.3965f)
.build();
EntityDefinition<ChestedHorseEntity> chestedHorseEntityBase = EntityDefinition.inherited(ChestedHorseEntity::new, abstractHorseEntityBase)
@ -932,17 +837,14 @@ public final class EntityDefinitions {
.build();
DONKEY = EntityDefinition.inherited(chestedHorseEntityBase.factory(), chestedHorseEntityBase)
.type(EntityType.DONKEY)
.bedrockId(24)
.height(1.6f).width(1.3965f)
.build();
MULE = EntityDefinition.inherited(chestedHorseEntityBase.factory(), chestedHorseEntityBase)
.type(EntityType.MULE)
.bedrockId(25)
.height(1.6f).width(1.3965f)
.build();
LLAMA = EntityDefinition.inherited(LlamaEntity::new, chestedHorseEntityBase)
.type(EntityType.LLAMA)
.bedrockId(29)
.height(1.87f).width(0.9f)
.<Integer>addTranslator(MetadataType.INT, (entity, entityMetadata) -> entity.getDirtyMetadata().put(EntityData.STRENGTH, entityMetadata.getValue()))
.addTranslator(MetadataType.INT, LlamaEntity::setCarpetedColor)
@ -960,7 +862,6 @@ public final class EntityDefinitions {
.build();
CAT = EntityDefinition.inherited(CatEntity::new, tameableEntityBase)
.type(EntityType.CAT)
.bedrockId(75)
.height(0.35f).width(0.3f)
.addTranslator(MetadataType.INT, CatEntity::setCatVariant)
.addTranslator(MetadataType.BOOLEAN, CatEntity::setResting)
@ -969,13 +870,11 @@ public final class EntityDefinitions {
.build();
PARROT = EntityDefinition.inherited(ParrotEntity::new, tameableEntityBase)
.type(EntityType.PARROT)
.bedrockId(30)
.height(0.9f).width(0.5f)
.addTranslator(MetadataType.INT, (parrotEntity, entityMetadata) -> parrotEntity.getDirtyMetadata().put(EntityData.VARIANT, entityMetadata.getValue())) // Parrot color
.build();
WOLF = EntityDefinition.inherited(WolfEntity::new, tameableEntityBase)
.type(EntityType.WOLF)
.bedrockId(14)
.height(0.85f).width(0.6f)
// "Begging" on wiki.vg, "Interested" in Nukkit - the tilt of the head
.<Boolean>addTranslator(MetadataType.BOOLEAN, (wolfEntity, entityMetadata) -> wolfEntity.setFlag(EntityFlag.INTERESTED, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue()))
@ -985,9 +884,10 @@ public final class EntityDefinitions {
// As of 1.18 these don't track entity data at all
ENDER_DRAGON_PART = EntityDefinition.<EnderDragonPartEntity>builder(null)
.bedrockId(32)
.identifier("minecraft:armor_stand") // Emulated
.build();
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
}
public static void init() {

View File

@ -31,6 +31,7 @@ import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import com.nukkitx.protocol.bedrock.packet.PlaySoundPacket;
import lombok.Getter;
import org.geysermc.connector.entity.player.PlayerEntity;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.collision.BoundingBox;
@ -46,11 +47,15 @@ import java.util.concurrent.ThreadLocalRandom;
public class FishingHookEntity extends ThrowableEntity {
private boolean hooked = false;
private boolean inWater = false;
@Getter
private final boolean isOwnerSessionPlayer;
@Getter
private long bedrockTargetId;
private final BoundingBox boundingBox;
private boolean inWater = false;
public FishingHookEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, Vector3f position, Vector3f motion, float yaw, float pitch, PlayerEntity owner) {
super(session, entityId, geyserId, uuid, EntityDefinitions.FISHING_BOBBER, position, motion, yaw, pitch, 0f);
@ -59,8 +64,9 @@ public class FishingHookEntity extends ThrowableEntity {
// In Java, the splash sound depends on the entity's velocity, but in Bedrock the volume doesn't change.
// This splash can be confused with the sound from catching a fish. This silences the splash from Bedrock,
// so that it can be handled by moveAbsoluteImmediate.
this.dirtyMetadata.putFloat(EntityData.BOUNDING_BOX_HEIGHT, 128);
setBoundingBoxHeight(128);
isOwnerSessionPlayer = owner.getGeyserId() == session.getPlayerEntity().getGeyserId();
this.dirtyMetadata.put(EntityData.OWNER_EID, owner.getGeyserId());
}
@ -80,7 +86,8 @@ public class FishingHookEntity extends ThrowableEntity {
}
if (entity != null) {
dirtyMetadata.put(EntityData.TARGET_EID, entity.getGeyserId());
bedrockTargetId = entity.getGeyserId();
dirtyMetadata.put(EntityData.TARGET_EID, bedrockTargetId);
hooked = true;
} else {
hooked = false;

View File

@ -23,11 +23,33 @@
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.connector.entity.type;
package org.geysermc.connector.entity;
import lombok.Getter;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityDataMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
@Getter
public enum EntityType {
import java.util.Map;
/**
* A write-only wrapper for temporarily storing entity metadata that will be sent to Bedrock.
*/
public class GeyserDirtyMetadata {
private final Map<EntityData, Object> metadata = new Object2ObjectLinkedOpenHashMap<>();
public void put(EntityData entityData, Object value) {
metadata.put(entityData, value);
}
/**
* Applies the contents of the dirty metadata into the input and clears the contents of our map.
*/
public void apply(EntityDataMap map) {
map.putAll(metadata);
metadata.clear();
}
public boolean hasEntries() {
return !metadata.isEmpty();
}
}

View File

@ -41,7 +41,6 @@ import org.geysermc.connector.network.translators.world.block.BlockStateValues;
import java.util.UUID;
public class ItemEntity extends ThrowableEntity {
protected ItemData item;
private int waterLevel = -1;
@ -63,7 +62,11 @@ public class ItemEntity extends ThrowableEntity {
itemPacket.setMotion(motion);
itemPacket.setFromFishing(false);
itemPacket.setItemInHand(item);
itemPacket.getMetadata().putAll(dirtyMetadata);
itemPacket.getMetadata().putFlags(this.flags);
dirtyMetadata.apply(itemPacket.getMetadata());
setFlagsDirty(false);
session.sendUpstreamPacket(itemPacket);
}

View File

@ -104,7 +104,7 @@ public class ItemFrameEntity extends Entity {
@Override
public void spawnEntity() {
updateBlock();
updateBlock(true);
session.getConnector().getLogger().debug("Spawned item frame at location " + bedrockPosition + " with java id " + entityId);
valid = true;
}
@ -174,14 +174,14 @@ public class ItemFrameEntity extends Entity {
@Override
public void updateBedrockMetadata() {
updateBlock();
updateBlock(false);
}
/**
* Updates the item frame as a block
*/
public void updateBlock() {
if (!changed) {
public void updateBlock(boolean force) {
if (!changed && !force) {
// Don't send a block update packet - nothing changed
return;
}

View File

@ -140,12 +140,8 @@ public class LivingEntity extends Entity {
@Override
protected void setDimensions(Pose pose) {
if (pose == Pose.SLEEPING) {
boundingBoxWidth = 0.2f;
boundingBoxHeight = 0.2f;
if (boundingBoxWidth != definition.width() || boundingBoxHeight != definition.height()) {
dirtyMetadata.put(EntityData.BOUNDING_BOX_WIDTH, boundingBoxWidth);
dirtyMetadata.put(EntityData.BOUNDING_BOX_HEIGHT, boundingBoxHeight);
}
setBoundingBoxWidth(0.2f);
setBoundingBoxHeight(0.2f);
} else {
super.setDimensions(pose);
}

View File

@ -294,8 +294,7 @@ public class ArmorStandEntity extends LivingEntity {
}
return;
}
//boolean isNametagEmpty = metadata.getString(EntityData.NAMETAG).isEmpty() || metadata.getByte(EntityData.NAMETAG_ALWAYS_SHOW, (byte) -1) == (byte) 0; - may not be necessary?
boolean isNametagEmpty = dirtyMetadata.getString(EntityData.NAMETAG).isEmpty(); // TODO
boolean isNametagEmpty = nametag.isEmpty();
if (!isNametagEmpty && (!helmet.equals(ItemData.AIR) || !chestplate.equals(ItemData.AIR) || !leggings.equals(ItemData.AIR)
|| !boots.equals(ItemData.AIR) || !hand.equals(ItemData.AIR) || !offHand.equals(ItemData.AIR))) {
// If the second entity exists, no need to recreate it.
@ -313,7 +312,7 @@ public class ArmorStandEntity extends LivingEntity {
}
// Copy metadata
secondEntity.isSmall = isSmall;
secondEntity.getDirtyMetadata().putAll(dirtyMetadata); //TODO check
//secondEntity.getDirtyMetadata().putAll(dirtyMetadata); //TODO check
secondEntity.flags.merge(this.flags);
// Guarantee this copy is NOT invisible
secondEntity.setFlag(EntityFlag.INVISIBLE, false);

View File

@ -44,7 +44,7 @@ public class AnimalEntity extends AgeableEntity {
* <code>wheat</code>.
* @return true if this is a valid item to breed with for this animal.
*/
public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemMapping mapping) {
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
// This is what it defaults to. OK.
return javaIdentifierStripped.equals("wheat");
}

View File

@ -56,7 +56,7 @@ public class AxolotlEntity extends AnimalEntity {
}
@Override
public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemMapping mapping) {
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return javaIdentifierStripped.equals("tropical_fish_bucket");
}

View File

@ -67,7 +67,7 @@ public class BeeEntity extends AnimalEntity {
}
@Override
public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemMapping mapping) {
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return session.getTagCache().isFlower(mapping);
}
}

View File

@ -39,7 +39,7 @@ public class ChickenEntity extends AnimalEntity {
}
@Override
public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemMapping mapping) {
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return javaIdentifierStripped.contains("seeds");
}
}

View File

@ -55,7 +55,7 @@ public class FoxEntity extends AnimalEntity {
}
@Override
public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemMapping mapping) {
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return session.getTagCache().isFoxFood(mapping);
}
}

View File

@ -29,7 +29,6 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadat
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import lombok.Getter;
import org.geysermc.connector.entity.EntityDefinition;
import org.geysermc.connector.network.session.GeyserSession;
@ -55,8 +54,8 @@ public class GoatEntity extends AnimalEntity {
@Override
protected void setDimensions(Pose pose) {
if (pose == Pose.LONG_JUMPING) {
dirtyMetadata.put(EntityData.BOUNDING_BOX_WIDTH, LONG_JUMPING_WIDTH);
dirtyMetadata.put(EntityData.BOUNDING_BOX_HEIGHT, LONG_JUMPING_HEIGHT);
setBoundingBoxWidth(LONG_JUMPING_WIDTH);
setBoundingBoxHeight(LONG_JUMPING_HEIGHT);
} else {
super.setDimensions(pose);
}

View File

@ -55,7 +55,7 @@ public class HoglinEntity extends AnimalEntity {
}
@Override
public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemMapping mapping) {
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return javaIdentifierStripped.equals("crimson_fungus");
}
}

View File

@ -39,7 +39,7 @@ public class OcelotEntity extends AnimalEntity {
}
@Override
public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemMapping mapping) {
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return javaIdentifierStripped.equals("cod") || javaIdentifierStripped.equals("salmon");
}
}

View File

@ -83,7 +83,7 @@ public class PandaEntity extends AnimalEntity {
}
@Override
public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemMapping mapping) {
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return javaIdentifierStripped.equals("bamboo");
}

View File

@ -39,7 +39,7 @@ public class PigEntity extends AnimalEntity {
}
@Override
public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemMapping mapping) {
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return javaIdentifierStripped.equals("carrot") || javaIdentifierStripped.equals("potato") || javaIdentifierStripped.equals("beetroot");
}
}

View File

@ -39,7 +39,7 @@ public class PolarBearEntity extends AnimalEntity {
}
@Override
public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemMapping mapping) {
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return false;
}
}

View File

@ -72,7 +72,7 @@ public class RabbitEntity extends AnimalEntity {
}
@Override
public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemMapping mapping) {
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return javaIdentifierStripped.equals("dandelion") || javaIdentifierStripped.equals("carrot") || javaIdentifierStripped.equals("golden_carrot");
}
}

View File

@ -93,7 +93,7 @@ public class StriderEntity extends AnimalEntity {
}
@Override
public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemMapping mapping) {
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return javaIdentifierStripped.equals("warped_fungus");
}
}

View File

@ -50,7 +50,7 @@ public class TurtleEntity extends AnimalEntity {
}
@Override
public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemMapping mapping) {
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return javaIdentifierStripped.equals("seagrass");
}
}

View File

@ -120,7 +120,7 @@ public class AbstractHorseEntity extends AnimalEntity {
}
@Override
public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemMapping mapping) {
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return DONKEY_AND_HORSE_FOODS.contains(javaIdentifierStripped);
}
}

View File

@ -70,7 +70,7 @@ public class LlamaEntity extends ChestedHorseEntity {
}
@Override
public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemMapping mapping) {
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return javaIdentifierStripped.equals("wheat") || javaIdentifierStripped.equals("hay_block");
}
}

View File

@ -95,7 +95,7 @@ public class CatEntity extends TameableEntity {
}
@Override
public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemMapping mapping) {
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return javaIdentifierStripped.equals("cod") || javaIdentifierStripped.equals("salmon");
}
}

View File

@ -39,7 +39,7 @@ public class ParrotEntity extends TameableEntity {
}
@Override
public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemMapping mapping) {
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return javaIdentifierStripped.contains("seeds") || javaIdentifierStripped.equals("cookie");
}
}

View File

@ -56,7 +56,7 @@ public class WolfEntity extends TameableEntity {
@Override
public void setTameableFlags(EntityMetadata<Byte> entityMetadata) {
super.setFlags(entityMetadata);
super.setTameableFlags(entityMetadata);
// Reset wolf color
byte xd = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
boolean angry = (xd & 0x02) == 0x02;
@ -87,8 +87,8 @@ public class WolfEntity extends TameableEntity {
}
@Override
public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemMapping mapping) {
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
// Cannot be a baby to eat these foods
return WOLF_FOODS.contains(javaIdentifierStripped) && !getFlag(EntityFlag.BABY);
return WOLF_FOODS.contains(javaIdentifierStripped) && !isBaby();
}
}

View File

@ -29,7 +29,6 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadat
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.LevelEventType;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityEventType;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import com.nukkitx.protocol.bedrock.packet.*;
@ -237,7 +236,7 @@ public class EnderDragonEntity extends MobEntity implements Tickable {
phaseTicks++;
if (phase == 3) { // Landing Phase
float headHeight = head.getDirtyMetadata().getFloat(EntityData.BOUNDING_BOX_HEIGHT); //TODO
float headHeight = head.getBoundingBoxHeight();
Vector3f headCenter = head.getPosition().up(headHeight * 0.5f);
for (int i = 0; i < 8; i++) {

View File

@ -44,7 +44,7 @@ public class SpellcasterIllagerEntity extends AbstractIllagerEntity {
public SpellcasterIllagerEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
// OptionalPack usage
dirtyMetadata.getFlags().setFlag(EntityFlag.BRIBED, this.definition == EntityDefinitions.ILLUSIONER);
setFlag(EntityFlag.BRIBED, this.definition == EntityDefinitions.ILLUSIONER);
}
public void setSpellType(EntityMetadata<Byte> entityMetadata) {

View File

@ -28,6 +28,7 @@ package org.geysermc.connector.entity.player;
import com.github.steveice10.mc.auth.data.GameProfile;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.FloatEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.scoreboard.ScoreboardPosition;
@ -67,6 +68,8 @@ public class PlayerEntity extends LivingEntity {
private String username;
private boolean playerList = true; // Player is in the player list
private Vector3i bedPosition;
/**
* Saves the parrot currently on the player's left shoulder; otherwise null
*/
@ -114,10 +117,9 @@ public class PlayerEntity extends LivingEntity {
addPlayerPacket.getAdventureSettings().setPlayerPermission(PlayerPermission.MEMBER);
addPlayerPacket.setDeviceId("");
addPlayerPacket.setPlatformChatId("");
addPlayerPacket.getMetadata().putAll(dirtyMetadata);
addPlayerPacket.getMetadata().putFlags(flags);
dirtyMetadata.apply(addPlayerPacket.getMetadata());
dirtyMetadata.clear();
setFlagsDirty(false);
long linkedEntityId = session.getEntityCache().getCachedPlayerEntityLink(entityId);
@ -189,8 +191,7 @@ public class PlayerEntity extends LivingEntity {
movePlayerPacket.setMode(MovePlayerPacket.Mode.NORMAL);
// If the player is moved while sleeping, we have to adjust their y, so it appears
// correctly on Bedrock. This fixes GSit's lay.
if (dirtyMetadata.getFlags().getFlag(EntityFlag.SLEEPING)) {
Vector3i bedPosition = dirtyMetadata.getPos(EntityData.BED_POSITION);
if (getFlag(EntityFlag.SLEEPING)) {
if (bedPosition != null && (bedPosition.getY() == 0 || bedPosition.distanceSquared(position.toInt()) > 4)) {
// Force the player movement by using a teleport
movePlayerPacket.setPosition(Vector3f.from(position.getX(), position.getY() - definition.offset() + 0.2f, position.getZ()));
@ -253,6 +254,11 @@ public class PlayerEntity extends LivingEntity {
super.setPosition(position.add(0, definition.offset(), 0));
}
@Override
public Vector3i setBedPosition(EntityMetadata<Position> entityMetadata) {
return bedPosition = super.setBedPosition(entityMetadata);
}
public void setAbsorptionHearts(EntityMetadata<Float> entityMetadata) {
// Extra hearts - is not metadata but an attribute on Bedrock
UpdateAttributesPacket attributesPacket = new UpdateAttributesPacket();
@ -358,11 +364,12 @@ public class PlayerEntity extends LivingEntity {
// The name is not visible to the session player; clear name
newDisplayName = "";
}
needsUpdate = useGivenTeam && !newDisplayName.equals(dirtyMetadata.getString(EntityData.NAMETAG, null));
needsUpdate = useGivenTeam && !newDisplayName.equals(nametag);
nametag = newDisplayName;
dirtyMetadata.put(EntityData.NAMETAG, newDisplayName);
} else if (useGivenTeam) {
// The name has reset, if it was previously something else
needsUpdate = !newDisplayName.equals(dirtyMetadata.getString(EntityData.NAMETAG));
needsUpdate = !newDisplayName.equals(nametag);
dirtyMetadata.put(EntityData.NAMETAG, this.username);
} else {
needsUpdate = false;
@ -393,10 +400,8 @@ public class PlayerEntity extends LivingEntity {
return;
}
}
if (height != boundingBoxHeight || definition.width() != boundingBoxWidth) {
dirtyMetadata.put(EntityData.BOUNDING_BOX_WIDTH, definition.width());
dirtyMetadata.put(EntityData.BOUNDING_BOX_HEIGHT, height);
}
setBoundingBoxWidth(definition.width());
setBoundingBoxHeight(height);
}
public void setBelowNameText(Objective objective) {
@ -410,7 +415,6 @@ public class PlayerEntity extends LivingEntity {
}
String displayString = amount + " " + objective.getDisplayName();
dirtyMetadata.put(EntityData.SCORE_TAG, displayString);
if (valid) {
// Already spawned - we still need to run the rest of this code because the spawn packet will be
// providing the information
@ -419,15 +423,11 @@ public class PlayerEntity extends LivingEntity {
packet.getMetadata().put(EntityData.SCORE_TAG, displayString);
session.sendUpstreamPacket(packet);
}
} else {
// Always remove the score tag first, then check for valid.
// That way the score tag is removed if the player was spawned, then despawned, and is being respawned
if (dirtyMetadata.remove(EntityData.SCORE_TAG) != null && valid) {
SetEntityDataPacket packet = new SetEntityDataPacket();
packet.setRuntimeEntityId(geyserId);
packet.getMetadata().put(EntityData.SCORE_TAG, "");
session.sendUpstreamPacket(packet);
}
} else if (valid) {
SetEntityDataPacket packet = new SetEntityDataPacket();
packet.setRuntimeEntityId(geyserId);
packet.getMetadata().put(EntityData.SCORE_TAG, "");
session.sendUpstreamPacket(packet);
}
}
}

View File

@ -33,6 +33,7 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.AttributeData;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import com.nukkitx.protocol.bedrock.packet.UpdateAttributesPacket;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
@ -59,6 +60,15 @@ public class SessionPlayerEntity extends PlayerEntity {
* Whether to check for updated speed after all entity metadata has been processed
*/
private boolean refreshSpeed = false;
/**
* Used in PlayerInputTranslator for movement checks.
*/
@Getter
private boolean isRidingInFront;
/**
* Used for villager inventory emulation.
*/
private int fakeTradeXp;
private final GeyserSession session;
@ -130,6 +140,17 @@ public class SessionPlayerEntity extends PlayerEntity {
}
}
@Override
public void setRiderSeatPosition(Vector3f position) {
super.setRiderSeatPosition(position);
this.isRidingInFront = position != null && position.getX() > 0;
}
public void addFakeTradeExperience(int tradeXp) {
fakeTradeXp += tradeXp;
dirtyMetadata.put(EntityData.TRADE_XP, fakeTradeXp);
}
@Override
public AttributeData createHealthAttribute() {
// Max health must be divisible by two in bedrock

View File

@ -83,10 +83,9 @@ public class SkullPlayerEntity extends PlayerEntity {
addPlayerPacket.getAdventureSettings().setPlayerPermission(PlayerPermission.MEMBER);
addPlayerPacket.setDeviceId("");
addPlayerPacket.setPlatformChatId("");
addPlayerPacket.getMetadata().putAll(dirtyMetadata);
addPlayerPacket.getMetadata().putFlags(flags);
dirtyMetadata.apply(addPlayerPacket.getMetadata());
dirtyMetadata.clear();
setFlagsDirty(false);
valid = true;

View File

@ -1072,7 +1072,7 @@ public class GeyserSession implements CommandSender {
AttributeData currentPlayerSpeed = playerEntity.getAttributes().get(GeyserAttributeType.MOVEMENT_SPEED);
if (currentPlayerSpeed != null) {
if ((pose.equals(Pose.SNEAKING) && !sneaking && collisionManager.isUnderSlab()) ||
(!swimmingInWater && playerEntity.getDirtyMetadata().getFlags().getFlag(EntityFlag.SWIMMING) && !collisionManager.isPlayerInWater())) {
(!swimmingInWater && playerEntity.getFlag(EntityFlag.SWIMMING) && !collisionManager.isPlayerInWater())) {
// Either of those conditions means that Bedrock goes zoom when they shouldn't be
AttributeData speedAttribute = GeyserAttributeType.MOVEMENT_SPEED.getAttribute(originalSpeedAttribute / 3.32f);
playerEntity.getAttributes().put(GeyserAttributeType.MOVEMENT_SPEED, speedAttribute);

View File

@ -50,7 +50,7 @@ public class BedrockAdventureSettingsTranslator extends PacketTranslator<Adventu
ServerboundPlayerAbilitiesPacket abilitiesPacket = new ServerboundPlayerAbilitiesPacket(isFlying);
session.sendDownstreamPacket(abilitiesPacket);
if (isFlying && session.getPlayerEntity().getDirtyMetadata().getFlags().getFlag(EntityFlag.SWIMMING)) {
if (isFlying && session.getPlayerEntity().getFlag(EntityFlag.SWIMMING)) {
// Bedrock can fly and swim at the same time? Make sure that can't happen
session.setSwimming(false);
}

View File

@ -28,7 +28,6 @@ package org.geysermc.connector.network.translators.bedrock;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.level.ServerboundMoveVehiclePacket;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.level.ServerboundPlayerInputPacket;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.packet.PlayerInputPacket;
import org.geysermc.connector.entity.BoatEntity;
import org.geysermc.connector.entity.Entity;
@ -65,8 +64,7 @@ public class BedrockPlayerInputTranslator extends PacketTranslator<PlayerInputPa
sendMovement = true;
} else {
// Check if the player is the front rider
Vector3f seatPos = session.getPlayerEntity().getDirtyMetadata().getVector3f(EntityData.RIDER_SEAT_POSITION, null);
if (seatPos != null && seatPos.getX() > 0) {
if (session.getPlayerEntity().isRidingInFront()) {
sendMovement = true;
}
}

View File

@ -30,7 +30,6 @@ import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundCl
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.packet.MovePlayerPacket;
import com.nukkitx.protocol.bedrock.packet.RespawnPacket;
import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket;
import org.geysermc.connector.entity.player.PlayerEntity;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.PacketTranslator;
@ -54,11 +53,7 @@ public class BedrockRespawnTranslator extends PacketTranslator<RespawnPacket> {
if (session.isSpawned()) {
// Client might be stuck; resend spawn information
PlayerEntity entity = session.getPlayerEntity();
if (entity == null) return;
SetEntityDataPacket entityDataPacket = new SetEntityDataPacket();
entityDataPacket.setRuntimeEntityId(entity.getGeyserId());
entityDataPacket.getMetadata().putAll(entity.getDirtyMetadata());
session.sendUpstreamPacket(entityDataPacket);
entity.updateBedrockMetadata(); // TODO test?
MovePlayerPacket movePlayerPacket = new MovePlayerPacket();
movePlayerPacket.setRuntimeEntityId(entity.getGeyserId());

View File

@ -27,9 +27,8 @@ package org.geysermc.connector.network.translators.bedrock.entity;
import com.github.steveice10.mc.protocol.data.game.inventory.VillagerTrade;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundSelectTradePacket;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.packet.EntityEventPacket;
import org.geysermc.connector.entity.Entity;
import org.geysermc.connector.entity.player.SessionPlayerEntity;
import org.geysermc.connector.inventory.GeyserItemStack;
import org.geysermc.connector.inventory.Inventory;
import org.geysermc.connector.inventory.MerchantContainer;
@ -55,14 +54,15 @@ public class BedrockEntityEventTranslator extends PacketTranslator<EntityEventPa
session.sendDownstreamPacket(selectTradePacket);
session.scheduleInEventLoop(() -> {
Entity villager = session.getPlayerEntity();
SessionPlayerEntity villager = session.getPlayerEntity();
Inventory openInventory = session.getOpenInventory();
if (openInventory instanceof MerchantContainer merchantInventory) {
VillagerTrade[] trades = merchantInventory.getVillagerTrades();
if (trades != null && packet.getData() >= 0 && packet.getData() < trades.length) {
VillagerTrade trade = merchantInventory.getVillagerTrades()[packet.getData()];
openInventory.setItem(2, GeyserItemStack.from(trade.getOutput()), session);
villager.getDirtyMetadata().put(EntityData.TRADE_XP, trade.getXp() + villager.getDirtyMetadata().getInt(EntityData.TRADE_XP));
// TODO this logic doesn't add up
villager.addFakeTradeExperience(trade.getXp());
villager.updateBedrockMetadata();
}
}

View File

@ -116,7 +116,7 @@ public class BedrockActionTranslator extends PacketTranslator<PlayerActionPacket
useItemPacket = new ServerboundUseItemPacket(Hand.OFF_HAND);
}
session.sendDownstreamPacket(useItemPacket);
session.getPlayerEntity().getDirtyMetadata().getFlags().setFlag(EntityFlag.BLOCKING, true);
session.getPlayerEntity().setFlag(EntityFlag.BLOCKING, true);
// metadata will be updated when sneaking
}
@ -127,10 +127,10 @@ public class BedrockActionTranslator extends PacketTranslator<PlayerActionPacket
session.sendDownstreamPacket(stopSneakPacket);
// Stop shield, if necessary
if (session.getPlayerEntity().getDirtyMetadata().getFlags().getFlag(EntityFlag.BLOCKING)) {
if (session.getPlayerEntity().getFlag(EntityFlag.BLOCKING)) {
ServerboundPlayerActionPacket releaseItemPacket = new ServerboundPlayerActionPacket(PlayerAction.RELEASE_USE_ITEM, BlockUtils.POSITION_ZERO, Direction.DOWN);
session.sendDownstreamPacket(releaseItemPacket);
session.getPlayerEntity().getDirtyMetadata().getFlags().setFlag(EntityFlag.BLOCKING, false);
session.getPlayerEntity().setFlag(EntityFlag.BLOCKING, false);
// metadata will be updated when sneaking
}

View File

@ -99,7 +99,7 @@ public class BedrockInteractTranslator extends PacketTranslator<InteractPacket>
if (session.getOpenInventory() == null) {
Entity ridingEntity = session.getRidingVehicleEntity();
if (ridingEntity instanceof AbstractHorseEntity) {
if (ridingEntity.getDirtyMetadata().getFlags().getFlag(EntityFlag.TAMED)) {
if (ridingEntity.getFlag(EntityFlag.TAMED)) {
// We should request to open the horse inventory instead
ServerboundPlayerCommandPacket openHorseWindowPacket = new ServerboundPlayerCommandPacket((int) session.getPlayerEntity().getEntityId(), PlayerState.OPEN_HORSE_INVENTORY);
session.sendDownstreamPacket(openHorseWindowPacket);

View File

@ -28,10 +28,8 @@ package org.geysermc.connector.network.translators.collision;
import com.nukkitx.math.vector.Vector3d;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import com.nukkitx.protocol.bedrock.packet.MovePlayerPacket;
import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket;
import lombok.Getter;
import lombok.Setter;
import org.geysermc.connector.entity.Entity;
@ -121,7 +119,7 @@ public class CollisionManager {
// - In Bedrock Edition, the height becomes 1.65 blocks, allowing movement through spaces as small as 1.75 (2 - 14) blocks high.
// - In Java Edition, the height becomes 1.5 blocks.
// Other instances have the player's bounding box become as small as 0.6 or 0.2.
double playerHeight = session.getPlayerEntity().getDirtyMetadata().getFloat(EntityData.BOUNDING_BOX_HEIGHT);
double playerHeight = session.getPlayerEntity().getBoundingBoxHeight();
playerBoundingBox.setMiddleY(playerBoundingBox.getMiddleY() - (playerBoundingBox.getSizeY() / 2.0) + (playerHeight / 2.0));
playerBoundingBox.setSizeY(playerHeight);
}
@ -188,10 +186,7 @@ public class CollisionManager {
public void recalculatePosition() {
PlayerEntity entity = session.getPlayerEntity();
// Gravity might need to be reset...
SetEntityDataPacket entityDataPacket = new SetEntityDataPacket();
entityDataPacket.setRuntimeEntityId(entity.getGeyserId());
entityDataPacket.getMetadata().putAll(entity.getDirtyMetadata());
session.sendUpstreamPacket(entityDataPacket);
entity.updateBedrockMetadata(); // TODO may not be necessary
MovePlayerPacket movePlayerPacket = new MovePlayerPacket();
movePlayerPacket.setRuntimeEntityId(entity.getGeyserId());

View File

@ -220,7 +220,7 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
case BLOCK_STATE -> BlockRegistries.JAVA_TO_BEDROCK_IDENTIFIERS.get().keySet().toArray(new String[0]);
case ITEM_STACK -> session.getItemMappings().getItemNames();
case ITEM_ENCHANTMENT -> Enchantment.JavaEnchantment.ALL_JAVA_IDENTIFIERS;
case ENTITY_SUMMON -> Registries.JAVA_ENTITY_IDENTIFIERS.get().keySet().toArray(new String[0]); //TODO add Marker
case ENTITY_SUMMON -> Registries.JAVA_ENTITY_IDENTIFIERS.get().keySet().toArray(new String[0]);
case COLOR -> VALID_COLORS;
case SCOREBOARD_SLOT -> VALID_SCOREBOARD_SLOTS;
case MOB_EFFECT -> ALL_EFFECT_IDENTIFIERS;

View File

@ -90,10 +90,7 @@ public class JavaLoginTranslator extends PacketTranslator<ClientboundLoginPacket
session.sendUpstreamPacket(playerGameTypePacket);
}
SetEntityDataPacket entityDataPacket = new SetEntityDataPacket();
entityDataPacket.setRuntimeEntityId(entity.getGeyserId());
entityDataPacket.getMetadata().putAll(entity.getDirtyMetadata());
session.sendUpstreamPacket(entityDataPacket);
entity.updateBedrockMetadata();
// Send if client should show respawn screen
GameRulesChangedPacket gamerulePacket = new GameRulesChangedPacket();

View File

@ -34,6 +34,7 @@ import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
import com.nukkitx.protocol.bedrock.packet.*;
import org.geysermc.connector.entity.Entity;
import org.geysermc.connector.entity.EntityDefinitions;
import org.geysermc.connector.entity.FishingHookEntity;
import org.geysermc.connector.entity.LivingEntity;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.PacketTranslator;
@ -122,9 +123,9 @@ public class JavaEntityEventTranslator extends PacketTranslator<ClientboundEntit
case FISHING_HOOK_PULL_PLAYER:
// Player is pulled from a fishing rod
// The physics of this are clientside on Java
long pulledById = entity.getDirtyMetadata().getLong(EntityData.TARGET_EID);
if (session.getPlayerEntity().getGeyserId() == pulledById) {
Entity hookOwner = session.getEntityCache().getEntityByGeyserId(entity.getDirtyMetadata().getLong(EntityData.OWNER_EID));
FishingHookEntity fishingHook = (FishingHookEntity) entity;
if (fishingHook.isOwnerSessionPlayer()) {
Entity hookOwner = session.getEntityCache().getEntityByGeyserId(fishingHook.getBedrockTargetId());
if (hookOwner != null) {
// https://minecraft.gamepedia.com/Fishing_Rod#Hooking_mobs_and_other_entities
SetEntityMotionPacket motionPacket = new SetEntityMotionPacket();

View File

@ -33,7 +33,6 @@ import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.PacketTranslator;
import org.geysermc.connector.network.translators.Translator;
import org.geysermc.connector.utils.InteractiveTagManager;
import org.geysermc.connector.utils.LanguageUtils;
import java.util.List;
@ -61,16 +60,19 @@ public class JavaSetEntityDataTranslator extends PacketTranslator<ClientboundSet
continue;
}
EntityMetadataTranslator<? super Entity, ?> translator = (EntityMetadataTranslator<? super Entity, ?>) translators.get(metadata.getId());
EntityMetadataTranslator<? super Entity, Object> translator = (EntityMetadataTranslator<? super Entity, Object>) translators.get(metadata.getId());
if (translator == null) {
// This can safely happen; it means we don't translate this entity metadata
continue;
}
if (translator.acceptedType() != metadata.getType()) {
session.getConnector().getLogger().warning("Metadata ID " + metadata.getId() + " was received with type " + metadata.getType() + " but we expected " + translator.acceptedType() + " for " + entity.getDefinition().entityType());
if (session.getConnector().getConfig().isDebugMode()) {
session.getConnector().getLogger().debug(metadata.toString());
}
continue;
}
translator.translateFunction().accept(entity, metadata);
translator.translateFunction().accept(entity, (EntityMetadata<Object>) metadata);
}
entity.updateBedrockMetadata();

View File

@ -33,7 +33,6 @@ import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityLinkData;
import com.nukkitx.protocol.bedrock.packet.MovePlayerPacket;
import com.nukkitx.protocol.bedrock.packet.RespawnPacket;
import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket;
import com.nukkitx.protocol.bedrock.packet.SetEntityLinkPacket;
import org.geysermc.connector.entity.Entity;
import org.geysermc.connector.entity.EntityDefinitions;
@ -69,10 +68,7 @@ public class JavaPlayerPositionTranslator extends PacketTranslator<ClientboundPl
respawnPacket.setState(RespawnPacket.State.SERVER_READY);
session.sendUpstreamPacket(respawnPacket);
SetEntityDataPacket entityDataPacket = new SetEntityDataPacket();
entityDataPacket.setRuntimeEntityId(entity.getGeyserId());
entityDataPacket.getMetadata().putAll(entity.getDirtyMetadata());
session.sendUpstreamPacket(entityDataPacket);
entity.updateBedrockMetadata();
MovePlayerPacket movePlayerPacket = new MovePlayerPacket();
movePlayerPacket.setRuntimeEntityId(entity.getGeyserId());

View File

@ -29,7 +29,6 @@ import com.github.steveice10.mc.protocol.packet.ingame.clientbound.inventory.Cli
import com.nukkitx.nbt.NbtMap;
import com.nukkitx.nbt.NbtMapBuilder;
import com.nukkitx.nbt.NbtType;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
import com.nukkitx.protocol.bedrock.packet.UpdateEquipPacket;
import org.geysermc.connector.entity.Entity;
@ -132,6 +131,6 @@ public class JavaHorseScreenOpenTranslator extends PacketTranslator<ClientboundH
session.sendUpstreamPacket(updateEquipPacket);
session.setInventoryTranslator(inventoryTranslator);
InventoryUtils.openInventory(session, new Container(entity.getDirtyMetadata().getString(EntityData.NAMETAG), packet.getContainerId(), packet.getNumberOfSlots(), null, session.getPlayerInventory()));
InventoryUtils.openInventory(session, new Container(entity.getNametag(), packet.getContainerId(), packet.getNumberOfSlots(), null, session.getPlayerInventory()));
}
}

View File

@ -49,6 +49,7 @@ import io.netty.buffer.ByteBufOutputStream;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import it.unimi.dsi.fastutil.ints.IntLists;
import org.geysermc.connector.entity.ItemFrameEntity;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.PacketTranslator;
import org.geysermc.connector.network.translators.Translator;
@ -68,9 +69,7 @@ import org.geysermc.connector.utils.ChunkUtils;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;
import java.util.*;
import static org.geysermc.connector.utils.ChunkUtils.*;
@ -85,11 +84,12 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
// Ensure that, if the player is using lower world heights, the position is not offset
int yOffset = session.getChunkCache().getChunkMinY();
int chunkSize = session.getChunkCache().getChunkHeightY();
// Temporarily stores compound tags of Bedrock-only block entities
List<NbtMap> bedrockOnlyBlockEntities = new ArrayList<>();
DataPalette[] javaChunks = new DataPalette[session.getChunkCache().getChunkHeightY()];
DataPalette[] javaBiomes = new DataPalette[session.getChunkCache().getChunkHeightY()];
DataPalette[] javaChunks = new DataPalette[chunkSize];
DataPalette[] javaBiomes = new DataPalette[chunkSize];
BitSet waterloggedPaletteIds = new BitSet();
BitSet pistonOrFlowerPaletteIds = new BitSet();
@ -100,21 +100,21 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
int sectionCount;
byte[] payload;
ByteBuf byteBuf = null;
GeyserChunkSection[] sections = new GeyserChunkSection[javaChunks.length - yOffset];
GeyserChunkSection[] sections = new GeyserChunkSection[javaChunks.length - (yOffset + ((overworld ? MINIMUM_ACCEPTED_HEIGHT_OVERWORLD : MINIMUM_ACCEPTED_HEIGHT) >> 4))];
try {
NetInput in = new StreamNetInput(new ByteArrayInputStream(packet.getChunkData()));
for (int sectionY = 0; sectionY < session.getChunkCache().getChunkHeightY(); sectionY++) {
for (int sectionY = 0; sectionY < chunkSize; sectionY++) {
ChunkSection javaSection = ChunkSection.read(in);
javaChunks[sectionY] = javaSection.getChunkData();
javaBiomes[sectionY] = javaSection.getBiomeData();
int bedrockSectionY = sectionY + (yOffset - ((overworld ? MINIMUM_ACCEPTED_HEIGHT_OVERWORLD : MINIMUM_ACCEPTED_HEIGHT) >> 4));
if (bedrockSectionY < 0 || maxBedrockSectionY < bedrockSectionY) {
// Ignore this chunk section since it goes outside the bounds accepted by the Bedrock client
continue;
}
ChunkSection javaSection = ChunkSection.read(in);
javaChunks[sectionY] = javaSection.getChunkData();
javaBiomes[sectionY] = javaSection.getBiomeData();
// No need to encode an empty section...
if (javaSection.isBlockCountEmpty()) {
continue;
@ -316,11 +316,11 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
for (int i = 0; i < sectionCount; i++) {
int biomeYOffset = dimensionOffset + i;
if (biomeYOffset < yOffset) {
// Ignore this biome section since it goes below the height of the Java world
// Ignore this biome section since it goes above or below the height of the Java world
byteBuf.writeBytes(ChunkUtils.EMPTY_BIOME_DATA);
continue;
}
BiomeTranslator.toNewBedrockBiome(session, javaBiomes[i]).writeToNetwork(byteBuf);
BiomeTranslator.toNewBedrockBiome(session, javaBiomes[i + (dimensionOffset - yOffset)]).writeToNetwork(byteBuf);
}
// As of 1.17.10, Bedrock hardcodes to always read 32 biome sections
@ -356,5 +356,14 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
levelChunkPacket.setChunkZ(packet.getZ());
levelChunkPacket.setData(payload);
session.sendUpstreamPacket(levelChunkPacket);
for (Map.Entry<Vector3i, ItemFrameEntity> entry : session.getItemFrameCache().entrySet()) {
Vector3i position = entry.getKey();
if ((position.getX() >> 4) == packet.getX() && (position.getZ() >> 4) == packet.getZ()) {
// Update this item frame so it doesn't get lost in the abyss
//TODO optimize
entry.getValue().updateBlock(true);
}
}
}
}

View File

@ -136,18 +136,18 @@ public class JavaLevelParticlesTranslator extends PacketTranslator<ClientboundLe
return null;
}
if (particleMapping.getLevelEventType() != null) {
if (particleMapping.levelEventType() != null) {
return (position) -> {
LevelEventPacket packet = new LevelEventPacket();
packet.setType(particleMapping.getLevelEventType());
packet.setType(particleMapping.levelEventType());
packet.setPosition(position);
return packet;
};
} else if (particleMapping.getIdentifier() != null) {
} else if (particleMapping.identifier() != null) {
int dimensionId = DimensionUtils.javaToBedrock(session.getDimension());
return (position) -> {
SpawnParticleEffectPacket stringPacket = new SpawnParticleEffectPacket();
stringPacket.setIdentifier(particleMapping.getIdentifier());
stringPacket.setIdentifier(particleMapping.identifier());
stringPacket.setDimensionId(dimensionId);
stringPacket.setPosition(position);
return stringPacket;

View File

@ -27,7 +27,6 @@ package org.geysermc.connector.network.translators.sound.entity;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityEventType;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import com.nukkitx.protocol.bedrock.packet.EntityEventPacket;
import org.geysermc.connector.entity.Entity;
import org.geysermc.connector.entity.living.animal.AnimalEntity;
@ -42,10 +41,10 @@ public class FeedBabySoundInteractionHandler implements EntitySoundInteractionHa
@Override
public void handleInteraction(GeyserSession session, Vector3f position, Entity entity) {
if (entity instanceof AnimalEntity && !(entity instanceof CatEntity || entity instanceof OcelotEntity)) {
if (entity instanceof AnimalEntity animalEntity && !(entity instanceof CatEntity || entity instanceof OcelotEntity)) {
String handIdentifier = session.getPlayerInventory().getItemInHand().getMapping(session).getJavaIdentifier();
boolean isBaby = entity.getDirtyMetadata().getFlags().getFlag(EntityFlag.BABY);
if (isBaby && ((AnimalEntity) entity).canEat(session, handIdentifier.replace("minecraft:", ""),
boolean isBaby = animalEntity.isBaby();
if (isBaby && animalEntity.canEat(handIdentifier.replace("minecraft:", ""),
session.getPlayerInventory().getItemInHand().getMapping(session))) {
// Play the "feed child" effect
EntityEventPacket feedEvent = new EntityEventPacket();

View File

@ -43,7 +43,7 @@ public class MilkEntitySoundInteractionHandler implements EntitySoundInteraction
if (!session.getPlayerInventory().getItemInHand().getMapping(session).getJavaIdentifier().equals("minecraft:bucket")) {
return;
}
if (value.getDirtyMetadata().getFlags().getFlag(EntityFlag.BABY)) {
if (value.getFlag(EntityFlag.BABY)) {
return;
}

View File

@ -32,6 +32,7 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import org.geysermc.connector.registry.type.ParticleMapping;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
/**
@ -49,12 +50,10 @@ public class ParticleTypesRegistryLoader extends EffectRegistryLoader<Map<Partic
while (particlesIterator.hasNext()) {
Map.Entry<String, JsonNode> entry = particlesIterator.next();
JsonNode bedrockId = entry.getValue().get("bedrockId");
JsonNode bedrockIdNumeric = entry.getValue().get("bedrockNumericId");
JsonNode eventType = entry.getValue().get("eventType");
particles.put(ParticleType.valueOf(entry.getKey().toUpperCase()), new ParticleMapping(
eventType == null ? null : LevelEventType.valueOf(eventType.asText().toUpperCase()),
bedrockId == null ? null : bedrockId.asText(),
bedrockIdNumeric == null ? -1 : bedrockIdNumeric.asInt())
particles.put(ParticleType.valueOf(entry.getKey().toUpperCase(Locale.ROOT)), new ParticleMapping(
eventType == null ? null : LevelEventType.valueOf(eventType.asText().toUpperCase(Locale.ROOT)),
bedrockId == null ? null : bedrockId.asText())
);
}
} catch (Exception e) {

View File

@ -226,6 +226,8 @@ public class ItemRegistryPopulator {
if (javaIdentifier.equals("minecraft:sculk_sensor")) {
// TODO fix in mappings
mappingItem.setBedrockIdentifier("minecraft:sculk_sensor");
} else if (javaIdentifier.equals("minecraft:music_disc_otherside") && palette.getValue().protocolVersion() <= Bedrock_v471.V471_CODEC.getProtocolVersion()) {
mappingItem.setBedrockIdentifier("minecraft:music_disc_pigstep");
}
if (usingFurnaceMinecart && javaIdentifier.equals("minecraft:furnace_minecart")) {
@ -398,7 +400,7 @@ public class ItemRegistryPopulator {
.count(1)
.blockRuntimeId(mapping.getBedrockBlockId())
.build());
} else if (javaIdentifier.startsWith("minecraft:music_disc_")) {
} else if (javaIdentifier.startsWith("minecraft:music_disc_") && !javaIdentifier.equals("minecraft:music_disc_otherside")) { // TODO TEMPORARY
// The Java record level event uses the item ID as the "key" to play the record
Registries.RECORDS.register(itemIndex, SoundEvent.valueOf("RECORD_" +
javaIdentifier.replace("minecraft:music_disc_", "").toUpperCase(Locale.ENGLISH)));

View File

@ -26,14 +26,9 @@
package org.geysermc.connector.registry.type;
import com.nukkitx.protocol.bedrock.data.LevelEventType;
import lombok.Value;
import javax.annotation.ParametersAreNullableByDefault;
@Value
@ParametersAreNullableByDefault
public class ParticleMapping {
LevelEventType levelEventType;
String identifier;
int id;
public record ParticleMapping(LevelEventType levelEventType, String identifier) {
}

View File

@ -152,7 +152,7 @@ public class ChunkUtils {
ItemFrameEntity itemFrameEntity = ItemFrameEntity.getItemFrameEntity(session, position);
if (itemFrameEntity != null) {
if (blockState == JAVA_AIR_ID) { // Item frame is still present and no block overrides that; refresh it
itemFrameEntity.updateBlock();
itemFrameEntity.updateBlock(true);
// Still update the chunk cache with the new block
session.getChunkCache().updateBlock(position.getX(), position.getY(), position.getZ(), blockState);
return;

View File

@ -50,7 +50,7 @@ public class EffectUtils {
return -1;
}
LevelEventType levelEventType = mapping.getLevelEventType();
LevelEventType levelEventType = mapping.levelEventType();
if (levelEventType == null) {
return -1;
}

View File

@ -28,7 +28,6 @@ package org.geysermc.connector.utils;
import com.github.steveice10.mc.protocol.data.game.entity.Effect;
import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.connector.entity.Entity;
import org.geysermc.connector.entity.EntityDefinitions;
@ -70,7 +69,7 @@ public final class EntityUtils {
}
private static float getMountedHeightOffset(Entity mount) {
float height = mount.getDirtyMetadata().getFloat(EntityData.BOUNDING_BOX_HEIGHT);
float height = mount.getBoundingBoxHeight();
float mountedHeightOffset = height * 0.75f;
switch (mount.getDefinition().entityType()) {
case CHICKEN, SPIDER -> mountedHeightOffset = height * 0.5f;
@ -80,7 +79,7 @@ public final class EntityUtils {
MINECART_COMMAND_BLOCK -> mountedHeightOffset = 0;
case BOAT -> mountedHeightOffset = -0.1f;
case HOGLIN, ZOGLIN -> {
boolean isBaby = mount.getDirtyMetadata().getFlags().getFlag(EntityFlag.BABY);
boolean isBaby = mount.getFlag(EntityFlag.BABY);
mountedHeightOffset = height - (isBaby ? 0.2f : 0.15f);
}
case PIGLIN -> mountedHeightOffset = height * 0.92f;
@ -110,10 +109,10 @@ public final class EntityUtils {
case PIGLIN:
case PIGLIN_BRUTE:
case ZOMBIFIED_PIGLIN:
isBaby = passenger.getDirtyMetadata().getFlags().getFlag(EntityFlag.BABY);
isBaby = passenger.getFlag(EntityFlag.BABY);
return isBaby ? -0.05f : -0.45f;
case ZOMBIE:
isBaby = passenger.getDirtyMetadata().getFlags().getFlag(EntityFlag.BABY);
isBaby = passenger.getFlag(EntityFlag.BABY);
return isBaby ? 0.0f : -0.45f;
case EVOKER:
case ILLUSIONER:
@ -174,7 +173,7 @@ public final class EntityUtils {
MINECART_COMMAND_BLOCK, BOAT -> yOffset -= mount.getDefinition().height() * 0.5f;
}
Vector3f offset = Vector3f.from(xOffset, yOffset, zOffset);
passenger.getDirtyMetadata().put(EntityData.RIDER_SEAT_POSITION, offset);
passenger.setRiderSeatPosition(offset);
}
passenger.updateBedrockMetadata();
}

View File

@ -86,7 +86,7 @@ public class InteractiveTagManager {
// Holding a leash and the mob is leashable for sure
// (Plugins can change this behavior so that's something to look into in the far far future)
interactiveTag = InteractiveTag.LEASH;
} else if (interactEntity instanceof AnimalEntity && ((AnimalEntity) interactEntity).canEat(session, javaIdentifierStripped, mapping)) {
} else if (interactEntity instanceof AnimalEntity && ((AnimalEntity) interactEntity).canEat(javaIdentifierStripped, mapping)) {
// This animal can be fed
interactiveTag = InteractiveTag.FEED;
} else {