From 0d1fedbdbfa0a1968ace97ea0435b630d6c4d31c Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sun, 24 Apr 2022 13:58:34 -0400 Subject: [PATCH 1/6] Fix instances of resizing global biome palettes Fixes #2744 --- .../geysermc/geyser/translator/level/BiomeTranslator.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/BiomeTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/BiomeTranslator.java index a202c3f81..ac9a0517a 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/BiomeTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/BiomeTranslator.java @@ -126,11 +126,10 @@ public class BiomeTranslator { storage = new BlockStorage(bitArray, bedrockPalette); } else { storage = new BlockStorage(0); - BitArray bitArray = storage.getBitArray(); // Each section of biome corresponding to a chunk section contains 4 * 4 * 4 entries for (int i = 0; i < 64; i++) { - int javaId = biomeData.getPalette().idToState(biomeData.getStorage().get(i)); + int javaId = palette.idToState(biomeData.getStorage().get(i)); int x = i & 3; int y = (i >> 4) & 3; int z = (i >> 2) & 3; @@ -139,7 +138,9 @@ public class BiomeTranslator { int idx = storage.idFor(biomeId); // Convert biome coordinates into block coordinates // Bedrock expects a full 4096 blocks - multiplyIdToStorage(bitArray, idx, x, y, z); + // Implementation note: storage.getBitArray() must be called and not stored - if the palette + // grows, then the instance can change + multiplyIdToStorage(storage.getBitArray(), idx, x, y, z); } } return storage; From 074d60d5b02cd0d0fc8deafe1a658f4aec15bdbd Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Mon, 25 Apr 2022 15:13:09 -0400 Subject: [PATCH 2/6] Add system locale and encoding to Geyser dumps --- .../src/main/java/org/geysermc/geyser/dump/DumpInfo.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/dump/DumpInfo.java b/core/src/main/java/org/geysermc/geyser/dump/DumpInfo.java index 2734c7443..ca902ea5c 100644 --- a/core/src/main/java/org/geysermc/geyser/dump/DumpInfo.java +++ b/core/src/main/java/org/geysermc/geyser/dump/DumpInfo.java @@ -54,10 +54,7 @@ import java.net.InetSocketAddress; import java.net.Socket; import java.net.UnknownHostException; import java.nio.file.Paths; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Properties; +import java.util.*; import java.util.stream.Collectors; @Getter @@ -67,6 +64,8 @@ public class DumpInfo { private final DumpInfo.VersionInfo versionInfo; private final int cpuCount; + private final Locale systemLocale; + private final String systemEncoding; private Properties gitInfo; private final GeyserConfiguration config; private final Floodgate floodgate; @@ -81,6 +80,8 @@ public class DumpInfo { this.versionInfo = new VersionInfo(); this.cpuCount = Runtime.getRuntime().availableProcessors(); + this.systemLocale = Locale.getDefault(); + this.systemEncoding = System.getProperty("file.encoding"); try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResource("git.properties")) { this.gitInfo = new Properties(); From 3035527be21583a207849bef7a3bce5ba6b790f8 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Wed, 27 Apr 2022 20:04:13 -0400 Subject: [PATCH 3/6] Indicate 1.18.31 support for Geyser This uses the same protocol version as 1.18.30, so no further changes are required. --- README.md | 2 +- .../java/org/geysermc/geyser/network/MinecraftProtocol.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bbb9532a5..3e247f4b5 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ The ultimate goal of this project is to allow Minecraft: Bedrock Edition users t Special thanks to the DragonProxy project for being a trailblazer in protocol translation and for all the team members who have joined us here! -### Currently supporting Minecraft Bedrock 1.18.0 - 1.18.30 and Minecraft Java 1.18.2. +### Currently supporting Minecraft Bedrock 1.18.0 - 1.18.31 and Minecraft Java 1.18.2. ## Setting Up Take a look [here](https://wiki.geysermc.org/geyser/setup/) for how to set up Geyser. diff --git a/core/src/main/java/org/geysermc/geyser/network/MinecraftProtocol.java b/core/src/main/java/org/geysermc/geyser/network/MinecraftProtocol.java index 0f5782f86..828b04a9d 100644 --- a/core/src/main/java/org/geysermc/geyser/network/MinecraftProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/MinecraftProtocol.java @@ -62,7 +62,9 @@ public final class MinecraftProtocol { SUPPORTED_BEDROCK_CODECS.add(Bedrock_v486.V486_CODEC.toBuilder() .minecraftVersion("1.18.10/1.18.12") // 1.18.11 is also supported, but was only on Switch and since that auto-updates it's not needed .build()); - SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC); + SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC.toBuilder() + .minecraftVersion("1.18.30/1.18.31") + .build()); } /** From 8a1799e0e3d16177b5e358710b4e8ae0e3fab24e Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Fri, 29 Apr 2022 13:24:58 -0400 Subject: [PATCH 4/6] Remove block tag adding to villager trading Fixes sugar cane being untradeable. --- .../populator/BlockRegistryPopulator.java | 6 ------ .../geyser/registry/type/BlockMappings.java | 15 --------------- .../inventory/JavaMerchantOffersTranslator.java | 8 ++------ 3 files changed, 2 insertions(+), 27 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java index d8aa6a456..412d7d779 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java @@ -132,7 +132,6 @@ public class BlockRegistryPopulator { } catch (Exception e) { throw new AssertionError("Unable to get blocks from runtime block states", e); } - Map javaIdentifierToBedrockTag = new Object2ObjectOpenHashMap<>(blocksTag.size()); // New since 1.16.100 - find the block runtime ID by the order given to us in the block palette, // as we no longer send a block palette Object2IntMap blockStateOrderedMap = new Object2IntOpenHashMap<>(blocksTag.size()); @@ -202,10 +201,6 @@ public class BlockRegistryPopulator { flowerPotBlocks.put(cleanJavaIdentifier.intern(), blocksTag.get(bedrockRuntimeId)); } - if (!cleanJavaIdentifier.equals(entry.getValue().get("bedrock_identifier").asText())) { - javaIdentifierToBedrockTag.put(cleanJavaIdentifier.intern(), blocksTag.get(bedrockRuntimeId)); - } - javaToBedrockBlocks[javaRuntimeId] = bedrockRuntimeId; } @@ -240,7 +235,6 @@ public class BlockRegistryPopulator { BlockRegistries.BLOCKS.register(palette.getKey().valueInt(), builder.blockStateVersion(stateVersion) .javaToBedrockBlocks(javaToBedrockBlocks) - .javaIdentifierToBedrockTag(javaIdentifierToBedrockTag) .itemFrames(itemFrames) .flowerPotBlocks(flowerPotBlocks) .jigsawStateIds(jigsawStateIds) diff --git a/core/src/main/java/org/geysermc/geyser/registry/type/BlockMappings.java b/core/src/main/java/org/geysermc/geyser/registry/type/BlockMappings.java index a105682a6..41318ee64 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/type/BlockMappings.java +++ b/core/src/main/java/org/geysermc/geyser/registry/type/BlockMappings.java @@ -47,12 +47,6 @@ public class BlockMappings { NbtList bedrockBlockStates; - /** - * Contains a map of Java blocks to their respective Bedrock block tag, if the Java identifier is different from Bedrock. - * Required to fix villager trades with these blocks. - */ - Map javaIdentifierToBedrockTag; - int commandBlockRuntimeId; Object2IntMap itemFrames; @@ -74,13 +68,4 @@ public class BlockMappings { public boolean isItemFrame(int bedrockBlockRuntimeId) { return this.itemFrames.values().contains(bedrockBlockRuntimeId); } - - /** - * @param cleanJavaIdentifier the clean Java identifier of the block to look up - * - * @return the block tag of the block name mapped from Java to Bedrock. - */ - public NbtMap getBedrockBlockNbt(String cleanJavaIdentifier) { - return this.javaIdentifierToBedrockTag.get(cleanJavaIdentifier); - } } \ No newline at end of file diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaMerchantOffersTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaMerchantOffersTranslator.java index 8af5c8af1..1c9ded0c1 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaMerchantOffersTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaMerchantOffersTranslator.java @@ -178,12 +178,8 @@ public class JavaMerchantOffersTranslator extends PacketTranslator Date: Sat, 30 Apr 2022 20:40:34 -0400 Subject: [PATCH 5/6] Fix lava and snow cauldrons looking wrong Fixes #2955 --- .../geyser/level/block/BlockStateValues.java | 18 +++++++++- .../block/entity/BedrockOnlyBlockEntity.java | 15 ++++++++ .../JavaLevelChunkWithLightTranslator.java | 22 ++++++------ .../geyser/util/BlockEntityUtils.java | 35 ++++++++----------- 4 files changed, 58 insertions(+), 32 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/level/block/BlockStateValues.java b/core/src/main/java/org/geysermc/geyser/level/block/BlockStateValues.java index 48d0e80e0..34569c5af 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/BlockStateValues.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/BlockStateValues.java @@ -46,6 +46,7 @@ import java.util.Locale; public final class BlockStateValues { private static final Int2IntMap BANNER_COLORS = new FixedInt2IntMap(); private static final Int2ByteMap BED_COLORS = new FixedInt2ByteMap(); + private static final IntSet NON_WATER_CAULDRONS = new IntOpenHashSet(); private static final Int2ByteMap COMMAND_BLOCK_VALUES = new Int2ByteOpenHashMap(); private static final Int2ObjectMap DOUBLE_CHEST_VALUES = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap FLOWER_POT_VALUES = new Int2ObjectOpenHashMap<>(); @@ -62,6 +63,7 @@ public final class BlockStateValues { private static final Int2ByteMap SKULL_ROTATIONS = new Int2ByteOpenHashMap(); private static final Int2IntMap SKULL_WALL_DIRECTIONS = new Int2IntOpenHashMap(); private static final Int2ByteMap SHULKERBOX_DIRECTIONS = new FixedInt2ByteMap(); + private static final IntSet WATER_CAULDRONS = new IntOpenHashSet(); private static final Int2IntMap WATER_LEVEL = new Int2IntOpenHashMap(); public static final int JAVA_AIR_ID = 0; @@ -176,7 +178,7 @@ public final class BlockStateValues { return; } - if (javaId.startsWith("minecraft:water")) { + if (javaId.startsWith("minecraft:water") && !javaId.contains("cauldron")) { String strLevel = javaId.substring(javaId.lastIndexOf("level=") + 6, javaId.length() - 1); int level = Integer.parseInt(strLevel); WATER_LEVEL.put(javaBlockState, level); @@ -189,6 +191,11 @@ public final class BlockStateValues { if (direction.isHorizontal()) { HORIZONTAL_FACING_JIGSAWS.add(javaBlockState); } + return; + } + + if (javaId.contains("_cauldron") && !javaId.contains("water_")) { + NON_WATER_CAULDRONS.add(javaBlockState); } } @@ -214,6 +221,15 @@ public final class BlockStateValues { return BED_COLORS.getOrDefault(state, (byte) -1); } + /** + * Non-water cauldrons (since Bedrock 1.18.30) must have a block entity packet sent on chunk load to fix rendering issues. + * + * @return if this Java block state is a non-empty non-water cauldron + */ + public static boolean isCauldron(int state) { + return NON_WATER_CAULDRONS.contains(state); + } + /** * The block state in Java and Bedrock both contain the conditional bit, however command block block entity tags * in Bedrock need the conditional information. diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BedrockOnlyBlockEntity.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BedrockOnlyBlockEntity.java index 0ec7219c3..94760b66c 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BedrockOnlyBlockEntity.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BedrockOnlyBlockEntity.java @@ -26,7 +26,10 @@ package org.geysermc.geyser.translator.level.block.entity; import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.nbt.NbtList; import com.nukkitx.nbt.NbtMap; +import com.nukkitx.nbt.NbtType; +import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.session.GeyserSession; /** @@ -59,6 +62,18 @@ public interface BedrockOnlyBlockEntity extends RequiresBlockState { return FlowerPotBlockEntityTranslator.getTag(session, blockState, position); } else if (PistonBlockEntityTranslator.isBlock(blockState)) { return PistonBlockEntityTranslator.getTag(blockState, position); + } else if (BlockStateValues.isCauldron(blockState)) { + // As of 1.18.30: this is required to make rendering not look weird on chunk load (lava and snow cauldrons look dim) + return NbtMap.builder() + .putString("id", "Cauldron") + .putByte("isMovable", (byte) 0) + .putShort("PotionId", (short) -1) + .putShort("PotionType", (short) -1) + .putList("Items", NbtType.END, NbtList.EMPTY) + .putInt("x", position.getX()) + .putInt("y", position.getY()) + .putInt("z", position.getZ()) + .build(); } return null; } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelChunkWithLightTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelChunkWithLightTranslator.java index 165d90b36..3855b1139 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelChunkWithLightTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelChunkWithLightTranslator.java @@ -99,7 +99,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator bedrockBlockEntities = new ObjectArrayList<>(blockEntities.length); BitSet waterloggedPaletteIds = new BitSet(); - BitSet pistonOrFlowerPaletteIds = new BitSet(); + BitSet bedrockOnlyBlockEntityIds = new BitSet(); BedrockDimension bedrockDimension = session.getChunkCache().getBedrockDimension(); int maxBedrockSectionY = (bedrockDimension.height() >> 4) - 1; @@ -144,7 +144,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator> 8) & 0xF), (packet.getZ() << 4) + ((yzx >> 4) & 0xF)), javaId @@ -173,7 +173,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator> 8) & 0xF), (packet.getZ() << 4) + ((yzx >> 4) & 0xF)), javaPalette.idToState(paletteId) @@ -233,9 +233,9 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator BEDROCK_ONLY_BLOCK_ENTITIES = new ObjectArrayList<>(); + public static final List BEDROCK_ONLY_BLOCK_ENTITIES = List.of( + (BedrockOnlyBlockEntity) Registries.BLOCK_ENTITIES.get().get(BlockEntityType.CHEST), + new FlowerPotBlockEntityTranslator() + ); /** * 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<>() { - { + public static final Map BLOCK_ENTITY_TRANSLATIONS = Map.of( // Bedrock/Java differences - put(BlockEntityType.ENCHANTING_TABLE, "EnchantTable"); - put(BlockEntityType.JIGSAW, "JigsawBlock"); - put(BlockEntityType.PISTON, "PistonArm"); - put(BlockEntityType.TRAPPED_CHEST, "Chest"); + BlockEntityType.ENCHANTING_TABLE, "EnchantTable", + BlockEntityType.JIGSAW, "JigsawBlock", + BlockEntityType.PISTON, "PistonArm", + BlockEntityType.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 - } - }; - - static { - // Seeing as there are only two - and, hopefully, will only ever be two - we can hardcode this - BEDROCK_ONLY_BLOCK_ENTITIES.add((BedrockOnlyBlockEntity) Registries.BLOCK_ENTITIES.get().get(BlockEntityType.CHEST)); - BEDROCK_ONLY_BLOCK_ENTITIES.add(new FlowerPotBlockEntityTranslator()); - } + ); public static String getBedrockBlockEntityId(BlockEntityType type) { // These are the only exceptions when it comes to block entity ids @@ -77,9 +72,9 @@ public class BlockEntityUtils { String id = type.name(); // Split at every space or capital letter - for the latter, some legacy Java block entity tags are the correct format already - String[] words = id.split("_");; + String[] words = id.split("_"); for (int i = 0; i < words.length; i++) { - words[i] = words[i].substring(0, 1).toUpperCase() + words[i].substring(1).toLowerCase(); + words[i] = words[i].substring(0, 1).toUpperCase(Locale.ROOT) + words[i].substring(1).toLowerCase(Locale.ROOT); } return String.join("", words); From 31a84ea302671904cd405ea82cffb277d99c5d0b Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sat, 30 Apr 2022 20:42:29 -0400 Subject: [PATCH 6/6] Remove unused set --- .../java/org/geysermc/geyser/level/block/BlockStateValues.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/level/block/BlockStateValues.java b/core/src/main/java/org/geysermc/geyser/level/block/BlockStateValues.java index 34569c5af..a9b3ffedc 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/BlockStateValues.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/BlockStateValues.java @@ -46,12 +46,12 @@ import java.util.Locale; public final class BlockStateValues { private static final Int2IntMap BANNER_COLORS = new FixedInt2IntMap(); private static final Int2ByteMap BED_COLORS = new FixedInt2ByteMap(); - private static final IntSet NON_WATER_CAULDRONS = new IntOpenHashSet(); private static final Int2ByteMap COMMAND_BLOCK_VALUES = new Int2ByteOpenHashMap(); private static final Int2ObjectMap DOUBLE_CHEST_VALUES = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap FLOWER_POT_VALUES = new Int2ObjectOpenHashMap<>(); private static final IntSet HORIZONTAL_FACING_JIGSAWS = new IntOpenHashSet(); private static final LecternHasBookMap LECTERN_BOOK_STATES = new LecternHasBookMap(); + private static final IntSet NON_WATER_CAULDRONS = new IntOpenHashSet(); private static final Int2IntMap NOTEBLOCK_PITCHES = new FixedInt2IntMap(); private static final Int2BooleanMap PISTON_VALUES = new Int2BooleanOpenHashMap(); private static final IntSet STICKY_PISTONS = new IntOpenHashSet(); @@ -63,7 +63,6 @@ public final class BlockStateValues { private static final Int2ByteMap SKULL_ROTATIONS = new Int2ByteOpenHashMap(); private static final Int2IntMap SKULL_WALL_DIRECTIONS = new Int2IntOpenHashMap(); private static final Int2ByteMap SHULKERBOX_DIRECTIONS = new FixedInt2ByteMap(); - private static final IntSet WATER_CAULDRONS = new IntOpenHashSet(); private static final Int2IntMap WATER_LEVEL = new Int2IntOpenHashMap(); public static final int JAVA_AIR_ID = 0;