From e74fa6c42dae9a59fe13860756ed67c3d9fef4ab Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sun, 2 May 2021 13:07:04 -0400 Subject: [PATCH 1/6] Allow connections even if encryption failed to initialize post-1.16.220 (#2147) This allows Java 16 to still be compatible with Geyser. --- connector/pom.xml | 2 +- .../connector/utils/LoginEncryptionUtils.java | 23 ++++++++++++++++++- connector/src/main/resources/languages | 2 +- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/connector/pom.xml b/connector/pom.xml index 90ee8a5c9..7d4bae7a0 100644 --- a/connector/pom.xml +++ b/connector/pom.xml @@ -32,7 +32,7 @@ com.github.CloudburstMC.Protocol bedrock-v431 - f8ecf54 + 9947665 compile diff --git a/connector/src/main/java/org/geysermc/connector/utils/LoginEncryptionUtils.java b/connector/src/main/java/org/geysermc/connector/utils/LoginEncryptionUtils.java index 3c093df94..1614f6191 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/LoginEncryptionUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/LoginEncryptionUtils.java @@ -60,6 +60,8 @@ import java.util.UUID; public class LoginEncryptionUtils { private static final ObjectMapper JSON_MAPPER = new ObjectMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + private static boolean HAS_SENT_ENCRYPTION_MESSAGE = false; + private static boolean validateChainData(JsonNode data) throws Exception { ECPublicKey lastKey = null; boolean validChain = false; @@ -133,7 +135,18 @@ public class LoginEncryptionUtils { session.setClientData(JSON_MAPPER.convertValue(JSON_MAPPER.readTree(clientJwt.getPayload().toBytes()), BedrockClientData.class)); if (EncryptionUtils.canUseEncryption()) { - LoginEncryptionUtils.startEncryptionHandshake(session, identityPublicKey); + try { + LoginEncryptionUtils.startEncryptionHandshake(session, identityPublicKey); + } catch (Throwable e) { + // An error can be thrown on older Java 8 versions about an invalid key + if (connector.getConfig().isDebugMode()) { + e.printStackTrace(); + } + + sendEncryptionFailedMessage(connector); + } + } else { + sendEncryptionFailedMessage(connector); } } catch (Exception ex) { session.disconnect("disconnectionScreen.internalError.cantConnect"); @@ -155,6 +168,14 @@ public class LoginEncryptionUtils { session.sendUpstreamPacketImmediately(packet); } + private static void sendEncryptionFailedMessage(GeyserConnector connector) { + if (!HAS_SENT_ENCRYPTION_MESSAGE) { + connector.getLogger().warning(LanguageUtils.getLocaleStringLog("geyser.network.encryption.line_1")); + connector.getLogger().warning(LanguageUtils.getLocaleStringLog("geyser.network.encryption.line_2", "https://geysermc.org/supported_java")); + HAS_SENT_ENCRYPTION_MESSAGE = true; + } + } + private static final int AUTH_MSA_DETAILS_FORM_ID = 1334; private static final int AUTH_MSA_CODE_FORM_ID = 1335; private static final int AUTH_FORM_ID = 1336; diff --git a/connector/src/main/resources/languages b/connector/src/main/resources/languages index 3d3b60de7..96e7ed66c 160000 --- a/connector/src/main/resources/languages +++ b/connector/src/main/resources/languages @@ -1 +1 @@ -Subproject commit 3d3b60de724f3f552f351c5f400269fde7598b67 +Subproject commit 96e7ed66ccdafea0cc991b8004566d448e8f6e6a From ce000a496bfbdec6924606c0904b594d15cdcd82 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sun, 2 May 2021 21:47:11 -0400 Subject: [PATCH 2/6] Use tags sent from the server, where possible (#2188) Java Edition has a tags system that allows for some server-side control of certain properties. This PR allows for piglin trading items, wool, and flowers to be determined from the server. --- .../entity/living/animal/AnimalEntity.java | 4 +- .../entity/living/animal/BeeEntity.java | 14 +--- .../entity/living/animal/ChickenEntity.java | 4 +- .../entity/living/animal/FoxEntity.java | 3 +- .../entity/living/animal/HoglinEntity.java | 3 +- .../entity/living/animal/OcelotEntity.java | 3 +- .../entity/living/animal/PandaEntity.java | 3 +- .../entity/living/animal/PigEntity.java | 3 +- .../entity/living/animal/PolarBearEntity.java | 3 +- .../entity/living/animal/RabbitEntity.java | 3 +- .../entity/living/animal/StriderEntity.java | 3 +- .../entity/living/animal/TurtleEntity.java | 3 +- .../animal/horse/AbstractHorseEntity.java | 3 +- .../living/animal/horse/LlamaEntity.java | 3 +- .../living/animal/tameable/CatEntity.java | 3 +- .../living/animal/tameable/ParrotEntity.java | 3 +- .../living/animal/tameable/WolfEntity.java | 3 +- .../entity/living/monster/PiglinEntity.java | 2 +- .../network/session/GeyserSession.java | 2 + .../network/session/cache/TagCache.java | 74 ++++++++++++++++++ .../BedrockBlockPickRequestTranslator.java | 2 +- .../player/BedrockActionTranslator.java | 10 ++- .../collision/CollisionTranslator.java | 2 +- .../translators/item/ItemRegistry.java | 9 +-- .../java/JavaDeclareTagsTranslator.java | 40 ++++++++++ .../java/JavaJoinGameTranslator.java | 2 + .../player/JavaPlayerActionAckTranslator.java | 12 +-- .../world/JavaBlockBreakAnimTranslator.java | 2 +- .../FeedBabySoundInteractionHandler.java | 3 +- .../world/block/BlockTranslator.java | 70 ++++++++--------- .../connector/registry/type/BlockMapping.java | 75 +++++++++++++++++++ .../geysermc/connector/utils/BlockUtils.java | 22 ++++-- .../utils/InteractiveTagManager.java | 2 +- 33 files changed, 295 insertions(+), 98 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/session/cache/TagCache.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareTagsTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/registry/type/BlockMapping.java 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 075690662..efded1f6f 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 @@ -28,6 +28,8 @@ package org.geysermc.connector.entity.living.animal; import com.nukkitx.math.vector.Vector3f; import org.geysermc.connector.entity.living.AgeableEntity; import org.geysermc.connector.entity.type.EntityType; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.item.ItemEntry; public class AnimalEntity extends AgeableEntity { @@ -40,7 +42,7 @@ public class AnimalEntity extends AgeableEntity { * wheat. * @return true if this is a valid item to breed with for this animal. */ - public boolean canEat(String javaIdentifierStripped) { + public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) { // This is what it defaults to. OK. return javaIdentifierStripped.equals("wheat"); } 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 d076b8a6f..b2d5faaad 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 @@ -26,7 +26,6 @@ package org.geysermc.connector.entity.living.animal; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; -import com.google.common.collect.ImmutableSet; import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityEventType; @@ -34,16 +33,9 @@ import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import com.nukkitx.protocol.bedrock.packet.EntityEventPacket; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; - -import java.util.Set; +import org.geysermc.connector.network.translators.item.ItemEntry; public class BeeEntity extends AnimalEntity { - /** - * A list of all flowers. Used for feeding bees. - */ - private static final Set FLOWERS = ImmutableSet.of("dandelion", "poppy", "blue_orchid", "allium", "azure_bluet", - "red_tulip", "pink_tulip", "white_tulip", "orange_tulip", "cornflower", "lily_of_the_valley", "wither_rose", - "sunflower", "lilac", "rose_bush", "peony"); public BeeEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { super(entityId, geyserId, entityType, position, motion, rotation); @@ -74,7 +66,7 @@ public class BeeEntity extends AnimalEntity { } @Override - public boolean canEat(String javaIdentifierStripped) { - return FLOWERS.contains(javaIdentifierStripped); + public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) { + return session.getTagCache().isFlower(itemEntry); } } 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 66e8f9ac8..b5f0395d4 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 @@ -27,6 +27,8 @@ package org.geysermc.connector.entity.living.animal; import com.nukkitx.math.vector.Vector3f; import org.geysermc.connector.entity.type.EntityType; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.item.ItemEntry; public class ChickenEntity extends AnimalEntity { @@ -35,7 +37,7 @@ public class ChickenEntity extends AnimalEntity { } @Override - public boolean canEat(String javaIdentifierStripped) { + public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) { 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 bfa376272..ff71e87f0 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 @@ -31,6 +31,7 @@ import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.item.ItemEntry; public class FoxEntity extends AnimalEntity { @@ -54,7 +55,7 @@ public class FoxEntity extends AnimalEntity { } @Override - public boolean canEat(String javaIdentifierStripped) { + public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) { return javaIdentifierStripped.equals("sweet_berries"); } } 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 b915c07de..9fbb17725 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 @@ -30,6 +30,7 @@ import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.item.ItemEntry; import org.geysermc.connector.utils.DimensionUtils; public class HoglinEntity extends AnimalEntity { @@ -49,7 +50,7 @@ public class HoglinEntity extends AnimalEntity { } @Override - public boolean canEat(String javaIdentifierStripped) { + public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) { 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 7c7d74770..1cf541c8c 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 @@ -30,6 +30,7 @@ import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.item.ItemEntry; public class OcelotEntity extends AnimalEntity { @@ -46,7 +47,7 @@ public class OcelotEntity extends AnimalEntity { } @Override - public boolean canEat(String javaIdentifierStripped) { + public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) { 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 9431d66a0..2f5ced080 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 @@ -33,6 +33,7 @@ import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import com.nukkitx.protocol.bedrock.packet.EntityEventPacket; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.item.ItemEntry; import org.geysermc.connector.network.translators.item.ItemRegistry; public class PandaEntity extends AnimalEntity { @@ -80,7 +81,7 @@ public class PandaEntity extends AnimalEntity { } @Override - public boolean canEat(String javaIdentifierStripped) { + public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) { 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 551e1c345..bbb1aed20 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 @@ -30,6 +30,7 @@ import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.item.ItemEntry; public class PigEntity extends AnimalEntity { @@ -47,7 +48,7 @@ public class PigEntity extends AnimalEntity { } @Override - public boolean canEat(String javaIdentifierStripped) { + public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) { 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 7b5d42f35..f33635aeb 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 @@ -30,6 +30,7 @@ import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.item.ItemEntry; public class PolarBearEntity extends AnimalEntity { @@ -46,7 +47,7 @@ public class PolarBearEntity extends AnimalEntity { } @Override - public boolean canEat(String javaIdentifierStripped) { + public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) { 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 a789b48e4..9137cd23a 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 @@ -31,6 +31,7 @@ import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.item.ItemEntry; public class RabbitEntity extends AnimalEntity { @@ -61,7 +62,7 @@ public class RabbitEntity extends AnimalEntity { } @Override - public boolean canEat(String javaIdentifierStripped) { + public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) { 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 2a99a5a03..a90a044bc 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 @@ -31,6 +31,7 @@ import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.connector.entity.Entity; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.item.ItemEntry; public class StriderEntity extends AnimalEntity { @@ -87,7 +88,7 @@ public class StriderEntity extends AnimalEntity { } @Override - public boolean canEat(String javaIdentifierStripped) { + public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) { 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 89df815d7..536f40755 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 @@ -30,6 +30,7 @@ import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.item.ItemEntry; public class TurtleEntity extends AnimalEntity { @@ -48,7 +49,7 @@ public class TurtleEntity extends AnimalEntity { } @Override - public boolean canEat(String javaIdentifierStripped) { + public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) { 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 d2f89e101..324c8229f 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 @@ -37,6 +37,7 @@ import org.geysermc.connector.entity.attribute.AttributeType; import org.geysermc.connector.entity.living.animal.AnimalEntity; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.item.ItemEntry; import org.geysermc.connector.network.translators.item.ItemRegistry; import java.util.Set; @@ -112,7 +113,7 @@ public class AbstractHorseEntity extends AnimalEntity { } @Override - public boolean canEat(String javaIdentifierStripped) { + public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) { 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 0b21c771e..8ab1df1a8 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 @@ -32,6 +32,7 @@ import com.nukkitx.protocol.bedrock.data.inventory.ItemData; import com.nukkitx.protocol.bedrock.packet.MobArmorEquipmentPacket; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.item.ItemEntry; import org.geysermc.connector.network.translators.item.ItemRegistry; public class LlamaEntity extends ChestedHorseEntity { @@ -77,7 +78,7 @@ public class LlamaEntity extends ChestedHorseEntity { } @Override - public boolean canEat(String javaIdentifierStripped) { + public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) { 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 7866d25cf..2d56d0c18 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 @@ -31,6 +31,7 @@ import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.item.ItemEntry; public class CatEntity extends TameableEntity { @@ -85,7 +86,7 @@ public class CatEntity extends TameableEntity { } @Override - public boolean canEat(String javaIdentifierStripped) { + public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) { 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 50ec9ed04..45327c785 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 @@ -30,6 +30,7 @@ import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.data.entity.EntityData; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.item.ItemEntry; public class ParrotEntity extends TameableEntity { @@ -47,7 +48,7 @@ public class ParrotEntity extends TameableEntity { } @Override - public boolean canEat(String javaIdentifierStripped) { + public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) { 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 91350ef54..bb7916937 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 @@ -32,6 +32,7 @@ import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.item.ItemEntry; import java.util.Set; @@ -87,7 +88,7 @@ public class WolfEntity extends TameableEntity { } @Override - public boolean canEat(String javaIdentifierStripped) { + public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) { // Cannot be a baby to eat these foods return WOLF_FOODS.contains(javaIdentifierStripped) && !metadata.getFlags().getFlag(EntityFlag.BABY); } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/monster/PiglinEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/monster/PiglinEntity.java index e6e509b11..44fa2c49d 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/monster/PiglinEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/PiglinEntity.java @@ -61,7 +61,7 @@ public class PiglinEntity extends BasePiglinEntity { @Override public void updateOffHand(GeyserSession session) { // Check if the Piglin is holding Gold and set the ADMIRING flag accordingly so its pose updates - boolean changed = metadata.getFlags().setFlag(EntityFlag.ADMIRING, offHand.getId() == ItemRegistry.GOLD.getBedrockId()); + boolean changed = metadata.getFlags().setFlag(EntityFlag.ADMIRING, session.getTagCache().shouldPiglinAdmire(ItemRegistry.getItem(this.offHand))); if (changed) { super.updateBedrockMetadata(session); } 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 63cdc6ece..081ad859a 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 @@ -146,6 +146,7 @@ public class GeyserSession implements CommandSender { private ChunkCache chunkCache; private EntityCache entityCache; private EntityEffectCache effectCache; + private final TagCache tagCache; private WorldCache worldCache; private WindowCache windowCache; private final Int2ObjectMap teleportMap = new Int2ObjectOpenHashMap<>(); @@ -452,6 +453,7 @@ public class GeyserSession implements CommandSender { this.chunkCache = new ChunkCache(this); this.entityCache = new EntityCache(this); this.effectCache = new EntityEffectCache(); + this.tagCache = new TagCache(); this.worldCache = new WorldCache(this); this.windowCache = new WindowCache(this); diff --git a/connector/src/main/java/org/geysermc/connector/network/session/cache/TagCache.java b/connector/src/main/java/org/geysermc/connector/network/session/cache/TagCache.java new file mode 100644 index 000000000..c46e37b74 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/session/cache/TagCache.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2019-2021 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.session.cache; + +import com.github.steveice10.mc.protocol.packet.ingame.server.ServerDeclareTagsPacket; +import it.unimi.dsi.fastutil.ints.IntList; +import it.unimi.dsi.fastutil.ints.IntLists; +import org.geysermc.connector.network.translators.item.ItemEntry; +import org.geysermc.connector.registry.type.BlockMapping; + +import java.util.Map; + +/** + * Manages information sent from the {@link ServerDeclareTagsPacket}. If that packet is not sent, all lists here + * will remain empty, matching Java Edition behavior. + */ +public class TagCache { + /* Blocks */ + private IntList wool = IntLists.emptyList(); + /* Items */ + private IntList flowers = IntLists.emptyList(); + private IntList piglinLoved = IntLists.emptyList(); + + public void loadPacket(ServerDeclareTagsPacket packet) { + Map blockTags = packet.getBlockTags(); + this.wool = IntList.of(blockTags.get("minecraft:wool")); + + Map itemTags = packet.getItemTags(); + this.flowers = IntList.of(itemTags.get("minecraft:flowers")); + this.piglinLoved = IntList.of(itemTags.get("minecraft:piglin_loved")); + } + + public void clear() { + this.wool = IntLists.emptyList(); + + this.flowers = IntLists.emptyList(); + this.piglinLoved = IntLists.emptyList(); + } + + public boolean isFlower(ItemEntry itemEntry) { + return flowers.contains(itemEntry.getJavaId()); + } + + public boolean shouldPiglinAdmire(ItemEntry itemEntry) { + return piglinLoved.contains(itemEntry.getJavaId()); + } + + public boolean isWool(BlockMapping blockMapping) { + return wool.contains(blockMapping.getJavaBlockId()); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockPickRequestTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockPickRequestTranslator.java index 9becfb36f..350c029ff 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockPickRequestTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockPickRequestTranslator.java @@ -46,6 +46,6 @@ public class BedrockBlockPickRequestTranslator extends PacketTranslator type : collisionTypes) { CollisionRemapper annotation = annotationMap.get(type); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemRegistry.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemRegistry.java index 10c14074f..0e1a28d54 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemRegistry.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemRegistry.java @@ -108,10 +108,6 @@ public class ItemRegistry { * Egg item entry, used in JavaEntityStatusTranslator.java */ public static ItemEntry EGG; - /** - * Gold item entry, used in PiglinEntity.java - */ - public static ItemEntry GOLD; /** * Shield item entry, used in Entity.java and LivingEntity.java */ @@ -294,7 +290,7 @@ public class ItemRegistry { // However, in order for some visuals and crafting to work, we need to send the first matching block state // as indexed by Bedrock's block palette // There are exceptions! But, ideally, the block ID override should take care of those. - String javaBlockIdentifier = BlockTranslator.getJavaIdBlockMap().inverse().get(blockRuntimeIdNode.intValue()).split("\\[")[0]; + String javaBlockIdentifier = BlockTranslator.getBlockMapping(blockRuntimeIdNode.intValue()).getCleanJavaIdentifier(); NbtMapBuilder requiredBlockStatesBuilder = NbtMap.builder(); String correctBedrockIdentifier = blockTranslator.getAllBedrockBlockStates().get(aValidBedrockBlockId).getString("name"); boolean firstPass = true; @@ -437,9 +433,6 @@ public class ItemRegistry { case "minecraft:egg": EGG = itemEntry; break; - case "minecraft:gold_ingot": - GOLD = itemEntry; - break; case "minecraft:shield": SHIELD = itemEntry; break; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareTagsTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareTagsTranslator.java new file mode 100644 index 000000000..368693bf2 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareTagsTranslator.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2019-2021 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.java; + +import com.github.steveice10.mc.protocol.packet.ingame.server.ServerDeclareTagsPacket; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; +import org.geysermc.connector.network.translators.Translator; + +@Translator(packet = ServerDeclareTagsPacket.class) +public class JavaDeclareTagsTranslator extends PacketTranslator { + + @Override + public void translate(ServerDeclareTagsPacket packet, GeyserSession session) { + session.getTagCache().loadPacket(packet); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java index abd79437f..47918440b 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java @@ -63,6 +63,8 @@ public class JavaJoinGameTranslator extends PacketTranslator itemFrames = new Object2IntOpenHashMap<>(); private final Map flowerPotBlocks = new HashMap<>(); - public static final Int2DoubleMap JAVA_RUNTIME_ID_TO_HARDNESS = new Int2DoubleOpenHashMap(); - public static final Int2BooleanMap JAVA_RUNTIME_ID_TO_CAN_HARVEST_WITH_HAND = new Int2BooleanOpenHashMap(); - public static final Int2ObjectMap JAVA_RUNTIME_ID_TO_TOOL_TYPE = new Int2ObjectOpenHashMap<>(); - - // The index of the collision data in collision.json - public static final Int2IntMap JAVA_RUNTIME_ID_TO_COLLISION_INDEX = new Int2IntOpenHashMap(); - - private static final Int2ObjectMap JAVA_RUNTIME_ID_TO_PICK_ITEM = new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap JAVA_RUNTIME_ID_TO_BLOCK_MAPPING = new Int2ObjectOpenHashMap<>(); /** * Java numeric ID to java unique identifier, used for block names in the statistics screen @@ -96,11 +90,7 @@ public abstract class BlockTranslator { private final EmptyChunkProvider emptyChunkProvider; - /** - * A list of all Java runtime wool IDs, for use with block breaking math and shears - */ - public static final IntSet JAVA_RUNTIME_WOOL_IDS = new IntOpenHashSet(); - public static final int JAVA_RUNTIME_COBWEB_ID; + public static final int JAVA_COBWEB_BLOCK_ID; public static final int JAVA_RUNTIME_FURNACE_ID; public static final int JAVA_RUNTIME_FURNACE_LIT_ID; @@ -127,7 +117,7 @@ public abstract class BlockTranslator { } int javaRuntimeId = -1; - int cobwebRuntimeId = -1; + int cobwebBlockId = -1; int furnaceRuntimeId = -1; int furnaceLitRuntimeId = -1; int spawnerRuntimeId = -1; @@ -139,31 +129,35 @@ public abstract class BlockTranslator { Map.Entry entry = blocksIterator.next(); String javaId = entry.getKey(); + BlockMapping.BlockMappingBuilder builder = BlockMapping.builder(); // TODO fix this, (no block should have a null hardness) JsonNode hardnessNode = entry.getValue().get("block_hardness"); if (hardnessNode != null) { - JAVA_RUNTIME_ID_TO_HARDNESS.put(javaRuntimeId, hardnessNode.doubleValue()); + builder.hardness(hardnessNode.doubleValue()); } - try { - JAVA_RUNTIME_ID_TO_CAN_HARVEST_WITH_HAND.put(javaRuntimeId, entry.getValue().get("can_break_with_hand").booleanValue()); - } catch (Exception e) { - JAVA_RUNTIME_ID_TO_CAN_HARVEST_WITH_HAND.put(javaRuntimeId, false); + JsonNode canBreakWithHandNode = entry.getValue().get("can_break_with_hand"); + if (canBreakWithHandNode != null) { + builder.canBreakWithHand(canBreakWithHandNode.booleanValue()); + } else { + builder.canBreakWithHand(false); } JsonNode toolTypeNode = entry.getValue().get("tool_type"); if (toolTypeNode != null) { - JAVA_RUNTIME_ID_TO_TOOL_TYPE.put(javaRuntimeId, toolTypeNode.textValue()); + builder.toolType(toolTypeNode.textValue()); + } else { + builder.toolType(""); } JsonNode collisionIndexNode = entry.getValue().get("collision_index"); if (hardnessNode != null) { - JAVA_RUNTIME_ID_TO_COLLISION_INDEX.put(javaRuntimeId, collisionIndexNode.intValue()); + builder.collisionIndex(collisionIndexNode.intValue()); } JsonNode pickItemNode = entry.getValue().get("pick_item"); if (pickItemNode != null) { - JAVA_RUNTIME_ID_TO_PICK_ITEM.put(javaRuntimeId, pickItemNode.textValue()); + builder.pickItem(pickItemNode.textValue()); } JAVA_ID_BLOCK_MAP.put(javaId, javaRuntimeId); @@ -183,11 +177,14 @@ public abstract class BlockTranslator { JAVA_TO_BEDROCK_IDENTIFIERS.put(cleanJavaIdentifier, bedrockIdentifier); } - if (javaId.contains("wool")) { - JAVA_RUNTIME_WOOL_IDS.add(javaRuntimeId); + builder.javaBlockId(uniqueJavaId); - } else if (javaId.contains("cobweb")) { - cobwebRuntimeId = javaRuntimeId; + builder.javaIdentifier(javaId); + + JAVA_RUNTIME_ID_TO_BLOCK_MAPPING.put(javaRuntimeId, builder.build()); + + if (javaId.contains("cobweb")) { + cobwebBlockId = uniqueJavaId; } else if (javaId.startsWith("minecraft:furnace[facing=north")) { if (javaId.contains("lit=true")) { @@ -204,10 +201,10 @@ public abstract class BlockTranslator { } } - if (cobwebRuntimeId == -1) { + if (cobwebBlockId == -1) { throw new AssertionError("Unable to find cobwebs in palette"); } - JAVA_RUNTIME_COBWEB_ID = cobwebRuntimeId; + JAVA_COBWEB_BLOCK_ID = cobwebBlockId; if (furnaceRuntimeId == -1) { throw new AssertionError("Unable to find furnace in palette"); @@ -229,6 +226,8 @@ public abstract class BlockTranslator { } JAVA_WATER_ID = waterRuntimeId; + BlockMapping.AIR = JAVA_RUNTIME_ID_TO_BLOCK_MAPPING.get(JAVA_AIR_ID); + BlockTranslator1_16_100.init(); BlockTranslator1_16_210.init(); BLOCKS_JSON = null; // We no longer require this so let it garbage collect away @@ -457,18 +456,11 @@ public abstract class BlockTranslator { } /** - * Get the item a Java client would receive when pressing - * the Pick Block key on a specific Java block state. - * - * @param javaId The Java runtime id of the block - * @return The Java identifier of the item + * @param javaRuntimeId the Java runtime ID of the block to search for. + * @return the corresponding block mapping for this runtime ID. */ - public static String getPickItem(int javaId) { - String itemIdentifier = JAVA_RUNTIME_ID_TO_PICK_ITEM.get(javaId); - if (itemIdentifier == null) { - return JAVA_ID_BLOCK_MAP.inverse().get(javaId).split("\\[")[0]; - } - return itemIdentifier; + public static BlockMapping getBlockMapping(int javaRuntimeId) { + return JAVA_RUNTIME_ID_TO_BLOCK_MAPPING.getOrDefault(javaRuntimeId, BlockMapping.AIR); } /** diff --git a/connector/src/main/java/org/geysermc/connector/registry/type/BlockMapping.java b/connector/src/main/java/org/geysermc/connector/registry/type/BlockMapping.java new file mode 100644 index 000000000..8aa06abc2 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/registry/type/BlockMapping.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2019-2021 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.registry.type; + +import lombok.Builder; +import lombok.Value; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +@Builder +@Value +public class BlockMapping { + public static BlockMapping AIR; + + String javaIdentifier; + /** + * The block ID shared between all different block states of this block. + * NOT the runtime ID! + */ + int javaBlockId; + + double hardness; + boolean canBreakWithHand; + @Nonnull String toolType; + /** + * The index of this collision in collision.json + */ + int collisionIndex; + @Nullable String pickItem; + + /** + * @return the identifier without the additional block states + */ + public String getCleanJavaIdentifier() { + return javaIdentifier.split("\\[")[0]; + } + + /** + * Get the item a Java client would receive when pressing + * the Pick Block key on a specific Java block state. + * + * @return The Java identifier of the item + */ + public String getPickItem() { + if (pickItem != null) { + return pickItem; + } + + return getCleanJavaIdentifier(); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/utils/BlockUtils.java b/connector/src/main/java/org/geysermc/connector/utils/BlockUtils.java index 997e4aee4..01c85ab43 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/BlockUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/BlockUtils.java @@ -33,6 +33,7 @@ import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.item.ItemEntry; import org.geysermc.connector.network.translators.item.ToolItemEntry; import org.geysermc.connector.network.translators.world.block.BlockTranslator; +import org.geysermc.connector.registry.type.BlockMapping; public class BlockUtils { /** @@ -108,11 +109,11 @@ public class BlockUtils { return 1.0 / speed; } - public static double getBreakTime(double blockHardness, int blockId, ItemEntry item, CompoundTag nbtData, GeyserSession session) { - boolean isWoolBlock = BlockTranslator.JAVA_RUNTIME_WOOL_IDS.contains(blockId); - boolean isCobweb = blockId == BlockTranslator.JAVA_RUNTIME_COBWEB_ID; - String blockToolType = BlockTranslator.JAVA_RUNTIME_ID_TO_TOOL_TYPE.getOrDefault(blockId, ""); - boolean canHarvestWithHand = BlockTranslator.JAVA_RUNTIME_ID_TO_CAN_HARVEST_WITH_HAND.get(blockId); + public static double getBreakTime(GeyserSession session, BlockMapping blockMapping, ItemEntry item, CompoundTag nbtData, boolean isSessionPlayer) { + boolean isWoolBlock = session.getTagCache().isWool(blockMapping); + boolean isCobweb = blockMapping.getJavaBlockId() == BlockTranslator.JAVA_COBWEB_BLOCK_ID; + String blockToolType = blockMapping.getToolType(); + boolean canHarvestWithHand = blockMapping.isCanBreakWithHand(); String toolType = ""; String toolTier = ""; boolean correctTool = false; @@ -126,8 +127,11 @@ public class BlockUtils { int hasteLevel = 0; int miningFatigueLevel = 0; - if (session == null) { - return calculateBreakTime(blockHardness, toolTier, canHarvestWithHand, correctTool, toolType, isWoolBlock, isCobweb, toolEfficiencyLevel, hasteLevel, miningFatigueLevel, false, false, false); + if (!isSessionPlayer) { + // Another entity is currently mining; we have all the information we know + return calculateBreakTime(blockMapping.getHardness(), toolTier, canHarvestWithHand, correctTool, toolType, isWoolBlock, + isCobweb, toolEfficiencyLevel, hasteLevel, miningFatigueLevel, false, + false, false); } hasteLevel = session.getEffectCache().getEffectLevel(Effect.FASTER_DIG); @@ -140,7 +144,9 @@ public class BlockUtils { boolean outOfWaterButNotOnGround = (!isInWater) && (!session.getPlayerEntity().isOnGround()); boolean insideWaterNotOnGround = isInWater && !session.getPlayerEntity().isOnGround(); - return calculateBreakTime(blockHardness, toolTier, canHarvestWithHand, correctTool, toolType, isWoolBlock, isCobweb, toolEfficiencyLevel, hasteLevel, miningFatigueLevel, insideOfWaterWithoutAquaAffinity, outOfWaterButNotOnGround, insideWaterNotOnGround); + return calculateBreakTime(blockMapping.getHardness(), toolTier, canHarvestWithHand, correctTool, toolType, isWoolBlock, + isCobweb, toolEfficiencyLevel, hasteLevel, miningFatigueLevel, insideOfWaterWithoutAquaAffinity, + outOfWaterButNotOnGround, insideWaterNotOnGround); } /** 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 ff7ad11cf..1d6cf60d9 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/InteractiveTagManager.java +++ b/connector/src/main/java/org/geysermc/connector/utils/InteractiveTagManager.java @@ -82,7 +82,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(javaIdentifierStripped)) { + } else if (interactEntity instanceof AnimalEntity && ((AnimalEntity) interactEntity).canEat(session, javaIdentifierStripped, itemEntry)) { // This animal can be fed interactiveTag = InteractiveTag.FEED; } else { From 2aa131f9dceed6d5d72a37758374a945e8290e9b Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sun, 9 May 2021 01:11:42 -0400 Subject: [PATCH 3/6] Fix minecart rotation when not on rails (#2200) This isn't perfect, but it's better than before, for sure. --- .../java/org/geysermc/connector/entity/MinecartEntity.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/connector/src/main/java/org/geysermc/connector/entity/MinecartEntity.java b/connector/src/main/java/org/geysermc/connector/entity/MinecartEntity.java index 49b12a3e1..b66b049eb 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/MinecartEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/MinecartEntity.java @@ -79,4 +79,10 @@ public class MinecartEntity extends Entity { public void moveAbsolute(GeyserSession session, Vector3f position, Vector3f rotation, boolean isOnGround, boolean teleported) { super.moveAbsolute(session, position.add(0d, this.entityType.getOffset(), 0d), rotation, isOnGround, teleported); } + + @Override + public Vector3f getBedrockRotation() { + // Note: minecart rotation on rails does not care about the actual rotation value + return Vector3f.from(0, rotation.getX(), 0); + } } From dda0172dedde65131dbe3c61170ddb9163096f6b Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sun, 9 May 2021 01:19:06 -0400 Subject: [PATCH 4/6] Allow more blocks to have a place sound on standalone (#2183) Items such as wall torch blocks currently do not have a place sound on standalone, as their block identifier differs from their item identifier. This commit uses the pick item logic in order to fix place sounds for such blocks. --- .../java/world/JavaBlockChangeTranslator.java | 2 +- .../connector/registry/type/BlockMapping.java | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockChangeTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockChangeTranslator.java index e362e335f..de9563d9b 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockChangeTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockChangeTranslator.java @@ -68,7 +68,7 @@ public class JavaBlockChangeTranslator extends PacketTranslator Date: Sun, 9 May 2021 01:25:57 -0400 Subject: [PATCH 5/6] Fix visual glitch when swapping out armor that's already equipped (#2173) Bedrock Edition allows you to swap out armor by right-clicking an item in your inventory, even when armor in that slot is already equipped. This PR prevents Bedrock from performing this action if both slots are occupied (which Java Edition will not do). --- .../BedrockInventoryTransactionTranslator.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java index 99d2de0b4..7dd670197 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java @@ -238,7 +238,16 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator Date: Sun, 9 May 2021 15:44:41 -0400 Subject: [PATCH 6/6] Item frame optimization and block picking support (#2203) Geyser now supports block picking for item frames. It checks to see if the item frame has an item in it - if so, it attempts the same block picking process with the item inside (NBT included). Otherwise, it attempts to pick for an item frame item. This commit also improves item frames by having the internal map store the entity and not the ID - in many situations, this prevents two maps from having to be searched. Additionally, item frames are no longer despawned if an item is placed on them - rather, it waits until the server tells us to despawn the entity. --- .../connector/entity/ItemFrameEntity.java | 31 +++---- .../network/session/GeyserSession.java | 10 +-- .../BedrockBlockPickRequestTranslator.java | 13 +++ .../BedrockEntityPickRequestTranslator.java | 2 +- ...BedrockInventoryTransactionTranslator.java | 30 ++++--- .../BedrockItemFrameDropItemTranslator.java | 11 ++- .../player/BedrockActionTranslator.java | 6 +- .../geysermc/connector/utils/ChunkUtils.java | 19 ++--- .../connector/utils/InventoryUtils.java | 80 ++++++++++++++++--- 9 files changed, 137 insertions(+), 65 deletions(-) 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 e10ad0afd..79711b0cb 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java @@ -35,6 +35,7 @@ import com.nukkitx.nbt.NbtMapBuilder; import com.nukkitx.protocol.bedrock.data.inventory.ItemData; import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket; import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; +import lombok.Getter; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.item.ItemEntry; @@ -69,6 +70,11 @@ public class ItemFrameEntity extends Entity { * Cached item frame's Bedrock compound tag. */ private NbtMap cachedTag; + /** + * The item currently in the item frame. Used for block picking. + */ + @Getter + private ItemStack heldItem = null; public ItemFrameEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation, HangingDirection direction) { super(entityId, geyserId, entityType, position, motion, rotation); @@ -87,7 +93,8 @@ public class ItemFrameEntity extends Entity { bedrockRuntimeId = session.getBlockTranslator().getItemFrame(blockBuilder.build()); bedrockPosition = Vector3i.from(position.getFloorX(), position.getFloorY(), position.getFloorZ()); - session.getItemFrameCache().put(bedrockPosition, entityId); + session.getItemFrameCache().put(bedrockPosition, this); + // Delay is required, or else loading in frames on chunk load is sketchy at best session.getConnector().getGeneralThreadPool().schedule(() -> { updateBlock(session); @@ -99,13 +106,14 @@ public class ItemFrameEntity extends Entity { @Override public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { if (entityMetadata.getId() == 7 && entityMetadata.getValue() != null) { - ItemData itemData = ItemTranslator.translateToBedrock(session, (ItemStack) entityMetadata.getValue()); + this.heldItem = (ItemStack) entityMetadata.getValue(); + ItemData itemData = ItemTranslator.translateToBedrock(session, heldItem); ItemEntry itemEntry = ItemRegistry.getItem((ItemStack) entityMetadata.getValue()); NbtMapBuilder builder = NbtMap.builder(); builder.putByte("Count", (byte) itemData.getCount()); if (itemData.getTag() != null) { - builder.put("tag", itemData.getTag().toBuilder().build()); + builder.put("tag", itemData.getTag()); } builder.putShort("Damage", (short) itemData.getDamage()); builder.putString("Name", itemEntry.getBedrockIdentifier()); @@ -146,7 +154,9 @@ public class ItemFrameEntity extends Entity { updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS); session.sendUpstreamPacket(updateBlockPacket); - session.getItemFrameCache().remove(position, entityId); + + session.getItemFrameCache().remove(bedrockPosition, this); + valid = false; return true; } @@ -192,16 +202,7 @@ public class ItemFrameEntity extends Entity { * @param session GeyserSession. * @return Java entity ID or -1 if not found. */ - public static long getItemFrameEntityId(GeyserSession session, Vector3i position) { - return session.getItemFrameCache().getOrDefault(position, -1); - } - - /** - * Force-remove from the position-to-ID map so it doesn't cause conflicts. - * @param session GeyserSession. - * @param position position of the removed item frame. - */ - public static void removePosition(GeyserSession session, Vector3i position) { - session.getItemFrameCache().remove(position); + public static ItemFrameEntity getItemFrameEntity(GeyserSession session, Vector3i position) { + return session.getItemFrameCache().get(position); } } 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 081ad859a..28aff40b9 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 @@ -66,10 +66,7 @@ import it.unimi.dsi.fastutil.ints.IntList; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectMaps; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.Object2LongMap; -import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectIterator; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import it.unimi.dsi.fastutil.objects.*; import lombok.AccessLevel; import lombok.Getter; import lombok.NonNull; @@ -81,6 +78,7 @@ import org.geysermc.connector.command.CommandSender; import org.geysermc.connector.common.AuthType; import org.geysermc.connector.configuration.EmoteOffhandWorkaroundOption; import org.geysermc.connector.entity.Entity; +import org.geysermc.connector.entity.ItemFrameEntity; import org.geysermc.connector.entity.Tickable; import org.geysermc.connector.entity.attribute.Attribute; import org.geysermc.connector.entity.attribute.AttributeType; @@ -189,10 +187,10 @@ public class GeyserSession implements CommandSender { private final Long2ObjectMap storedMaps = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap<>()); /** - * A map of Vector3i positions to Java entity IDs. + * A map of Vector3i positions to Java entities. * Used for translating Bedrock block actions to Java entity actions. */ - private final Object2LongMap itemFrameCache = new Object2LongOpenHashMap<>(); + private final Map itemFrameCache = new Object2ObjectOpenHashMap<>(); /** * Stores a list of all lectern locations and their block entity tags. diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockPickRequestTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockPickRequestTranslator.java index 350c029ff..ba74c7769 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockPickRequestTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockPickRequestTranslator.java @@ -27,6 +27,7 @@ package org.geysermc.connector.network.translators.bedrock; import com.nukkitx.math.vector.Vector3i; import com.nukkitx.protocol.bedrock.packet.BlockPickRequestPacket; +import org.geysermc.connector.entity.ItemFrameEntity; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.Translator; @@ -43,6 +44,18 @@ public class BedrockBlockPickRequestTranslator extends PacketTranslator