diff --git a/connector/src/main/java/org/geysermc/connector/entity/AbstractArrowEntity.java b/connector/src/main/java/org/geysermc/connector/entity/AbstractArrowEntity.java index f51516dc6..be07a12ce 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/AbstractArrowEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/AbstractArrowEntity.java @@ -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); } diff --git a/connector/src/main/java/org/geysermc/connector/entity/EnderCrystalEntity.java b/connector/src/main/java/org/geysermc/connector/entity/EnderCrystalEntity.java index a39c479f8..df7c041b3 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/EnderCrystalEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/EnderCrystalEntity.java @@ -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 entityMetadata) { diff --git a/connector/src/main/java/org/geysermc/connector/entity/Entity.java b/connector/src/main/java/org/geysermc/connector/entity/Entity.java index bdeacc9dc..3bf5a3a16 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/Entity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/Entity.java @@ -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 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. * diff --git a/connector/src/main/java/org/geysermc/connector/entity/EntityDefinition.java b/connector/src/main/java/org/geysermc/connector/entity/EntityDefinition.java index c4100d95d..e4baf1ed4 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/EntityDefinition.java +++ b/connector/src/main/java/org/geysermc/connector/entity/EntityDefinition.java @@ -46,7 +46,7 @@ import java.util.function.BiConsumer; * * @param the entity type this definition represents */ -public record EntityDefinition(EntityFactory factory, EntityType entityType, int bedrockId, String identifier, +public record EntityDefinition(EntityFactory factory, EntityType entityType, String identifier, float width, float height, float offset, List> translators) { public static Builder inherited(BaseEntityFactory factory, EntityDefinition parent) { @@ -54,7 +54,7 @@ public record EntityDefinition(EntityFactory factory, Entit } public static Builder inherited(EntityFactory factory, EntityDefinition 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 Builder builder(EntityFactory factory) { @@ -66,7 +66,6 @@ public record EntityDefinition(EntityFactory factory, Entit public static class Builder { private final EntityFactory factory; private EntityType type; - private int bedrockId; private String identifier; private float width; private float height; @@ -78,10 +77,9 @@ public record EntityDefinition(EntityFactory factory, Entit translators = new ObjectArrayList<>(); } - public Builder(EntityFactory factory, EntityType type, int bedrockId, String identifier, float width, float height, float offset, List> translators) { + public Builder(EntityFactory factory, EntityType type, String identifier, float width, float height, float offset, List> 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(EntityFactory factory, Entit if (identifier == null && type != null) { identifier = "minecraft:" + type.name().toLowerCase(Locale.ROOT); } - EntityDefinition definition = new EntityDefinition<>(factory, type, bedrockId, identifier, width, height, offset, translators); + EntityDefinition 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; } diff --git a/connector/src/main/java/org/geysermc/connector/entity/EntityDefinitions.java b/connector/src/main/java/org/geysermc/connector/entity/EntityDefinitions.java index 926c86c29..be51687c0 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/EntityDefinitions.java +++ b/connector/src/main/java/org/geysermc/connector/entity/EntityDefinitions.java @@ -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 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) .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() { - }, entityBase) // TODO + FALLING_BLOCK = EntityDefinition.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() { - }, entityBase) //TODO + FISHING_BOBBER = EntityDefinition.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 .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() { - }, entityBase) // TODO + ITEM_FRAME = EntityDefinition.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 { .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())) .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 livingEntityBase = EntityDefinition.inherited(LivingEntity::new, entityBase) .addTranslator(MetadataType.BYTE, LivingEntity::setLivingEntityFlags) .addTranslator(MetadataType.FLOAT, LivingEntity::setHealth) - .addTranslator(MetadataType.FLOAT, + .addTranslator(MetadataType.INT, (livingEntity, entityMetadata) -> livingEntity.getDirtyMetadata().put(EntityData.EFFECT_COLOR, entityMetadata.getValue())) .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.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 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 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) .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) .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) .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) .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 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) .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 .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.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() { diff --git a/connector/src/main/java/org/geysermc/connector/entity/FishingHookEntity.java b/connector/src/main/java/org/geysermc/connector/entity/FishingHookEntity.java index 2493ef588..8efb2db83 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/FishingHookEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/FishingHookEntity.java @@ -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; diff --git a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java b/connector/src/main/java/org/geysermc/connector/entity/GeyserDirtyMetadata.java similarity index 57% rename from connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java rename to connector/src/main/java/org/geysermc/connector/entity/GeyserDirtyMetadata.java index 517864e14..09cd79562 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java +++ b/connector/src/main/java/org/geysermc/connector/entity/GeyserDirtyMetadata.java @@ -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 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(); + } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/ItemEntity.java b/connector/src/main/java/org/geysermc/connector/entity/ItemEntity.java index ab5e2906e..04ea9f299 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/ItemEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/ItemEntity.java @@ -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); } diff --git a/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java b/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java index 5730fdaff..2ff653a06 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java @@ -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; } diff --git a/connector/src/main/java/org/geysermc/connector/entity/LivingEntity.java b/connector/src/main/java/org/geysermc/connector/entity/LivingEntity.java index 28f97a2a3..0a7a0da5c 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/LivingEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/LivingEntity.java @@ -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); } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/ArmorStandEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/ArmorStandEntity.java index 904de233f..e2d34f2b8 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/ArmorStandEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/ArmorStandEntity.java @@ -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); diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/AnimalEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/AnimalEntity.java index 7ef8f107e..60d2ba96a 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/AnimalEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/AnimalEntity.java @@ -44,7 +44,7 @@ public class AnimalEntity extends AgeableEntity { * wheat. * @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"); } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/AxolotlEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/AxolotlEntity.java index 53c70d13e..e0bfc577e 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/AxolotlEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/AxolotlEntity.java @@ -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"); } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/BeeEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/BeeEntity.java index 12366c4cd..a2524566d 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/BeeEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/BeeEntity.java @@ -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); } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/ChickenEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/ChickenEntity.java index b1031209f..a32262199 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/ChickenEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/ChickenEntity.java @@ -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"); } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/FoxEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/FoxEntity.java index 7016753ba..a10201155 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/FoxEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/FoxEntity.java @@ -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); } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/GoatEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/GoatEntity.java index 6bf7cd336..568be2d21 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/GoatEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/GoatEntity.java @@ -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); } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/HoglinEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/HoglinEntity.java index 6493810c4..fb2c68fd2 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/HoglinEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/HoglinEntity.java @@ -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"); } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/OcelotEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/OcelotEntity.java index ed4f8133b..945787417 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/OcelotEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/OcelotEntity.java @@ -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"); } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/PandaEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/PandaEntity.java index ff66d30a8..376079387 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/PandaEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/PandaEntity.java @@ -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"); } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/PigEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/PigEntity.java index 8fe4fde06..b31470e1b 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/PigEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/PigEntity.java @@ -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"); } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/PolarBearEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/PolarBearEntity.java index 4eb5d79fc..c83e6bad4 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/PolarBearEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/PolarBearEntity.java @@ -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; } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/RabbitEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/RabbitEntity.java index 2d6a0d96a..02d6db67e 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/RabbitEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/RabbitEntity.java @@ -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"); } } \ No newline at end of file diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/StriderEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/StriderEntity.java index d31bf4a4e..b2934e507 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/StriderEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/StriderEntity.java @@ -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"); } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/TurtleEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/TurtleEntity.java index 28ff2d836..495bc64a0 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/TurtleEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/TurtleEntity.java @@ -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"); } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/AbstractHorseEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/AbstractHorseEntity.java index 27a359d63..1b3ffbd71 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/AbstractHorseEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/AbstractHorseEntity.java @@ -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); } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/LlamaEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/LlamaEntity.java index 1c4e5155e..204261620 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/LlamaEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/LlamaEntity.java @@ -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"); } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/CatEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/CatEntity.java index a4fe27535..035044a93 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/CatEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/CatEntity.java @@ -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"); } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/ParrotEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/ParrotEntity.java index 763d489e4..603303a65 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/ParrotEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/ParrotEntity.java @@ -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"); } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/WolfEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/WolfEntity.java index 5d6bcf1e3..f828ce014 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/WolfEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/WolfEntity.java @@ -56,7 +56,7 @@ public class WolfEntity extends TameableEntity { @Override public void setTameableFlags(EntityMetadata 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(); } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/monster/EnderDragonEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/monster/EnderDragonEntity.java index ff149c5b7..3d381972d 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/monster/EnderDragonEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/EnderDragonEntity.java @@ -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++) { diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/monster/raid/SpellcasterIllagerEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/monster/raid/SpellcasterIllagerEntity.java index 23485750d..1dca4fd0a 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/monster/raid/SpellcasterIllagerEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/raid/SpellcasterIllagerEntity.java @@ -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 entityMetadata) { diff --git a/connector/src/main/java/org/geysermc/connector/entity/player/PlayerEntity.java b/connector/src/main/java/org/geysermc/connector/entity/player/PlayerEntity.java index cfa78e08a..8c2471526 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/player/PlayerEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/player/PlayerEntity.java @@ -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 entityMetadata) { + return bedPosition = super.setBedPosition(entityMetadata); + } + public void setAbsorptionHearts(EntityMetadata 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); } } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/player/SessionPlayerEntity.java b/connector/src/main/java/org/geysermc/connector/entity/player/SessionPlayerEntity.java index d8a3e5492..bc6d4077a 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/player/SessionPlayerEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/player/SessionPlayerEntity.java @@ -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 diff --git a/connector/src/main/java/org/geysermc/connector/entity/player/SkullPlayerEntity.java b/connector/src/main/java/org/geysermc/connector/entity/player/SkullPlayerEntity.java index c2c41d0dc..e6c5cdfb3 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/player/SkullPlayerEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/player/SkullPlayerEntity.java @@ -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; diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index ef545746b..72dcf3710 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -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); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockAdventureSettingsTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockAdventureSettingsTranslator.java index 10138f9a3..6fafef998 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockAdventureSettingsTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockAdventureSettingsTranslator.java @@ -50,7 +50,7 @@ public class BedrockAdventureSettingsTranslator extends PacketTranslator 0) { + if (session.getPlayerEntity().isRidingInFront()) { sendMovement = true; } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockRespawnTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockRespawnTranslator.java index 8d1fda4e8..4ccf77370 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockRespawnTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockRespawnTranslator.java @@ -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 { 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()); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/BedrockEntityEventTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/BedrockEntityEventTranslator.java index f46f486e9..ef275ca0a 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/BedrockEntityEventTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/BedrockEntityEventTranslator.java @@ -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 { - 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(); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/player/BedrockActionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/player/BedrockActionTranslator.java index cbc01f8ee..c3c3dad84 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/player/BedrockActionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/player/BedrockActionTranslator.java @@ -116,7 +116,7 @@ public class BedrockActionTranslator extends PacketTranslator 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); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/collision/CollisionManager.java b/connector/src/main/java/org/geysermc/connector/network/translators/collision/CollisionManager.java index 2f5c41ae9..3d9069232 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/collision/CollisionManager.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/collision/CollisionManager.java @@ -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 - 1⁄4) 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()); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaCommandsTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaCommandsTranslator.java index 8eca69333..28d965902 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaCommandsTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaCommandsTranslator.java @@ -220,7 +220,7 @@ public class JavaCommandsTranslator extends PacketTranslator 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; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaLoginTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaLoginTranslator.java index ca7c92302..772e65846 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaLoginTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaLoginTranslator.java @@ -90,10 +90,7 @@ public class JavaLoginTranslator extends PacketTranslator translator = (EntityMetadataTranslator) translators.get(metadata.getId()); + EntityMetadataTranslator translator = (EntityMetadataTranslator) 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) metadata); } entity.updateBedrockMetadata(); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPositionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPositionTranslator.java index f16c4aadf..3190a637b 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPositionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPositionTranslator.java @@ -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 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> 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 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); + } + } } } \ No newline at end of file diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/level/JavaLevelParticlesTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/level/JavaLevelParticlesTranslator.java index 3a5f6b446..c4ca16042 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/level/JavaLevelParticlesTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/level/JavaLevelParticlesTranslator.java @@ -136,18 +136,18 @@ public class JavaLevelParticlesTranslator extends PacketTranslator { 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; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/sound/entity/FeedBabySoundInteractionHandler.java b/connector/src/main/java/org/geysermc/connector/network/translators/sound/entity/FeedBabySoundInteractionHandler.java index 2895ad214..d7fa03943 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/sound/entity/FeedBabySoundInteractionHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/sound/entity/FeedBabySoundInteractionHandler.java @@ -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(); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/sound/entity/MilkEntitySoundInteractionHandler.java b/connector/src/main/java/org/geysermc/connector/network/translators/sound/entity/MilkEntitySoundInteractionHandler.java index 11f929f17..948b69afb 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/sound/entity/MilkEntitySoundInteractionHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/sound/entity/MilkEntitySoundInteractionHandler.java @@ -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; } diff --git a/connector/src/main/java/org/geysermc/connector/registry/loader/ParticleTypesRegistryLoader.java b/connector/src/main/java/org/geysermc/connector/registry/loader/ParticleTypesRegistryLoader.java index 9de4b946f..e05668b6f 100644 --- a/connector/src/main/java/org/geysermc/connector/registry/loader/ParticleTypesRegistryLoader.java +++ b/connector/src/main/java/org/geysermc/connector/registry/loader/ParticleTypesRegistryLoader.java @@ -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 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) { diff --git a/connector/src/main/java/org/geysermc/connector/registry/populator/ItemRegistryPopulator.java b/connector/src/main/java/org/geysermc/connector/registry/populator/ItemRegistryPopulator.java index 8f3e87e53..a7157960a 100644 --- a/connector/src/main/java/org/geysermc/connector/registry/populator/ItemRegistryPopulator.java +++ b/connector/src/main/java/org/geysermc/connector/registry/populator/ItemRegistryPopulator.java @@ -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))); diff --git a/connector/src/main/java/org/geysermc/connector/registry/type/ParticleMapping.java b/connector/src/main/java/org/geysermc/connector/registry/type/ParticleMapping.java index 2ed21ddb3..fa7fcb300 100644 --- a/connector/src/main/java/org/geysermc/connector/registry/type/ParticleMapping.java +++ b/connector/src/main/java/org/geysermc/connector/registry/type/ParticleMapping.java @@ -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) { } \ No newline at end of file diff --git a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java index df2923bb5..8015df8b7 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java @@ -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; diff --git a/connector/src/main/java/org/geysermc/connector/utils/EffectUtils.java b/connector/src/main/java/org/geysermc/connector/utils/EffectUtils.java index 692b26d85..7016cc786 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/EffectUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/EffectUtils.java @@ -50,7 +50,7 @@ public class EffectUtils { return -1; } - LevelEventType levelEventType = mapping.getLevelEventType(); + LevelEventType levelEventType = mapping.levelEventType(); if (levelEventType == null) { return -1; } diff --git a/connector/src/main/java/org/geysermc/connector/utils/EntityUtils.java b/connector/src/main/java/org/geysermc/connector/utils/EntityUtils.java index 57c0eac73..f0de018ff 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/EntityUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/EntityUtils.java @@ -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(); } diff --git a/connector/src/main/java/org/geysermc/connector/utils/InteractiveTagManager.java b/connector/src/main/java/org/geysermc/connector/utils/InteractiveTagManager.java index 0f7e66250..c43b19b92 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/InteractiveTagManager.java +++ b/connector/src/main/java/org/geysermc/connector/utils/InteractiveTagManager.java @@ -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 {