From 3f42d68f4e854c924292d2194e4bd58de8c4b630 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sun, 30 Oct 2022 11:34:08 -0500 Subject: [PATCH] Update to latest Protocol changes & cleanup item registry populator --- .../entity/type/FallingBlockEntity.java | 2 +- .../geyser/entity/type/ItemFrameEntity.java | 9 +- .../holder/BlockInventoryHolder.java | 4 +- .../CreativeItemRegistryPopulator.java | 131 ++++++++++ .../CustomItemRegistryPopulator.java | 53 ++++- .../populator/ItemRegistryPopulator.java | 225 +++++------------- .../populator/RecipeRegistryPopulator.java | 2 +- .../geyser/registry/type/BlockMappings.java | 15 +- .../geyser/registry/type/ItemMapping.java | 8 +- .../geyser/registry/type/ItemMappings.java | 4 +- .../chest/DoubleChestInventoryTranslator.java | 11 +- .../inventory/item/ItemTranslator.java | 28 ++- .../FlowerPotBlockEntityTranslator.java | 2 +- .../level/block/entity/PistonBlockEntity.java | 2 +- ...BedrockInventoryTransactionTranslator.java | 8 +- .../org/geysermc/geyser/util/ChunkUtils.java | 11 +- 16 files changed, 307 insertions(+), 208 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/registry/populator/CreativeItemRegistryPopulator.java diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/FallingBlockEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/FallingBlockEntity.java index 6f3c99d74..e6d3a5783 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/FallingBlockEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/FallingBlockEntity.java @@ -39,7 +39,7 @@ public class FallingBlockEntity extends Entity { public FallingBlockEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw, int javaId) { super(session, entityId, geyserId, uuid, EntityDefinitions.FALLING_BLOCK, position, motion, yaw, pitch, headYaw); - this.dirtyMetadata.put(EntityDataTypes.VARIANT, session.getBlockMappings().getBedrockBlockId(javaId)); + this.dirtyMetadata.put(EntityDataTypes.BLOCK, session.getBlockMappings().getBedrockBlock(javaId)); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/ItemFrameEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ItemFrameEntity.java index cbe70f162..cfec93c15 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/ItemFrameEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/ItemFrameEntity.java @@ -35,6 +35,7 @@ import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; import com.nukkitx.nbt.NbtMap; import com.nukkitx.nbt.NbtMapBuilder; +import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket; import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket; @@ -59,7 +60,7 @@ public class ItemFrameEntity extends Entity { /** * Specific block 'state' we are emulating in Bedrock. */ - private final int bedrockRuntimeId; + private final BlockDefinition blockDefinition; /** * Rotation of item in frame. */ @@ -90,7 +91,7 @@ public class ItemFrameEntity extends Entity { .putByte("item_frame_photo_bit", (byte) 0); blockBuilder.put("states", statesBuilder.build()); - bedrockRuntimeId = session.getBlockMappings().getItemFrame(blockBuilder.build()); + blockDefinition = session.getBlockMappings().getItemFrame(blockBuilder.build()); bedrockPosition = Vector3i.from(position.getFloorX(), position.getFloorY(), position.getFloorZ()); session.getItemFrameCache().put(bedrockPosition, this); @@ -152,7 +153,7 @@ public class ItemFrameEntity extends Entity { UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); updateBlockPacket.setDataLayer(0); updateBlockPacket.setBlockPosition(bedrockPosition); - updateBlockPacket.setRuntimeId(session.getBlockMappings().getBedrockAir().getRuntimeId()); //TODO maybe set this to the world block or another item frame? + updateBlockPacket.setDefinition(session.getBlockMappings().getBedrockAir()); //TODO maybe set this to the world block or another item frame? updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS); @@ -190,7 +191,7 @@ public class ItemFrameEntity extends Entity { UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); updateBlockPacket.setDataLayer(0); updateBlockPacket.setBlockPosition(bedrockPosition); - updateBlockPacket.setRuntimeId(bedrockRuntimeId); + updateBlockPacket.setDefinition(blockDefinition); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS); diff --git a/core/src/main/java/org/geysermc/geyser/inventory/holder/BlockInventoryHolder.java b/core/src/main/java/org/geysermc/geyser/inventory/holder/BlockInventoryHolder.java index 6c0396ec7..4cc039761 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/holder/BlockInventoryHolder.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/holder/BlockInventoryHolder.java @@ -93,7 +93,7 @@ public class BlockInventoryHolder extends InventoryHolder { UpdateBlockPacket blockPacket = new UpdateBlockPacket(); blockPacket.setDataLayer(0); blockPacket.setBlockPosition(position); - blockPacket.setRuntimeId(session.getBlockMappings().getBedrockBlockId(defaultJavaBlockState)); + blockPacket.setDefinition(session.getBlockMappings().getBedrockBlock(defaultJavaBlockState)); blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY); session.sendUpstreamPacket(blockPacket); inventory.setHolderPosition(position); @@ -157,7 +157,7 @@ public class BlockInventoryHolder extends InventoryHolder { UpdateBlockPacket blockPacket = new UpdateBlockPacket(); blockPacket.setDataLayer(0); blockPacket.setBlockPosition(holderPos); - blockPacket.setRuntimeId(session.getBlockMappings().getBedrockBlockId(realBlock)); + blockPacket.setDefinition(session.getBlockMappings().getBedrockBlock(realBlock)); blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY); session.sendUpstreamPacket(blockPacket); } diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/CreativeItemRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/CreativeItemRegistryPopulator.java new file mode 100644 index 000000000..578c83f49 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/CreativeItemRegistryPopulator.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2019-2022 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.geyser.registry.populator; + +import com.fasterxml.jackson.databind.JsonNode; +import com.nukkitx.nbt.NbtMap; +import com.nukkitx.nbt.NbtUtils; +import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition; +import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; +import org.geysermc.geyser.GeyserBootstrap; +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.registry.BlockRegistries; +import org.geysermc.geyser.registry.type.BlockMappings; +import org.geysermc.geyser.registry.type.ItemMappings; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Base64; +import java.util.List; +import java.util.Map; +import java.util.function.BiPredicate; +import java.util.function.Consumer; + +public class CreativeItemRegistryPopulator { + private static final List> JAVA_ONLY_ITEM_FILTER = List.of( + // Just shows an empty texture; either way it doesn't exist in the creative menu on Java + (identifier, data) -> identifier.equals("minecraft:debug_stick"), + // Bedrock-only as its own item + (identifier, data) -> identifier.equals("minecraft:empty_map") && data == 2, + // Bedrock-only banner patterns + (identifier, data) -> identifier.equals("minecraft:bordure_indented_banner_pattern") || identifier.equals("minecraft:field_masoned_banner_pattern") + ); + + public static void populate(Map.Entry version, Map definitions, Consumer itemConsumer) { + GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap(); + + // Load creative items + JsonNode creativeItemEntries; + try (InputStream stream = bootstrap.getResource(String.format("bedrock/creative_items.%s.json", version.getKey()))) { + creativeItemEntries = GeyserImpl.JSON_MAPPER.readTree(stream).get("items"); + } catch (Exception e) { + throw new AssertionError("Unable to load creative items", e); + } + + BlockMappings blockMappings = BlockRegistries.BLOCKS.forVersion(version.getValue().protocolVersion()); + for (JsonNode itemNode : creativeItemEntries) { + ItemData.Builder itemBuilder = createItemData(itemNode, blockMappings, definitions); + if (itemBuilder == null) { + continue; + } + + itemConsumer.accept(itemBuilder); + } + } + + private static ItemData.Builder createItemData(JsonNode itemNode, BlockMappings blockMappings, Map definitions) { + int count = 1; + int damage = 0; + int blockRuntimeId = 0; + NbtMap tag = null; + JsonNode damageNode = itemNode.get("damage"); + if (damageNode != null) { + damage = damageNode.asInt(); + } + + JsonNode countNode = itemNode.get("count"); + if (countNode != null) { + count = countNode.asInt(); + } + + JsonNode blockRuntimeIdNode = itemNode.get("blockRuntimeId"); + if (blockRuntimeIdNode != null) { + blockRuntimeId = blockRuntimeIdNode.asInt(); + } + + JsonNode nbtNode = itemNode.get("nbt_b64"); + if (nbtNode != null) { + byte[] bytes = Base64.getDecoder().decode(nbtNode.asText()); + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + try { + tag = (NbtMap) NbtUtils.createReaderLE(bais).readTag(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + String identifier = itemNode.get("id").textValue(); + for (BiPredicate predicate : JAVA_ONLY_ITEM_FILTER) { + if (predicate.test(identifier, damage)) { + return null; + } + } + + ItemDefinition definition = definitions.get(identifier); + if (definition == null) { + GeyserImpl.getInstance().getLogger().debug("Unknown item definition with identifier " + identifier + " when loading creative items!"); + return null; + } + + return ItemData.builder() + .definition(definition) + .damage(damage) + .count(count) + .tag(tag) + .blockDefinition(blockMappings.getBedrockBlock(blockRuntimeId)); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomItemRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomItemRegistryPopulator.java index d570f904e..5bd43607b 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomItemRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomItemRegistryPopulator.java @@ -25,20 +25,24 @@ package org.geysermc.geyser.registry.populator; +import com.google.common.collect.Multimap; import com.nukkitx.nbt.NbtMap; import com.nukkitx.nbt.NbtMapBuilder; import com.nukkitx.nbt.NbtType; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData; -import org.cloudburstmc.protocol.bedrock.packet.StartGamePacket; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.item.custom.CustomItemData; import org.geysermc.geyser.api.item.custom.CustomRenderOffsets; import org.geysermc.geyser.api.item.custom.NonVanillaCustomItemData; import org.geysermc.geyser.api.util.TriState; +import org.geysermc.geyser.event.type.GeyserDefineCustomItemsEventImpl; import org.geysermc.geyser.item.GeyserCustomMappingData; import org.geysermc.geyser.item.components.ToolBreakSpeedsUtils; import org.geysermc.geyser.item.components.WearableSlot; +import org.geysermc.geyser.item.mappings.MappingsConfigReader; import org.geysermc.geyser.registry.type.GeyserMappingItem; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.NonVanillaItemRegistration; @@ -50,6 +54,51 @@ import java.util.Map; import java.util.OptionalInt; public class CustomItemRegistryPopulator { + public static void populate(Map items, Multimap customItems, List nonVanillaCustomItems) { + MappingsConfigReader mappingsConfigReader = new MappingsConfigReader(); + // Load custom items from mappings files + mappingsConfigReader.loadMappingsFromJson((key, item) -> { + if (CustomItemRegistryPopulator.initialCheck(key, item, items)) { + customItems.get(key).add(item); + } + }); + + GeyserImpl.getInstance().eventBus().fire(new GeyserDefineCustomItemsEventImpl(customItems, nonVanillaCustomItems) { + @Override + public boolean register(@NonNull String identifier, @NonNull CustomItemData customItemData) { + if (CustomItemRegistryPopulator.initialCheck(identifier, customItemData, items)) { + customItems.get(identifier).add(customItemData); + return true; + } + return false; + } + + @Override + public boolean register(@NonNull NonVanillaCustomItemData customItemData) { + if (customItemData.identifier().startsWith("minecraft:")) { + GeyserImpl.getInstance().getLogger().error("The custom item " + customItemData.identifier() + + " is attempting to masquerade as a vanilla Minecraft item!"); + return false; + } + + if (customItemData.javaId() < items.size()) { + // Attempting to overwrite an item that already exists in the protocol + GeyserImpl.getInstance().getLogger().error("The custom item " + customItemData.identifier() + + " is attempting to overwrite a vanilla Minecraft item!"); + return false; + } + + nonVanillaCustomItems.add(customItemData); + return true; + } + }); + + int customItemCount = customItems.size() + nonVanillaCustomItems.size(); + if (customItemCount > 0) { + GeyserImpl.getInstance().getLogger().info("Registered " + customItemCount + " custom items"); + } + } + public static GeyserCustomMappingData registerCustomItem(String customItemName, GeyserMappingItem javaItem, CustomItemData customItemData, int bedrockId) { ItemDefinition itemDefinition = new ItemDefinition(customItemName, bedrockId, true); @@ -86,7 +135,7 @@ public class CustomItemRegistryPopulator { .javaId(customItemData.javaId()) .bedrockDefinition(new ItemDefinition(customIdentifier, customItemId, true)) .bedrockData(0) - .bedrockBlockId(0) + .bedrockBlockDefinition(null) .stackSize(customItemData.stackSize()) .toolType(customItemData.toolType()) .toolTier(customItemData.toolTier()) diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java index d876c4063..372b842fa 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java @@ -26,13 +26,11 @@ package org.geysermc.geyser.registry.populator; import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.JsonNode; import com.google.common.collect.Multimap; import com.google.common.collect.MultimapBuilder; import com.nukkitx.nbt.NbtMap; import com.nukkitx.nbt.NbtMapBuilder; import com.nukkitx.nbt.NbtType; -import com.nukkitx.nbt.NbtUtils; import it.unimi.dsi.fastutil.Pair; import it.unimi.dsi.fastutil.ints.Int2IntMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; @@ -45,7 +43,6 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.protocol.bedrock.codec.v527.Bedrock_v527; import org.cloudburstmc.protocol.bedrock.codec.v534.Bedrock_v534; import org.cloudburstmc.protocol.bedrock.codec.v544.Bedrock_v544; @@ -60,10 +57,8 @@ import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.item.custom.CustomItemData; import org.geysermc.geyser.api.item.custom.CustomItemOptions; import org.geysermc.geyser.api.item.custom.NonVanillaCustomItemData; -import org.geysermc.geyser.event.type.GeyserDefineCustomItemsEventImpl; import org.geysermc.geyser.inventory.item.StoredItemMappings; import org.geysermc.geyser.item.GeyserCustomMappingData; -import org.geysermc.geyser.item.mappings.MappingsConfigReader; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.type.BlockMappings; @@ -75,24 +70,22 @@ import org.geysermc.geyser.registry.type.PaletteItem; import org.geysermc.geyser.util.ItemUtils; import org.geysermc.geyser.util.collection.FixedInt2IntMap; -import java.io.ByteArrayInputStream; -import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; -import java.util.Base64; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; /** * Populates the item registries. */ public class ItemRegistryPopulator { - private record PaletteVersion(int protocolVersion, Map additionalTranslatedItems) { + record PaletteVersion(int protocolVersion, Map additionalTranslatedItems) { } public static void populate() { @@ -120,48 +113,10 @@ public class ItemRegistryPopulator { // (as of 1.19.2 Java) to replicate some edge cases in Java predicate behavior where it checks from the bottom // of the list first, then ascends. Multimap customItems = MultimapBuilder.hashKeys().arrayListValues().build(); - List nonVanillaCustomItems; + List nonVanillaCustomItems = customItemsAllowed ? new ObjectArrayList<>() : Collections.emptyList(); - MappingsConfigReader mappingsConfigReader = new MappingsConfigReader(); if (customItemsAllowed) { - // Load custom items from mappings files - mappingsConfigReader.loadMappingsFromJson((key, item) -> { - if (CustomItemRegistryPopulator.initialCheck(key, item, items)) { - customItems.get(key).add(item); - } - }); - - nonVanillaCustomItems = new ObjectArrayList<>(); - GeyserImpl.getInstance().eventBus().fire(new GeyserDefineCustomItemsEventImpl(customItems, nonVanillaCustomItems) { - @Override - public boolean register(@NonNull String identifier, @NonNull CustomItemData customItemData) { - if (CustomItemRegistryPopulator.initialCheck(identifier, customItemData, items)) { - customItems.get(identifier).add(customItemData); - return true; - } - return false; - } - - @Override - public boolean register(@NonNull NonVanillaCustomItemData customItemData) { - if (customItemData.identifier().startsWith("minecraft:")) { - GeyserImpl.getInstance().getLogger().error("The custom item " + customItemData.identifier() + - " is attempting to masquerade as a vanilla Minecraft item!"); - return false; - } - - if (customItemData.javaId() < items.size()) { - // Attempting to overwrite an item that already exists in the protocol - GeyserImpl.getInstance().getLogger().error("The custom item " + customItemData.identifier() + - " is attempting to overwrite a vanilla Minecraft item!"); - return false; - } - nonVanillaCustomItems.add(customItemData); - return true; - } - }); - } else { - nonVanillaCustomItems = Collections.emptyList(); + CustomItemRegistryPopulator.populate(items, customItems, nonVanillaCustomItems); } int customItemCount = customItems.size() + nonVanillaCustomItems.size(); @@ -209,15 +164,6 @@ public class ItemRegistryPopulator { Object2IntMap bedrockBlockIdOverrides = new Object2IntOpenHashMap<>(); Object2IntMap blacklistedIdentifiers = new Object2IntOpenHashMap<>(); - // Load creative items - // We load this before item mappings to get overridden block runtime ID mappings - JsonNode creativeItemEntries; - try (InputStream stream = bootstrap.getResource(String.format("bedrock/creative_items.%s.json", palette.getKey()))) { - creativeItemEntries = GeyserImpl.JSON_MAPPER.readTree(stream).get("items"); - } catch (Exception e) { - throw new AssertionError("Unable to load creative items", e); - } - List boats = new ObjectArrayList<>(); List buckets = new ObjectArrayList<>(); List spawnEggs = new ObjectArrayList<>(); @@ -225,74 +171,31 @@ public class ItemRegistryPopulator { List mappings = new ObjectArrayList<>(); // Temporary mapping to create stored items - Map identifierToMapping = new Object2ObjectOpenHashMap<>(); + Map javaIdentifierToMapping = new Object2ObjectOpenHashMap<>(); - int netId = 1; List creativeItems = new ArrayList<>(); - for (JsonNode itemNode : creativeItemEntries) { - int count = 1; - int damage = 0; - int blockRuntimeId = 0; - NbtMap tag = null; - JsonNode damageNode = itemNode.get("damage"); - if (damageNode != null) { - damage = damageNode.asInt(); - } - JsonNode countNode = itemNode.get("count"); - if (countNode != null) { - count = countNode.asInt(); - } - JsonNode blockRuntimeIdNode = itemNode.get("blockRuntimeId"); - if (blockRuntimeIdNode != null) { - blockRuntimeId = blockRuntimeIdNode.asInt(); - } - JsonNode nbtNode = itemNode.get("nbt_b64"); - if (nbtNode != null) { - byte[] bytes = Base64.getDecoder().decode(nbtNode.asText()); - ByteArrayInputStream bais = new ByteArrayInputStream(bytes); - try { - tag = (NbtMap) NbtUtils.createReaderLE(bais).readTag(); - } catch (IOException e) { - e.printStackTrace(); - } - } - String identifier = itemNode.get("id").textValue(); - if (identifier.equals("minecraft:debug_stick")) { - // Just shows an empty texture; either way it doesn't exist in the creative menu on Java - continue; - } else if (identifier.equals("minecraft:empty_map") && damage == 2) { - // Bedrock-only as its own item - continue; - } else if (identifier.equals("minecraft:bordure_indented_banner_pattern") || identifier.equals("minecraft:field_masoned_banner_pattern")) { - // Bedrock-only banner patterns - continue; - } + AtomicInteger creativeNetId = new AtomicInteger(); + CreativeItemRegistryPopulator.populate(palette, definitions, itemBuilder -> { + ItemData item = itemBuilder.netId(creativeNetId.getAndIncrement()).build(); + creativeItems.add(item); - ItemDefinition definition = definitions.get(identifier); - creativeItems.add(ItemData.builder() - .definition(definition) - .damage(damage) - .count(count) - .blockRuntimeId(blockRuntimeId) - .tag(tag) - .netId(netId++) - .build()); + if (item.getBlockDefinition() != null) { + String identifier = item.getDefinition().getIdentifier(); - if (blockRuntimeId != 0) { // Add override for item mapping, unless it already exists... then we know multiple states can exist if (!blacklistedIdentifiers.containsKey(identifier)) { if (bedrockBlockIdOverrides.containsKey(identifier)) { bedrockBlockIdOverrides.removeInt(identifier); // Save this as a blacklist, but also as knowledge of what the block state name should be - blacklistedIdentifiers.put(identifier, blockRuntimeId); + blacklistedIdentifiers.put(identifier, item.getBlockDefinition().getRuntimeId()); } else { // Unless there's multiple possibilities for this one state, let this be - bedrockBlockIdOverrides.put(identifier, blockRuntimeId); + bedrockBlockIdOverrides.put(identifier, item.getBlockDefinition().getRuntimeId()); } } } - } + }); BlockMappings blockMappings = BlockRegistries.BLOCKS.forVersion(palette.getValue().protocolVersion()); @@ -435,7 +338,7 @@ public class ItemRegistryPopulator { break; } - NbtMap states = blockMappings.getBedrockBlockPalette().get(itemData.getBlockRuntimeId()).getCompound("states"); + NbtMap states = blockMappings.getBedrockBlockPalette().get(itemData.getBlockDefinition().getRuntimeId()).getCompound("states"); boolean valid = true; for (Map.Entry nbtEntry : requiredBlockStates.entrySet()) { if (!states.get(nbtEntry.getKey()).equals(nbtEntry.getValue())) { @@ -445,7 +348,7 @@ public class ItemRegistryPopulator { } } if (valid) { - creativeItems.set(j, itemData.toBuilder().blockRuntimeId(bedrockBlockId).build()); + creativeItems.set(j, itemData.toBuilder().blockDefinition(blockMappings.getBedrockBlock(bedrockBlockId)).build()); break; } } @@ -460,7 +363,7 @@ public class ItemRegistryPopulator { .bedrockIdentifier(bedrockIdentifier.intern()) .bedrockDefinition(definition) .bedrockData(mappingItem.getBedrockData()) - .bedrockBlockId(bedrockBlockId) + .bedrockBlockDefinition(blockMappings.getBedrockBlock(bedrockBlockId)) .stackSize(stackSize) .maxDamage(mappingItem.getMaxDamage()) .hasSuspiciousStewEffect(mappingItem.isHasSuspiciousStewEffect()); @@ -534,7 +437,7 @@ public class ItemRegistryPopulator { .definition(definition) .damage(mapping.getBedrockData()) .count(1) - .blockRuntimeId(mapping.getBedrockBlockId()) + .blockDefinition(mapping.getBedrockBlockDefinition()) .build()); } else if (javaIdentifier.startsWith("minecraft:music_disc_")) { // The Java record level event uses the item ID as the "key" to play the record @@ -545,7 +448,7 @@ public class ItemRegistryPopulator { } mappings.add(mapping); - identifierToMapping.put(javaIdentifier, mapping); + javaIdentifierToMapping.put(javaIdentifier, mapping); itemNames.add(javaIdentifier); @@ -570,16 +473,14 @@ public class ItemRegistryPopulator { .javaId(-1) .bedrockDefinition(lodestoneCompass) .bedrockData(0) - .bedrockBlockId(-1) + .bedrockBlockDefinition(null) .stackSize(1) .customItemOptions(Collections.emptyList()) .build(); if (customItemsAllowed) { - // Add the furnace minecart as a custom item - int furnaceMinecartId = nextFreeBedrockId++; - - ItemDefinition definition = new ItemDefinition("geysermc:furnace_minecart", (short) furnaceMinecartId, true); + // Add furnace minecart + ItemDefinition definition = new ItemDefinition("geysermc:furnace_minecart", nextFreeBedrockId, true); definitions.put("geysermc:furnace_minecart", definition); registry.add(definition); @@ -589,49 +490,18 @@ public class ItemRegistryPopulator { .javaId(javaFurnaceMinecartId) .bedrockDefinition(definition) .bedrockData(0) - .bedrockBlockId(-1) + .bedrockBlockDefinition(null) .stackSize(1) .customItemOptions(Collections.emptyList()) // TODO check for custom items with furnace minecart .build()); creativeItems.add(ItemData.builder() - .netId(netId++) + .netId(creativeNetId.getAndIncrement()) .definition(definition) - .count(1).build()); - - NbtMapBuilder builder = NbtMap.builder(); - builder.putString("name", "geysermc:furnace_minecart") - .putInt("id", furnaceMinecartId); - - NbtMapBuilder itemProperties = NbtMap.builder(); - - NbtMapBuilder componentBuilder = NbtMap.builder(); - // Conveniently, as of 1.16.200, the furnace minecart has a texture AND translation string already. - itemProperties.putCompound("minecraft:icon", NbtMap.builder() - .putString("texture", "minecart_furnace") - .putString("frame", "0.000000") - .putInt("frame_version", 1) - .putString("legacy_id", "").build()); - componentBuilder.putCompound("minecraft:display_name", NbtMap.builder().putString("value", "item.minecartFurnace.name").build()); - - // Indicate that the arm animation should play on rails - List useOnTag = Collections.singletonList(NbtMap.builder().putString("tags", "q.any_tag('rail')").build()); - componentBuilder.putCompound("minecraft:entity_placer", NbtMap.builder() - .putList("dispense_on", NbtType.COMPOUND, useOnTag) - .putString("entity", "minecraft:minecart") - .putList("use_on", NbtType.COMPOUND, useOnTag) + .count(1) .build()); - // We always want to allow offhand usage when we can - matches Java Edition - itemProperties.putBoolean("allow_off_hand", true); - itemProperties.putBoolean("hand_equipped", false); - itemProperties.putInt("max_stack_size", 1); - itemProperties.putString("creative_group", "itemGroup.name.minecart"); - itemProperties.putInt("creative_category", 4); // 4 - "Items" - - componentBuilder.putCompound("item_properties", itemProperties.build()); - builder.putCompound("components", componentBuilder.build()); - componentItemData.add(new ComponentItemData("geysermc:furnace_minecart", builder.build())); + registerFurnaceMinecart(nextFreeBedrockId++, componentItemData); // Register any completely custom items given to us IntSet registeredJavaIds = new IntOpenHashSet(); // Used to check for duplicate item java ids @@ -657,8 +527,9 @@ public class ItemRegistryPopulator { if (customItem.creativeGroup() != null || customItem.creativeCategory().isPresent()) { creativeItems.add(ItemData.builder() .definition(registration.mapping().getBedrockDefinition()) - .netId(netId++) - .count(1).build()); + .netId(creativeNetId.getAndIncrement()) + .count(1) + .build()); } } } @@ -669,7 +540,7 @@ public class ItemRegistryPopulator { .definitionRegistry(registry.build()) .itemDefinitions(List.copyOf(definitions.values())) .itemNames(itemNames.toArray(new String[0])) - .storedItems(new StoredItemMappings(identifierToMapping)) + .storedItems(new StoredItemMappings(javaIdentifierToMapping)) .javaOnlyItems(javaOnlyItems) .buckets(buckets) .boats(boats) @@ -687,4 +558,40 @@ public class ItemRegistryPopulator { ItemUtils.setDyeColors(dyeColors); } + + private static void registerFurnaceMinecart(int nextFreeBedrockId, List componentItemData) { + NbtMapBuilder builder = NbtMap.builder(); + builder.putString("name", "geysermc:furnace_minecart") + .putInt("id", nextFreeBedrockId); + + NbtMapBuilder itemProperties = NbtMap.builder(); + + NbtMapBuilder componentBuilder = NbtMap.builder(); + // Conveniently, as of 1.16.200, the furnace minecart has a texture AND translation string already. + itemProperties.putCompound("minecraft:icon", NbtMap.builder() + .putString("texture", "minecart_furnace") + .putString("frame", "0.000000") + .putInt("frame_version", 1) + .putString("legacy_id", "").build()); + componentBuilder.putCompound("minecraft:display_name", NbtMap.builder().putString("value", "item.minecartFurnace.name").build()); + + // Indicate that the arm animation should play on rails + List useOnTag = Collections.singletonList(NbtMap.builder().putString("tags", "q.any_tag('rail')").build()); + componentBuilder.putCompound("minecraft:entity_placer", NbtMap.builder() + .putList("dispense_on", NbtType.COMPOUND, useOnTag) + .putString("entity", "minecraft:minecart") + .putList("use_on", NbtType.COMPOUND, useOnTag) + .build()); + + // We always want to allow offhand usage when we can - matches Java Edition + itemProperties.putBoolean("allow_off_hand", true); + itemProperties.putBoolean("hand_equipped", false); + itemProperties.putInt("max_stack_size", 1); + itemProperties.putString("creative_group", "itemGroup.name.minecart"); + itemProperties.putInt("creative_category", 4); // 4 - "Items" + + componentBuilder.putCompound("item_properties", itemProperties.build()); + builder.putCompound("components", componentBuilder.build()); + componentItemData.add(new ComponentItemData("geysermc:furnace_minecart", builder.build())); + } } diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/RecipeRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/RecipeRegistryPopulator.java index c21938416..5363e9e82 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/RecipeRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/RecipeRegistryPopulator.java @@ -232,7 +232,7 @@ public class RecipeRegistryPopulator { .definition(mapping.getBedrockDefinition()) .damage(damage) .count(count) - .blockRuntimeId(mapping.isBlock() ? mapping.getBedrockBlockId() : 0) + .blockDefinition(mapping.getBedrockBlockDefinition()) .tag(tag) .build(); } 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 fd410dd1f..33f8670b3 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 @@ -73,18 +73,11 @@ public class BlockMappings { return this.javaToBedrockBlocks[state]; } - public int getItemFrame(NbtMap tag) { - BlockDefinition definition = this.itemFrames.get(tag); - return definition == null ? -1 : definition.getRuntimeId(); + public BlockDefinition getItemFrame(NbtMap tag) { + return this.itemFrames.get(tag); } - public boolean isItemFrame(int bedrockBlockRuntimeId) { - for (Map.Entry entry : this.itemFrames.entrySet()) { - if (entry.getValue().getRuntimeId() == bedrockBlockRuntimeId) { - return true; - } - } - - return false; + public boolean isItemFrame(BlockDefinition definition) { + return this.itemFrames.containsKey(definition.getState()); } } \ No newline at end of file diff --git a/core/src/main/java/org/geysermc/geyser/registry/type/ItemMapping.java b/core/src/main/java/org/geysermc/geyser/registry/type/ItemMapping.java index bcc51fdfe..caa940b28 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/type/ItemMapping.java +++ b/core/src/main/java/org/geysermc/geyser/registry/type/ItemMapping.java @@ -26,11 +26,11 @@ package org.geysermc.geyser.registry.type; import it.unimi.dsi.fastutil.Pair; -import it.unimi.dsi.fastutil.objects.ObjectIntPair; import lombok.Builder; import lombok.EqualsAndHashCode; import lombok.Value; import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition; import org.geysermc.geyser.api.item.custom.CustomItemOptions; @@ -48,7 +48,7 @@ public class ItemMapping { 0, ItemDefinition.AIR, 0, - 0, // Air is never sent in full over the network for this to serialize. + null, // Air is never sent in full over the network for this to serialize. 64, null, null, @@ -69,7 +69,7 @@ public class ItemMapping { * The Bedrock block runtime ID to render this item with. The specific state *does* matter in how this item is rendered and used as a crafting ingredient. * Required since 1.16.220. */ - int bedrockBlockId; + BlockDefinition bedrockBlockDefinition; int stackSize; String toolType; @@ -92,7 +92,7 @@ public class ItemMapping { * @return if this item is a block */ public boolean isBlock() { - return this.bedrockBlockId != -1; + return this.bedrockBlockDefinition != null; } /** diff --git a/core/src/main/java/org/geysermc/geyser/registry/type/ItemMappings.java b/core/src/main/java/org/geysermc/geyser/registry/type/ItemMappings.java index 08d88671a..8fa7d9f91 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/type/ItemMappings.java +++ b/core/src/main/java/org/geysermc/geyser/registry/type/ItemMappings.java @@ -127,13 +127,13 @@ public class ItemMappings { return lodestoneCompass; } - boolean isBlock = data.getBlockRuntimeId() != 0; + boolean isBlock = data.getBlockDefinition() != null; boolean hasDamage = data.getDamage() != 0; for (ItemMapping mapping : this.items) { if (mapping.getBedrockDefinition().equals(definition)) { if (isBlock && !hasDamage) { // Pre-1.16.220 will not use block runtime IDs at all, so we shouldn't check either - if (data.getBlockRuntimeId() != mapping.getBedrockBlockId()) { + if (data.getBlockDefinition() != mapping.getBedrockBlockDefinition()) { continue; } } else { diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/chest/DoubleChestInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/chest/DoubleChestInventoryTranslator.java index 90f47578d..14ca1dd63 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/chest/DoubleChestInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/chest/DoubleChestInventoryTranslator.java @@ -28,6 +28,7 @@ package org.geysermc.geyser.translator.inventory.chest; import org.cloudburstmc.math.vector.Vector3i; import com.nukkitx.nbt.NbtMap; import com.nukkitx.nbt.NbtMapBuilder; +import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket; import org.cloudburstmc.protocol.bedrock.packet.ContainerClosePacket; @@ -82,12 +83,12 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator { Vector3i position = session.getPlayerEntity().getPosition().toInt().add(Vector3i.UP); Vector3i pairPosition = position.add(Vector3i.UNIT_X); - int bedrockBlockId = session.getBlockMappings().getBedrockBlockId(defaultJavaBlockState); + BlockDefinition definition = session.getBlockMappings().getBedrockBlock(defaultJavaBlockState); UpdateBlockPacket blockPacket = new UpdateBlockPacket(); blockPacket.setDataLayer(0); blockPacket.setBlockPosition(position); - blockPacket.setRuntimeId(bedrockBlockId); + blockPacket.setDefinition(definition); blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY); session.sendUpstreamPacket(blockPacket); @@ -107,7 +108,7 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator { blockPacket = new UpdateBlockPacket(); blockPacket.setDataLayer(0); blockPacket.setBlockPosition(pairPosition); - blockPacket.setRuntimeId(bedrockBlockId); + blockPacket.setDefinition(definition); blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY); session.sendUpstreamPacket(blockPacket); @@ -154,7 +155,7 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator { UpdateBlockPacket blockPacket = new UpdateBlockPacket(); blockPacket.setDataLayer(0); blockPacket.setBlockPosition(holderPos); - blockPacket.setRuntimeId(session.getBlockMappings().getBedrockBlockId(realBlock)); + blockPacket.setDefinition(session.getBlockMappings().getBedrockBlock(realBlock)); session.sendUpstreamPacket(blockPacket); holderPos = holderPos.add(Vector3i.UNIT_X); @@ -162,7 +163,7 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator { blockPacket = new UpdateBlockPacket(); blockPacket.setDataLayer(0); blockPacket.setBlockPosition(holderPos); - blockPacket.setRuntimeId(session.getBlockMappings().getBedrockBlockId(realBlock)); + blockPacket.setDefinition(session.getBlockMappings().getBedrockBlock(realBlock)); session.sendUpstreamPacket(blockPacket); } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/ItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/ItemTranslator.java index 22e9fac59..1515f64c8 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/ItemTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/ItemTranslator.java @@ -26,18 +26,30 @@ package org.geysermc.geyser.translator.inventory.item; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; -import com.github.steveice10.opennbt.tag.builtin.*; +import com.github.steveice10.opennbt.tag.builtin.ByteArrayTag; +import com.github.steveice10.opennbt.tag.builtin.ByteTag; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.DoubleTag; +import com.github.steveice10.opennbt.tag.builtin.FloatTag; +import com.github.steveice10.opennbt.tag.builtin.IntArrayTag; +import com.github.steveice10.opennbt.tag.builtin.IntTag; +import com.github.steveice10.opennbt.tag.builtin.ListTag; +import com.github.steveice10.opennbt.tag.builtin.LongArrayTag; +import com.github.steveice10.opennbt.tag.builtin.LongTag; +import com.github.steveice10.opennbt.tag.builtin.ShortTag; +import com.github.steveice10.opennbt.tag.builtin.StringTag; +import com.github.steveice10.opennbt.tag.builtin.Tag; import com.nukkitx.nbt.NbtList; import com.nukkitx.nbt.NbtMap; import com.nukkitx.nbt.NbtMapBuilder; import com.nukkitx.nbt.NbtType; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition; -import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition; +import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.registry.BlockRegistries; @@ -50,7 +62,11 @@ import org.geysermc.geyser.util.FileUtils; import javax.annotation.Nonnull; import java.lang.reflect.InvocationTargetException; -import java.util.*; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.stream.Collectors; public abstract class ItemTranslator { @@ -169,7 +185,7 @@ public abstract class ItemTranslator { ItemTranslator itemStackTranslator = ITEM_STACK_TRANSLATORS.getOrDefault(bedrockItem.getJavaId(), DEFAULT_TRANSLATOR); ItemData.Builder builder = itemStackTranslator.translateToBedrock(itemStack, bedrockItem, session.getItemMappings()); if (bedrockItem.isBlock()) { - builder.blockRuntimeId(bedrockItem.getBedrockBlockId()); + builder.blockDefinition(bedrockItem.getBedrockBlockDefinition()); } if (nbt != null) { diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/FlowerPotBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/FlowerPotBlockEntityTranslator.java index afd9c8d42..7747cf118 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/FlowerPotBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/FlowerPotBlockEntityTranslator.java @@ -80,7 +80,7 @@ public class FlowerPotBlockEntityTranslator implements BedrockOnlyBlockEntity { BlockEntityUtils.updateBlockEntity(session, tag, position); UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); updateBlockPacket.setDataLayer(0); - updateBlockPacket.setRuntimeId(session.getBlockMappings().getBedrockBlockId(blockState)); + updateBlockPacket.setDefinition(session.getBlockMappings().getBedrockBlock(blockState)); updateBlockPacket.setBlockPosition(position); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/PistonBlockEntity.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/PistonBlockEntity.java index 8955ff944..7f6ffa0c0 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/PistonBlockEntity.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/PistonBlockEntity.java @@ -598,7 +598,7 @@ public class PistonBlockEntity { updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); updateBlockPacket.setBlockPosition(newPos); - updateBlockPacket.setRuntimeId(session.getBlockMappings().getBedrockMovingBlock().getRuntimeId()); + updateBlockPacket.setDefinition(session.getBlockMappings().getBedrockMovingBlock()); updateBlockPacket.setDataLayer(0); session.sendUpstreamPacket(updateBlockPacket); // Update moving block with correct details diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java index d98c31e86..0af2a92ec 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java @@ -195,7 +195,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator= 2 && session.getGameMode() == GameMode.CREATIVE) { // Otherwise insufficient permissions - if (session.getBlockMappings().getJigsawStates().contains(packet.getBlockRuntimeId())) { + if (session.getBlockMappings().getJigsawStates().contains(packet.getBlockDefinition())) { ContainerOpenPacket openPacket = new ContainerOpenPacket(); openPacket.setBlockPosition(packet.getBlockPosition()); openPacket.setId((byte) 1); @@ -539,14 +539,14 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator