From 7fcd8f2daf9cc39c61d37934751251e22b202e14 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Wed, 10 Jun 2020 19:02:29 -0400 Subject: [PATCH] Fix block entities on older versions (#756) * Fix block entities on older versions This commit solves two problems related to block entities on older versions: - Occasionally, tags would contain the ID under a StringTag with an empty value, and not the ID tag. - The block entity regex did not account for block entity tags that were already in a Bedrock-compatible format (BlockEntity) * Move BLOCK_ENTITY_TRANSLATIONS to BlockEntityTranslator --- .../block/entity/BlockEntityTranslator.java | 13 +++++++++ .../connector/utils/BlockEntityUtils.java | 27 ++++++++----------- .../geysermc/connector/utils/ChunkUtils.java | 22 ++++++++++++--- 3 files changed, 42 insertions(+), 20 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BlockEntityTranslator.java index 3d663926..c87938dd 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BlockEntityTranslator.java @@ -46,6 +46,19 @@ public abstract class BlockEntityTranslator { public static final Map BLOCK_ENTITY_TRANSLATORS = new HashMap<>(); public static ObjectArrayList REQUIRES_BLOCK_STATE_LIST = new ObjectArrayList<>(); + /** + * Contains a list of irregular block entity name translations that can't be fit into the regex + */ + public static final Map BLOCK_ENTITY_TRANSLATIONS = new HashMap() { + { + // Bedrock/Java differences + put("minecraft:enchanting_table", "EnchantTable"); + put("minecraft:piston_head", "PistonArm"); + put("minecraft:trapped_chest", "Chest"); + // There are some legacy IDs sent but as far as I can tell they are not needed for things to work properly + } + }; + protected BlockEntityTranslator() { } diff --git a/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java b/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java index 038084c3..3a356e03 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java @@ -12,29 +12,24 @@ public class BlockEntityUtils { public static String getBedrockBlockEntityId(String id) { // These are the only exceptions when it comes to block entity ids - if (id.contains("piston_head")) - return "PistonArm"; - - if (id.contains("trapped_chest")) - return "Chest"; - - if (id.contains("EnderChest")) - return "EnderChest"; - - if (id.contains("enchanting_table")) { - return "EnchantTable"; + if (BlockEntityTranslator.BLOCK_ENTITY_TRANSLATIONS.containsKey(id)) { + return BlockEntityTranslator.BLOCK_ENTITY_TRANSLATIONS.get(id); } - id = id.toLowerCase() - .replace("minecraft:", "") + id = id.replace("minecraft:", "") .replace("_", " "); - String[] words = id.split(" "); + // Split at every space or capital letter - for the latter, some legacy Java block entity tags are the correct format already + String[] words; + if (!id.toUpperCase().equals(id)) { // Otherwise we get [S, K, U, L, L] + words = id.split("(?=[A-Z])| "); // Split at every space or note or before every capital letter + } else { + words = id.split(" "); + } for (int i = 0; i < words.length; i++) { words[i] = words[i].substring(0, 1).toUpperCase() + words[i].substring(1).toLowerCase(); } - id = String.join(" ", words); - return id.replace(" ", ""); + return String.join("", words); } public static BlockEntityTranslator getBlockEntityTranslator(String name) { 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 010a87af..f86173e2 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java @@ -30,6 +30,8 @@ import com.github.steveice10.mc.protocol.data.game.chunk.Column; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.StringTag; +import com.github.steveice10.opennbt.tag.builtin.Tag; import com.nukkitx.math.vector.Vector2i; import com.nukkitx.math.vector.Vector3i; import com.nukkitx.nbt.CompoundTagBuilder; @@ -137,11 +139,23 @@ public class ChunkUtils { while (i < blockEntities.length) { CompoundTag tag = blockEntities[i]; String tagName; - if (!tag.contains("id")) { - GeyserConnector.getInstance().getLogger().debug("Got tag with no id: " + tag.getValue()); - tagName = "Empty"; - } else { + if (tag.contains("id")) { tagName = (String) tag.get("id").getValue(); + } else { + tagName = "Empty"; + // Sometimes legacy tags have their ID be a StringTag with empty value + for (Tag subTag : tag) { + if (subTag instanceof StringTag) { + StringTag stringTag = (StringTag) subTag; + if (stringTag.getValue().equals("")) { + tagName = stringTag.getName(); + break; + } + } + } + if (tagName.equals("Empty")) { + GeyserConnector.getInstance().getLogger().debug("Got tag with no id: " + tag.getValue()); + } } String id = BlockEntityUtils.getBedrockBlockEntityId(tagName);