From c5d4b86564cdbdbfe956e2f210dba7560de50b1c Mon Sep 17 00:00:00 2001 From: Tim203 Date: Sat, 3 Jun 2023 11:47:50 +0200 Subject: [PATCH 001/344] Prepare for changes made in CloudburstMC/Protocol#205 --- .../geyser/entity/type/ItemFrameEntity.java | 2 +- .../geyser/entity/type/LivingEntity.java | 2 +- .../type/living/monster/EndermanEntity.java | 2 +- .../geysermc/geyser/inventory/Inventory.java | 2 +- .../geyser/item/GeyserCustomMappingData.java | 2 +- .../geysermc/geyser/item/type/PotionItem.java | 2 +- .../populator/BlockRegistryPopulator.java | 2 +- .../CreativeItemRegistryPopulator.java | 2 +- .../CustomItemRegistryPopulator.java | 4 +- .../populator/ItemRegistryPopulator.java | 6 +- .../geyser/registry/type/BlockMappings.java | 2 +- .../registry/type/GeyserBedrockBlock.java | 2 +- .../registry/type/GeyserItemDefinition.java | 2 +- .../geyser/registry/type/ItemMapping.java | 4 +- .../geyser/registry/type/ItemMappings.java | 2 +- .../geyser/session/GeyserSession.java | 3 +- .../geyser/skin/FloodgateSkinUploader.java | 5 +- .../chest/DoubleChestInventoryTranslator.java | 2 +- .../inventory/item/CustomItemTranslator.java | 2 +- .../inventory/item/ItemTranslator.java | 2 +- ...BedrockInventoryTransactionTranslator.java | 2 +- .../java/JavaUpdateRecipesTranslator.java | 2 +- .../org/geysermc/geyser/util/ChunkUtils.java | 2 +- .../geysermc/geyser/util/InventoryUtils.java | 2 +- .../geyser/util/LoginEncryptionUtils.java | 114 +++--------------- .../inventory/item/CustomItemsTest.java | 4 +- 26 files changed, 50 insertions(+), 128 deletions(-) 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 378385cfa..eb9329bcd 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,7 +35,7 @@ import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; -import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition; +import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket; import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java index 43fe555b0..4f38297c3 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java @@ -41,7 +41,7 @@ import lombok.Setter; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.AttributeData; -import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition; +import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/EndermanEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/EndermanEntity.java index 0d52b7a35..5b8e23f8b 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/EndermanEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/EndermanEntity.java @@ -29,7 +29,7 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanE import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; -import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition; +import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEvent2Packet; diff --git a/core/src/main/java/org/geysermc/geyser/inventory/Inventory.java b/core/src/main/java/org/geysermc/geyser/inventory/Inventory.java index 1dbde84f4..91e8c4e94 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/Inventory.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/Inventory.java @@ -33,7 +33,7 @@ import org.cloudburstmc.math.vector.Vector3i; import lombok.Getter; import lombok.Setter; import lombok.ToString; -import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition; +import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; diff --git a/core/src/main/java/org/geysermc/geyser/item/GeyserCustomMappingData.java b/core/src/main/java/org/geysermc/geyser/item/GeyserCustomMappingData.java index 08a8b387c..37bf9e02c 100644 --- a/core/src/main/java/org/geysermc/geyser/item/GeyserCustomMappingData.java +++ b/core/src/main/java/org/geysermc/geyser/item/GeyserCustomMappingData.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.item; -import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition; +import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData; import org.cloudburstmc.protocol.bedrock.packet.StartGamePacket; diff --git a/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java b/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java index 338473fc5..359639437 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java @@ -28,7 +28,7 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.Tag; -import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition; +import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.inventory.item.Potion; 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 d071bfc90..668eb97f2 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 @@ -37,7 +37,7 @@ import org.cloudburstmc.protocol.bedrock.codec.v560.Bedrock_v560; import org.cloudburstmc.protocol.bedrock.codec.v567.Bedrock_v567; import org.cloudburstmc.protocol.bedrock.codec.v575.Bedrock_v575; import org.cloudburstmc.protocol.bedrock.codec.v582.Bedrock_v582; -import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition; +import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.physics.PistonBehavior; 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 index 50398d863..6a4db5655 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/CreativeItemRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/CreativeItemRegistryPopulator.java @@ -28,7 +28,7 @@ package org.geysermc.geyser.registry.populator; import com.fasterxml.jackson.databind.JsonNode; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtUtils; -import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition; +import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; 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 ddf07c7d6..629fc17c5 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 @@ -30,8 +30,8 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; -import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition; -import org.cloudburstmc.protocol.bedrock.data.defintions.SimpleItemDefinition; +import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; +import org.cloudburstmc.protocol.bedrock.data.definitions.SimpleItemDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.item.custom.CustomItemData; 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 1713f263d..76814012e 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 @@ -42,9 +42,9 @@ import org.cloudburstmc.protocol.bedrock.codec.v560.Bedrock_v560; import org.cloudburstmc.protocol.bedrock.codec.v567.Bedrock_v567; import org.cloudburstmc.protocol.bedrock.codec.v575.Bedrock_v575; import org.cloudburstmc.protocol.bedrock.codec.v582.Bedrock_v582; -import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition; -import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition; -import org.cloudburstmc.protocol.bedrock.data.defintions.SimpleItemDefinition; +import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; +import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; +import org.cloudburstmc.protocol.bedrock.data.definitions.SimpleItemDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; 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 416b3f039..2efac0d4e 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 @@ -28,7 +28,7 @@ package org.geysermc.geyser.registry.type; import lombok.Builder; import lombok.Value; import org.cloudburstmc.nbt.NbtMap; -import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition; +import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.common.DefinitionRegistry; import java.util.Map; diff --git a/core/src/main/java/org/geysermc/geyser/registry/type/GeyserBedrockBlock.java b/core/src/main/java/org/geysermc/geyser/registry/type/GeyserBedrockBlock.java index 2fefc539b..190354359 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/type/GeyserBedrockBlock.java +++ b/core/src/main/java/org/geysermc/geyser/registry/type/GeyserBedrockBlock.java @@ -26,7 +26,7 @@ package org.geysermc.geyser.registry.type; import org.cloudburstmc.nbt.NbtMap; -import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition; +import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; public class GeyserBedrockBlock implements BlockDefinition { private final int runtimeId; diff --git a/core/src/main/java/org/geysermc/geyser/registry/type/GeyserItemDefinition.java b/core/src/main/java/org/geysermc/geyser/registry/type/GeyserItemDefinition.java index c8d83b021..fa1cb9985 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/type/GeyserItemDefinition.java +++ b/core/src/main/java/org/geysermc/geyser/registry/type/GeyserItemDefinition.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.registry.type; -import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition; +import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.geysermc.geyser.item.type.Item; /** 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 4883b5ec1..437b8223a 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 @@ -30,8 +30,8 @@ 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.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; +import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.geysermc.geyser.api.item.custom.CustomItemOptions; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.Item; 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 77564e98b..0b45d881a 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 @@ -29,7 +29,7 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import lombok.Builder; import lombok.Value; -import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition; +import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.common.DefinitionRegistry; diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 052222be1..0c89605c0 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -60,7 +60,6 @@ import com.github.steveice10.packetlib.event.session.*; import com.github.steveice10.packetlib.packet.Packet; import com.github.steveice10.packetlib.tcp.TcpClientSession; import com.github.steveice10.packetlib.tcp.TcpSession; -import com.nimbusds.jwt.SignedJWT; import io.netty.channel.Channel; import io.netty.channel.EventLoop; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; @@ -171,7 +170,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { * Used for Floodgate skin uploading */ @Setter - private List certChainData; + private List certChainData; @NotNull @Setter diff --git a/core/src/main/java/org/geysermc/geyser/skin/FloodgateSkinUploader.java b/core/src/main/java/org/geysermc/geyser/skin/FloodgateSkinUploader.java index 39de6c32a..4e4f52914 100644 --- a/core/src/main/java/org/geysermc/geyser/skin/FloodgateSkinUploader.java +++ b/core/src/main/java/org/geysermc/geyser/skin/FloodgateSkinUploader.java @@ -30,7 +30,6 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; -import com.nimbusds.jwt.SignedJWT; import lombok.Getter; import org.geysermc.floodgate.pluginmessage.PluginMessageChannels; import org.geysermc.floodgate.util.WebsocketEventType; @@ -191,14 +190,14 @@ public final class FloodgateSkinUploader { }; } - public void uploadSkin(List chainData, String clientData) { + public void uploadSkin(List chainData, String clientData) { if (chainData == null || clientData == null) { return; } ObjectNode node = JACKSON.createObjectNode(); ArrayNode chainDataNode = JACKSON.createArrayNode(); - chainData.forEach(jwt -> chainDataNode.add(jwt.serialize())); + chainData.forEach(chainDataNode::add); node.set("chain_data", chainDataNode); node.put("client_data", clientData); 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 2f19f56f3..0934f33a7 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,7 +28,7 @@ package org.geysermc.geyser.translator.inventory.chest; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; -import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition; +import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket; import org.cloudburstmc.protocol.bedrock.packet.ContainerClosePacket; diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/CustomItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/CustomItemTranslator.java index 31491fc3d..06d1e3aa6 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/CustomItemTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/CustomItemTranslator.java @@ -30,7 +30,7 @@ import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import it.unimi.dsi.fastutil.Pair; import org.checkerframework.checker.nullness.qual.Nullable; -import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition; +import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.geysermc.geyser.api.item.custom.CustomItemOptions; import org.geysermc.geyser.api.util.TriState; import org.geysermc.geyser.registry.type.ItemMapping; 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 045d4c56d..0f0421be8 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 @@ -37,7 +37,7 @@ import org.cloudburstmc.nbt.NbtList; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; -import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition; +import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.inventory.GeyserItemStack; 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 7d0fa4691..5bfb2dd6a 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 @@ -39,7 +39,7 @@ import org.cloudburstmc.math.vector.Vector3d; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.LevelEvent; -import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition; +import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.transaction.InventoryActionData; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java index d58892ce5..63d87240e 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java @@ -37,7 +37,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundUp import it.unimi.dsi.fastutil.ints.*; import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; -import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition; +import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.MultiRecipeData; import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.RecipeData; diff --git a/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java b/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java index d688c0866..469c971f6 100644 --- a/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java @@ -33,7 +33,7 @@ import lombok.experimental.UtilityClass; import org.cloudburstmc.math.GenericMath; import org.cloudburstmc.math.vector.Vector2i; import org.cloudburstmc.math.vector.Vector3i; -import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition; +import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.packet.LevelChunkPacket; import org.cloudburstmc.protocol.bedrock.packet.NetworkChunkPublisherUpdatePacket; import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket; diff --git a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java index 457993ac2..55af9eb11 100644 --- a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java @@ -35,7 +35,7 @@ import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; -import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition; +import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket; diff --git a/core/src/main/java/org/geysermc/geyser/util/LoginEncryptionUtils.java b/core/src/main/java/org/geysermc/geyser/util/LoginEncryptionUtils.java index dd523df5a..38fcdd1f6 100644 --- a/core/src/main/java/org/geysermc/geyser/util/LoginEncryptionUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/LoginEncryptionUtils.java @@ -28,17 +28,12 @@ package org.geysermc.geyser.util; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.JsonNodeType; import com.github.steveice10.mc.auth.service.MsaAuthenticationService; -import com.nimbusds.jose.JWSObject; -import com.nimbusds.jose.Payload; -import com.nimbusds.jose.shaded.json.JSONObject; -import com.nimbusds.jose.shaded.json.JSONValue; -import com.nimbusds.jwt.SignedJWT; import org.cloudburstmc.protocol.bedrock.packet.LoginPacket; import org.cloudburstmc.protocol.bedrock.packet.ServerToClientHandshakePacket; +import org.cloudburstmc.protocol.bedrock.util.ChainValidationResult; +import org.cloudburstmc.protocol.bedrock.util.ChainValidationResult.IdentityData; import org.cloudburstmc.protocol.bedrock.util.EncryptionUtils; -import org.cloudburstmc.protocol.common.util.Preconditions; import org.geysermc.cumulus.form.CustomForm; import org.geysermc.cumulus.form.ModalForm; import org.geysermc.cumulus.form.SimpleForm; @@ -54,15 +49,9 @@ import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.GeyserLocale; import javax.crypto.SecretKey; -import java.net.URI; import java.security.KeyPair; -import java.security.KeyPairGenerator; import java.security.PublicKey; -import java.security.interfaces.ECPublicKey; -import java.security.spec.ECGenParameterSpec; -import java.util.Iterator; import java.util.List; -import java.util.UUID; import java.util.function.BiConsumer; public class LoginEncryptionUtils { @@ -70,106 +59,44 @@ public class LoginEncryptionUtils { private static boolean HAS_SENT_ENCRYPTION_MESSAGE = false; - private static boolean validateChainData(List chain) throws Exception { - if (chain.size() != 3) { - return false; - } - - Payload identity = null; - ECPublicKey lastKey = null; - boolean mojangSigned = false; - Iterator iterator = chain.iterator(); - while (iterator.hasNext()) { - SignedJWT jwt = iterator.next(); - identity = jwt.getPayload(); - - // x509 cert is expected in every claim - URI x5u = jwt.getHeader().getX509CertURL(); - if (x5u == null) { - return false; - } - - ECPublicKey expectedKey = EncryptionUtils.generateKey(jwt.getHeader().getX509CertURL().toString()); - // First key is self-signed - if (lastKey == null) { - lastKey = expectedKey; - } else if (!lastKey.equals(expectedKey)) { - return false; - } - - if (!EncryptionUtils.verifyJwt(jwt, lastKey)) { - return false; - } - - if (mojangSigned) { - return !iterator.hasNext(); - } - - if (lastKey.equals(EncryptionUtils.getMojangPublicKey())) { - mojangSigned = true; - } - - Object payload = JSONValue.parse(jwt.getPayload().toString()); - Preconditions.checkArgument(payload instanceof JSONObject, "Payload is not an object"); - - Object identityPublicKey = ((JSONObject) payload).get("identityPublicKey"); - Preconditions.checkArgument(identityPublicKey instanceof String, "identityPublicKey node is missing in chain"); - lastKey = EncryptionUtils.generateKey((String) identityPublicKey); - } - - return mojangSigned; - } - public static void encryptPlayerConnection(GeyserSession session, LoginPacket loginPacket) { - encryptConnectionWithCert(session, loginPacket.getExtra().getParsedString(), loginPacket.getChain()); + encryptConnectionWithCert(session, loginPacket.getExtra(), loginPacket.getChain()); } - private static void encryptConnectionWithCert(GeyserSession session, String clientData, List certChainData) { + private static void encryptConnectionWithCert(GeyserSession session, String clientData, List certChainData) { try { GeyserImpl geyser = session.getGeyser(); - boolean validChain = validateChainData(certChainData); + ChainValidationResult result = EncryptionUtils.validateChain(certChainData); - geyser.getLogger().debug(String.format("Is player data valid? %s", validChain)); + geyser.getLogger().debug(String.format("Is player data signed? %s", result.signed())); - if (!validChain && !session.getGeyser().getConfig().isEnableProxyConnections()) { + if (!result.signed() && !session.getGeyser().getConfig().isEnableProxyConnections()) { session.disconnect(GeyserLocale.getLocaleStringLog("geyser.network.remote.invalid_xbox_account")); return; } - JWSObject jwt = certChainData.get(certChainData.size() - 1); - JsonNode payload = JSON_MAPPER.readTree(jwt.getPayload().toBytes()); - - if (payload.get("extraData").getNodeType() != JsonNodeType.OBJECT) { - throw new RuntimeException("AuthData was not found!"); - } - - JsonNode extraData = payload.get("extraData"); - session.setAuthenticationData(new AuthData( - extraData.get("displayName").asText(), - UUID.fromString(extraData.get("identity").asText()), - extraData.get("XUID").asText() - )); + IdentityData extraData = result.identityClaims().extraData; + session.setAuthenticationData(new AuthData(extraData.displayName, extraData.identity, extraData.xuid)); session.setCertChainData(certChainData); - if (payload.get("identityPublicKey").getNodeType() != JsonNodeType.STRING) { - throw new RuntimeException("Identity Public Key was not found!"); + PublicKey identityPublicKey = result.identityClaims().parsedIdentityPublicKey(); + + byte[] clientDataPayload = EncryptionUtils.verifyClientData(clientData, identityPublicKey); + if (clientDataPayload == null) { + throw new IllegalStateException("Client data isn't signed by the given chain data"); } - ECPublicKey identityPublicKey = EncryptionUtils.generateKey(payload.get("identityPublicKey").textValue()); - JWSObject clientJwt = JWSObject.parse(clientData); - EncryptionUtils.verifyJwt(clientJwt, identityPublicKey); - - JsonNode clientDataJson = JSON_MAPPER.readTree(clientJwt.getPayload().toBytes()); + JsonNode clientDataJson = JSON_MAPPER.readTree(clientDataPayload); BedrockClientData data = JSON_MAPPER.convertValue(clientDataJson, BedrockClientData.class); data.setOriginalString(clientData); session.setClientData(data); try { - LoginEncryptionUtils.startEncryptionHandshake(session, identityPublicKey); + startEncryptionHandshake(session, identityPublicKey); } catch (Throwable e) { // An error can be thrown on older Java 8 versions about an invalid key - if (geyser.getConfig().isDebugMode()) { + if (true || geyser.getConfig().isDebugMode()) { e.printStackTrace(); } @@ -182,14 +109,11 @@ public class LoginEncryptionUtils { } private static void startEncryptionHandshake(GeyserSession session, PublicKey key) throws Exception { - KeyPairGenerator generator = KeyPairGenerator.getInstance("EC"); - generator.initialize(new ECGenParameterSpec("secp384r1")); - KeyPair serverKeyPair = generator.generateKeyPair(); - + KeyPair serverKeyPair = EncryptionUtils.createKeyPair(); byte[] token = EncryptionUtils.generateRandomToken(); ServerToClientHandshakePacket packet = new ServerToClientHandshakePacket(); - packet.setJwt(EncryptionUtils.createHandshakeJwt(serverKeyPair, token).serialize()); + packet.setJwt(EncryptionUtils.createHandshakeJwt(serverKeyPair, token)); session.sendUpstreamPacketImmediately(packet); SecretKey encryptionKey = EncryptionUtils.getSecretKey(serverKeyPair.getPrivate(), key, token); diff --git a/core/src/test/java/org/geysermc/geyser/translator/inventory/item/CustomItemsTest.java b/core/src/test/java/org/geysermc/geyser/translator/inventory/item/CustomItemsTest.java index 10f265a41..c66a35486 100644 --- a/core/src/test/java/org/geysermc/geyser/translator/inventory/item/CustomItemsTest.java +++ b/core/src/test/java/org/geysermc/geyser/translator/inventory/item/CustomItemsTest.java @@ -30,8 +30,8 @@ package org.geysermc.geyser.translator.inventory.item; //import com.github.steveice10.opennbt.tag.builtin.IntTag; //import it.unimi.dsi.fastutil.Pair; //import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; -//import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition; -//import org.cloudburstmc.protocol.bedrock.data.defintions.SimpleItemDefinition; +//import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; +//import org.cloudburstmc.protocol.bedrock.data.definitions.SimpleItemDefinition; //import org.geysermc.geyser.api.item.custom.CustomItemOptions; //import org.geysermc.geyser.api.util.TriState; //import org.geysermc.geyser.item.GeyserCustomItemOptions; From 4e749d75f8cc317cd64d5b73a883c1be68664ef4 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Thu, 15 Jun 2023 13:27:11 -0400 Subject: [PATCH 002/344] Sound and particle mapping updates (#3874) --- core/src/main/resources/mappings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/resources/mappings b/core/src/main/resources/mappings index cf6fdf31f..80fdfbf89 160000 --- a/core/src/main/resources/mappings +++ b/core/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit cf6fdf31fe7c607d7fb3a4a42b86def45fe86385 +Subproject commit 80fdfbf89f586dbfbcf06152821adc7c1df88eab From eecf84e87d6f27cb0d1db27698f22306330c062c Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Thu, 15 Jun 2023 15:04:50 -0400 Subject: [PATCH 003/344] Show archeology brushing animations (#3855) Display items emerging from suspicious blocks --- .../geyser/level/block/BlockStateValues.java | 21 ++++++ .../BrushableBlockEntityTranslator.java | 73 +++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BrushableBlockEntityTranslator.java 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 27fb539be..1a4e96bca 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 @@ -48,6 +48,7 @@ public final class BlockStateValues { private static final IntSet HANGING_SIGNS = new IntOpenHashSet(); private static final Int2IntMap BANNER_COLORS = new FixedInt2IntMap(); private static final Int2ByteMap BED_COLORS = new FixedInt2ByteMap(); + private static final Int2IntMap BRUSH_PROGRESS = new Int2IntOpenHashMap(); 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<>(); @@ -105,6 +106,15 @@ public final class BlockStateValues { return; } + JsonNode bedrockStates = blockData.get("bedrock_states"); + if (bedrockStates != null) { + JsonNode brushedProgress = bedrockStates.get("brushed_progress"); + if (brushedProgress != null) { + BRUSH_PROGRESS.put(javaBlockState, brushedProgress.intValue()); + return; + } + } + if (javaId.contains("command_block")) { COMMAND_BLOCK_VALUES.put(javaBlockState, javaId.contains("conditional=true") ? (byte) 1 : (byte) 0); return; @@ -243,6 +253,17 @@ public final class BlockStateValues { return BED_COLORS.getOrDefault(state, (byte) -1); } + /** + * The brush progress of suspicious sand/gravel is not sent by the java server when it updates the block entity. + * Although brush progress is part of the bedrock block state, it must be included in the block entity update. + * + * @param state BlockState of the block + * @return brush progress or 0 if the lookup failed + */ + public static int getBrushProgress(int state) { + return BRUSH_PROGRESS.getOrDefault(state, 0); + } + /** * Non-water cauldrons (since Bedrock 1.18.30) must have a block entity packet sent on chunk load to fix rendering issues. * diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BrushableBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BrushableBlockEntityTranslator.java new file mode 100644 index 000000000..9a2b9d8e1 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BrushableBlockEntityTranslator.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2019-2023 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.translator.level.block.entity; + +import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; +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 org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtMapBuilder; +import org.geysermc.geyser.item.Items; +import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.network.GameProtocol; +import org.geysermc.geyser.registry.Registries; +import org.geysermc.geyser.registry.type.ItemMapping; + +@BlockEntity(type = BlockEntityType.BRUSHABLE_BLOCK) +public class BrushableBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState { + + @Override + public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) { + if (!(tag.remove("item") instanceof CompoundTag itemTag)) { + return; + } + Tag hitDirection = tag.get("hit_direction"); + if (hitDirection == null) { + // java server sends no direction when the item recedes back into the block (if player stops brushing) + return; + } + + String id = ((StringTag) itemTag.get("id")).getValue(); + if (Items.AIR.javaIdentifier().equals(id)) { + return; // server sends air when the block contains nothing + } + + ItemMapping mapping = Registries.ITEMS.forVersion(GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()).getMapping(id); + if (mapping == null) { + return; + } + NbtMapBuilder itemBuilder = NbtMap.builder() + .putString("Name", mapping.getBedrockIdentifier()) + .putByte("Count", (byte) itemTag.get("Count").getValue()); + + builder.putCompound("item", itemBuilder.build()); + // controls which side the item protrudes from + builder.putByte("brush_direction", ((Number) hitDirection.getValue()).byteValue()); + // controls how much the item protrudes + builder.putInt("brush_count", BlockStateValues.getBrushProgress(blockState)); + } +} From 6591332eb70afa9a0e4262133149753ef4e3b19a Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 16 Jun 2023 04:17:29 +0200 Subject: [PATCH 004/344] fix commands with trailing whitespaces (#3878) fixes https://github.com/GeyserMC/Geyser/issues/3877 --- .../protocol/bedrock/BedrockCommandRequestTranslator.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockCommandRequestTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockCommandRequestTranslator.java index bc04bf50e..b981516eb 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockCommandRequestTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockCommandRequestTranslator.java @@ -29,7 +29,6 @@ import org.cloudburstmc.protocol.bedrock.packet.CommandRequestPacket; import org.geysermc.common.PlatformType; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.translator.text.MessageTranslator; @@ -46,7 +45,9 @@ public class BedrockCommandRequestTranslator extends PacketTranslator Date: Fri, 16 Jun 2023 22:54:21 +0200 Subject: [PATCH 005/344] Update events library to latest version --- .../geyser/extension/event/GeyserExtensionEventBus.java | 8 +++++++- gradle/libs.versions.toml | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/extension/event/GeyserExtensionEventBus.java b/core/src/main/java/org/geysermc/geyser/extension/event/GeyserExtensionEventBus.java index f56b254a6..2764499ef 100644 --- a/core/src/main/java/org/geysermc/geyser/extension/event/GeyserExtensionEventBus.java +++ b/core/src/main/java/org/geysermc/geyser/extension/event/GeyserExtensionEventBus.java @@ -27,6 +27,7 @@ package org.geysermc.geyser.extension.event; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.event.Event; +import org.geysermc.event.FireResult; import org.geysermc.event.PostOrder; import org.geysermc.event.subscribe.Subscriber; import org.geysermc.geyser.api.event.EventBus; @@ -47,10 +48,15 @@ public record GeyserExtensionEventBus(EventBus eventBus, Extensi } @Override - public boolean fire(@NonNull Event event) { + public FireResult fire(@NonNull Event event) { return eventBus.fire(event); } + @Override + public FireResult fireSilently(@NonNull Event event) { + return eventBus.fireSilently(event); + } + @Override public @NonNull Set> subscribers(@NonNull Class eventClass) { return eventBus.subscribers(eventClass); diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b7d828b1e..d179c7576 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ base-api = "1.0.0-SNAPSHOT" cumulus = "1.1.1" erosion = "1.0-20230406.174837-8" -events = "1.0-SNAPSHOT" +events = "1.1-SNAPSHOT" jackson = "2.14.0" fastutil = "8.5.2" netty = "4.1.80.Final" From 23fb63eb17c6e7258e6a4210d2646225b8f25b3e Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Fri, 16 Jun 2023 20:37:54 -0400 Subject: [PATCH 006/344] Update mappings for new pottables, other misc(#3885) torchflower/cherry sapling as pottable, other misc --- core/src/main/resources/mappings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/resources/mappings b/core/src/main/resources/mappings index 80fdfbf89..dbc7aea1b 160000 --- a/core/src/main/resources/mappings +++ b/core/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit 80fdfbf89f586dbfbcf06152821adc7c1df88eab +Subproject commit dbc7aea1ba4d7926191cfabff0a5268461947bf0 From 6eca6ade06943680173535aa8fc481a68fe5c1c2 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Fri, 16 Jun 2023 20:51:29 -0400 Subject: [PATCH 007/344] Loop through item palette versions in ascending order (#3884) --- .../CreativeItemRegistryPopulator.java | 6 ++-- .../populator/ItemRegistryPopulator.java | 28 +++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) 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 index 6a4db5655..b60b811a2 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/CreativeItemRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/CreativeItemRegistryPopulator.java @@ -54,18 +54,18 @@ public class CreativeItemRegistryPopulator { (identifier, data) -> identifier.equals("minecraft:bordure_indented_banner_pattern") || identifier.equals("minecraft:field_masoned_banner_pattern") ); - static void populate(Map.Entry version, Map definitions, Consumer itemConsumer) { + static void populate(ItemRegistryPopulator.PaletteVersion palette, 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()))) { + try (InputStream stream = bootstrap.getResource(String.format("bedrock/creative_items.%s.json", palette.version()))) { 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()); + BlockMappings blockMappings = BlockRegistries.BLOCKS.forVersion(palette.protocolVersion()); for (JsonNode itemNode : creativeItemEntries) { ItemData.Builder itemBuilder = createItemData(itemNode, blockMappings, definitions); if (itemBuilder == null) { 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 d4cef1035..cccdff853 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 @@ -68,10 +68,10 @@ import java.util.concurrent.atomic.AtomicInteger; */ public class ItemRegistryPopulator { - record PaletteVersion(int protocolVersion, Map javaOnlyItems, Remapper remapper) { + record PaletteVersion(String version, int protocolVersion, Map javaOnlyItems, Remapper remapper) { - public PaletteVersion(int protocolVersion) { - this(protocolVersion, Collections.emptyMap(), (item, mapping) -> mapping); + public PaletteVersion(String version, int protocolVersion) { + this(version, protocolVersion, Collections.emptyMap(), (item, mapping) -> mapping); } } @@ -88,8 +88,8 @@ public class ItemRegistryPopulator { legacyJavaOnly.put(Items.PITCHER_POD, "minecraft:beetroot"); legacyJavaOnly.put(Items.SNIFFER_EGG, "minecraft:sniffer_spawn_egg"); // the BlockItem of the sniffer egg block - Map paletteVersions = new Object2ObjectOpenHashMap<>(); - paletteVersions.put("1_19_80", new PaletteVersion(Bedrock_v582.CODEC.getProtocolVersion(), legacyJavaOnly, (item, mapping) -> { + List paletteVersions = new ArrayList<>(2); + paletteVersions.add(new PaletteVersion("1_19_80", Bedrock_v582.CODEC.getProtocolVersion(), legacyJavaOnly, (item, mapping) -> { String id = item.javaIdentifier(); if (id.endsWith("pottery_sherd")) { return mapping.withBedrockIdentifier(id.replace("sherd", "shard")); @@ -101,7 +101,7 @@ public class ItemRegistryPopulator { return mapping; })); - paletteVersions.put("1_20_0", new PaletteVersion(Bedrock_v589.CODEC.getProtocolVersion())); + paletteVersions.add(new PaletteVersion("1_20_0", Bedrock_v589.CODEC.getProtocolVersion())); GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap(); @@ -131,11 +131,11 @@ public class ItemRegistryPopulator { boolean firstMappingsPass = true; /* Load item palette */ - for (Map.Entry palette : paletteVersions.entrySet()) { + for (PaletteVersion palette : paletteVersions) { TypeReference> paletteEntriesType = new TypeReference<>() {}; List itemEntries; - try (InputStream stream = bootstrap.getResource(String.format("bedrock/runtime_item_states.%s.json", palette.getKey()))) { + try (InputStream stream = bootstrap.getResource(String.format("bedrock/runtime_item_states.%s.json", palette.version()))) { itemEntries = GeyserImpl.JSON_MAPPER.readValue(stream, paletteEntriesType); } catch (Exception e) { throw new AssertionError("Unable to load Bedrock runtime item IDs", e); @@ -193,7 +193,7 @@ public class ItemRegistryPopulator { } }); - BlockMappings blockMappings = BlockRegistries.BLOCKS.forVersion(palette.getValue().protocolVersion()); + BlockMappings blockMappings = BlockRegistries.BLOCKS.forVersion(palette.protocolVersion()); Set javaOnlyItems = new ObjectOpenHashSet<>(); Collections.addAll(javaOnlyItems, Items.SPECTRAL_ARROW, Items.DEBUG_STICK, @@ -202,7 +202,7 @@ public class ItemRegistryPopulator { javaOnlyItems.add(Items.FURNACE_MINECART); } // Java-only items for this version - javaOnlyItems.addAll(palette.getValue().javaOnlyItems().keySet()); + javaOnlyItems.addAll(palette.javaOnlyItems().keySet()); Int2ObjectMap customIdMappings = new Int2ObjectOpenHashMap<>(); Set registeredItemNames = new ObjectOpenHashSet<>(); // This is used to check for duplicate item names @@ -213,12 +213,12 @@ public class ItemRegistryPopulator { throw new RuntimeException("Extra item in mappings? " + entry.getKey()); } GeyserMappingItem mappingItem; - String replacementItem = palette.getValue().javaOnlyItems().get(javaItem); + String replacementItem = palette.javaOnlyItems().get(javaItem); if (replacementItem != null) { mappingItem = items.get(replacementItem); // java only item, a java id fallback has been provided } else { // check if any mapping changes need to be made on this version - mappingItem = palette.getValue().remapper().remap(javaItem, entry.getValue()); + mappingItem = palette.remapper().remap(javaItem, entry.getValue()); } if (customItemsAllowed && javaItem == Items.FURNACE_MINECART) { @@ -230,7 +230,7 @@ public class ItemRegistryPopulator { String bedrockIdentifier = mappingItem.getBedrockIdentifier(); ItemDefinition definition = definitions.get(bedrockIdentifier); if (definition == null) { - throw new RuntimeException("Missing Bedrock ItemDefinition in version " + palette.getKey() + " for mapping: " + mappingItem); + throw new RuntimeException("Missing Bedrock ItemDefinition in version " + palette.version() + " for mapping: " + mappingItem); } BlockDefinition bedrockBlock = null; @@ -515,7 +515,7 @@ public class ItemRegistryPopulator { .customIdMappings(customIdMappings) .build(); - Registries.ITEMS.register(palette.getValue().protocolVersion(), itemMappings); + Registries.ITEMS.register(palette.protocolVersion(), itemMappings); firstMappingsPass = false; } From 903e61f1a38dd66d0bd314d8ca0d6af4cc0657db Mon Sep 17 00:00:00 2001 From: chris Date: Sat, 17 Jun 2023 03:39:53 +0200 Subject: [PATCH 008/344] Exposing resourcepack loading to api (#3696) Co-authored-by: Konicai <71294714+Konicai@users.noreply.github.com> Co-authored-by: RednedEpic --- .../org/geysermc/geyser/api/GeyserApi.java | 17 ++ .../SessionLoadResourcePacksEvent.java | 67 ++++++ .../geysermc/geyser/api/pack/PackCodec.java | 82 +++++++ .../geyser/api/pack/PathPackCodec.java | 45 ++++ .../geyser/api/pack/ResourcePack.java | 72 ++++++ .../geyser/api/pack/ResourcePackManifest.java | 209 ++++++++++++++++++ core/build.gradle.kts | 2 +- .../java/org/geysermc/geyser/GeyserImpl.java | 19 +- .../SessionLoadResourcePacksEventImpl.java | 69 ++++++ .../geyser/network/UpstreamPacketHandler.java | 71 +++--- .../geyser/pack/GeyserResourcePack.java | 38 ++++ .../pack/GeyserResourcePackManifest.java | 65 ++++++ .../geysermc/geyser/pack/ResourcePack.java | 160 -------------- .../geyser/pack/ResourcePackManifest.java | 117 ---------- .../geyser/pack/path/GeyserPathPackCodec.java | 109 +++++++++ .../geyser/registry/DeferredRegistry.java | 180 +++++++++++++++ .../geysermc/geyser/registry/IRegistry.java | 60 +++++ .../geysermc/geyser/registry/Registries.java | 7 + .../geysermc/geyser/registry/Registry.java | 5 +- .../loader/ProviderRegistryLoader.java | 9 +- .../registry/loader/RegistryLoaders.java | 13 +- .../registry/loader/ResourcePackLoader.java | 156 +++++++++++++ .../geysermc/geyser/skin/ProvidedSkins.java | 9 +- .../geysermc/geyser/text/MinecraftLocale.java | 13 +- .../org/geysermc/geyser/util/AssetUtils.java | 4 +- .../org/geysermc/geyser/util/FileUtils.java | 26 +-- .../loader/ResourcePackLoaderTest.java | 57 +++++ 27 files changed, 1334 insertions(+), 347 deletions(-) create mode 100644 api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionLoadResourcePacksEvent.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/pack/PackCodec.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/pack/PathPackCodec.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/pack/ResourcePack.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/pack/ResourcePackManifest.java create mode 100644 core/src/main/java/org/geysermc/geyser/event/type/SessionLoadResourcePacksEventImpl.java create mode 100644 core/src/main/java/org/geysermc/geyser/pack/GeyserResourcePack.java create mode 100644 core/src/main/java/org/geysermc/geyser/pack/GeyserResourcePackManifest.java delete mode 100644 core/src/main/java/org/geysermc/geyser/pack/ResourcePack.java delete mode 100644 core/src/main/java/org/geysermc/geyser/pack/ResourcePackManifest.java create mode 100644 core/src/main/java/org/geysermc/geyser/pack/path/GeyserPathPackCodec.java create mode 100644 core/src/main/java/org/geysermc/geyser/registry/DeferredRegistry.java create mode 100644 core/src/main/java/org/geysermc/geyser/registry/IRegistry.java create mode 100644 core/src/main/java/org/geysermc/geyser/registry/loader/ResourcePackLoader.java create mode 100644 core/src/test/java/org/geysermc/geyser/registry/loader/ResourcePackLoaderTest.java diff --git a/api/src/main/java/org/geysermc/geyser/api/GeyserApi.java b/api/src/main/java/org/geysermc/geyser/api/GeyserApi.java index f86206d36..84cb445ad 100644 --- a/api/src/main/java/org/geysermc/geyser/api/GeyserApi.java +++ b/api/src/main/java/org/geysermc/geyser/api/GeyserApi.java @@ -36,6 +36,7 @@ import org.geysermc.geyser.api.extension.ExtensionManager; import org.geysermc.geyser.api.network.BedrockListener; import org.geysermc.geyser.api.network.RemoteServer; +import java.nio.file.Path; import java.util.List; import java.util.UUID; @@ -107,6 +108,22 @@ public interface GeyserApi extends GeyserApiBase { @NonNull BedrockListener bedrockListener(); + /** + * Gets the {@link Path} to the Geyser config directory. + * + * @return the path to the Geyser config directory + */ + @NonNull + Path configDirectory(); + + /** + * Gets the {@link Path} to the Geyser packs directory. + * + * @return the path to the Geyser packs directory + */ + @NonNull + Path packDirectory(); + /** * Gets the current {@link GeyserApiBase} instance. * diff --git a/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionLoadResourcePacksEvent.java b/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionLoadResourcePacksEvent.java new file mode 100644 index 000000000..c2f1cd427 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionLoadResourcePacksEvent.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2019-2023 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.api.event.bedrock; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.api.connection.GeyserConnection; +import org.geysermc.geyser.api.event.connection.ConnectionEvent; +import org.geysermc.geyser.api.pack.ResourcePack; + +import java.util.List; +import java.util.UUID; + +/** + * Called when Geyser initializes a session for a new Bedrock client and is in the process of sending resource packs. + */ +public abstract class SessionLoadResourcePacksEvent extends ConnectionEvent { + public SessionLoadResourcePacksEvent(@NonNull GeyserConnection connection) { + super(connection); + } + + /** + * Gets an unmodifiable list of {@link ResourcePack}s that will be sent to the client. + * + * @return an unmodifiable list of resource packs that will be sent to the client. + */ + public abstract @NonNull List resourcePacks(); + + /** + * Registers a {@link ResourcePack} to be sent to the client. + * + * @param resourcePack a resource pack that will be sent to the client. + * @return true if the resource pack was added successfully, + * or false if already present + */ + public abstract boolean register(@NonNull ResourcePack resourcePack); + + /** + * Unregisters a resource pack from being sent to the client. + * + * @param uuid the UUID of the resource pack + * @return true whether the resource pack was removed from the list of resource packs. + */ + public abstract boolean unregister(@NonNull UUID uuid); +} diff --git a/api/src/main/java/org/geysermc/geyser/api/pack/PackCodec.java b/api/src/main/java/org/geysermc/geyser/api/pack/PackCodec.java new file mode 100644 index 000000000..884129fa3 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/pack/PackCodec.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2019-2023 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.api.pack; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.api.GeyserApi; + +import java.io.IOException; +import java.nio.channels.SeekableByteChannel; +import java.nio.file.Path; + +/** + * Represents a pack codec that can be used + * to provide resource packs to clients. + */ +public abstract class PackCodec { + + /** + * Gets the sha256 hash of the resource pack. + * + * @return the hash of the resource pack + */ + public abstract byte @NonNull [] sha256(); + + /** + * Gets the resource pack size. + * + * @return the resource pack file size + */ + public abstract long size(); + + /** + * Serializes the given resource pack into a byte buffer. + * + * @param resourcePack the resource pack to serialize + * @return the serialized resource pack + */ + @NonNull + public abstract SeekableByteChannel serialize(@NonNull ResourcePack resourcePack) throws IOException; + + /** + * Creates a new resource pack from this codec. + * + * @return the new resource pack + */ + @NonNull + protected abstract ResourcePack create(); + + /** + * Creates a new pack provider from the given path. + * + * @param path the path to create the pack provider from + * @return the new pack provider + */ + @NonNull + public static PackCodec path(@NonNull Path path) { + return GeyserApi.api().provider(PathPackCodec.class, path); + } +} diff --git a/api/src/main/java/org/geysermc/geyser/api/pack/PathPackCodec.java b/api/src/main/java/org/geysermc/geyser/api/pack/PathPackCodec.java new file mode 100644 index 000000000..ee5db8242 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/pack/PathPackCodec.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2019-2023 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.api.pack; + +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.nio.file.Path; + +/** + * Represents a pack codec that creates a resource + * pack from a path on the filesystem. + */ +public abstract class PathPackCodec extends PackCodec { + + /** + * Gets the path of the resource pack. + * + * @return the path of the resource pack + */ + @NonNull + public abstract Path path(); +} diff --git a/api/src/main/java/org/geysermc/geyser/api/pack/ResourcePack.java b/api/src/main/java/org/geysermc/geyser/api/pack/ResourcePack.java new file mode 100644 index 000000000..de1beaf65 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/pack/ResourcePack.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2019-2023 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.api.pack; + +import org.checkerframework.checker.nullness.qual.NonNull; + +/** + * Represents a resource pack sent to Bedrock clients + *

+ * This representation of a resource pack only contains what + * Geyser requires to send it to the client. + */ +public interface ResourcePack { + + /** + * The {@link PackCodec codec} for this pack. + * + * @return the codec for this pack + */ + @NonNull + PackCodec codec(); + + /** + * Gets the resource pack manifest. + * + * @return the resource pack manifest + */ + @NonNull + ResourcePackManifest manifest(); + + /** + * Gets the content key of the resource pack. Lack of a content key is represented by an empty String. + * + * @return the content key of the resource pack + */ + @NonNull + String contentKey(); + + /** + * Creates a resource pack with the given {@link PackCodec}. + * + * @param codec the pack codec + * @return the resource pack + */ + @NonNull + static ResourcePack create(@NonNull PackCodec codec) { + return codec.create(); + } +} diff --git a/api/src/main/java/org/geysermc/geyser/api/pack/ResourcePackManifest.java b/api/src/main/java/org/geysermc/geyser/api/pack/ResourcePackManifest.java new file mode 100644 index 000000000..c9ccdd6c5 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/pack/ResourcePackManifest.java @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2019-2023 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.api.pack; + +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.util.Collection; +import java.util.UUID; + +/** + * Represents a resource pack manifest. + */ +public interface ResourcePackManifest { + + /** + * Gets the format version of the resource pack. + * + * @return the format version + */ + int formatVersion(); + + /** + * Gets the header of the resource pack. + * + * @return the header + */ + @NonNull + Header header(); + + /** + * Gets the modules of the resource pack. + * + * @return the modules + */ + @NonNull + Collection modules(); + + /** + * Gets the dependencies of the resource pack. + * + * @return the dependencies + */ + @NonNull + Collection dependencies(); + + /** + * Represents the header of a resource pack. + */ + interface Header { + + /** + * Gets the UUID of the resource pack. + * + * @return the UUID + */ + @NonNull + UUID uuid(); + + /** + * Gets the version of the resource pack. + * + * @return the version + */ + @NonNull + Version version(); + + /** + * Gets the name of the resource pack. + * + * @return the name + */ + @NonNull + String name(); + + /** + * Gets the description of the resource pack. + * + * @return the description + */ + @NonNull + String description(); + + /** + * Gets the minimum supported Minecraft version of the resource pack. + * + * @return the minimum supported Minecraft version + */ + @NonNull + Version minimumSupportedMinecraftVersion(); + } + + /** + * Represents a module of a resource pack. + */ + interface Module { + + /** + * Gets the UUID of the module. + * + * @return the UUID + */ + @NonNull + UUID uuid(); + + /** + * Gets the version of the module. + * + * @return the version + */ + @NonNull + Version version(); + + /** + * Gets the type of the module. + * + * @return the type + */ + @NonNull + String type(); + + /** + * Gets the description of the module. + * + * @return the description + */ + @NonNull + String description(); + } + + /** + * Represents a dependency of a resource pack. + */ + interface Dependency { + + /** + * Gets the UUID of the dependency. + * + * @return the uuid + */ + @NonNull + UUID uuid(); + + /** + * Gets the version of the dependency. + * + * @return the version + */ + @NonNull + Version version(); + } + + /** + * Represents a version of a resource pack. + */ + interface Version { + + /** + * Gets the major version. + * + * @return the major version + */ + int major(); + + /** + * Gets the minor version. + * + * @return the minor version + */ + int minor(); + + /** + * Gets the patch version. + * + * @return the patch version + */ + int patch(); + + /** + * Gets the version formatted as a String. + * + * @return the version string + */ + @NonNull String toString(); + } +} + diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 97540f96e..4d94479c3 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -30,7 +30,7 @@ dependencies { } implementation(libs.raknet) { - exclude("io.netty", "*"); + exclude("io.netty", "*") } implementation(libs.netty.resolver.dns) diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index 8204cfd3b..796e5ed06 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -69,9 +69,9 @@ import org.geysermc.geyser.event.GeyserEventBus; import org.geysermc.geyser.extension.GeyserExtensionManager; import org.geysermc.geyser.level.WorldManager; import org.geysermc.geyser.network.netty.GeyserServer; -import org.geysermc.geyser.pack.ResourcePack; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.Registries; +import org.geysermc.geyser.registry.loader.RegistryLoaders; import org.geysermc.geyser.scoreboard.ScoreboardUpdater; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.PendingMicrosoftAuthentication; @@ -90,6 +90,7 @@ import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; +import java.nio.file.Path; import java.security.Key; import java.text.DecimalFormat; import java.util.*; @@ -258,7 +259,7 @@ public class GeyserImpl implements GeyserApi { SkinProvider.registerCacheImageTask(this); - ResourcePack.loadPacks(); + Registries.RESOURCE_PACKS.load(); String geyserUdpPort = System.getProperty("geyserUdpPort", ""); String pluginUdpPort = geyserUdpPort.isEmpty() ? System.getProperty("pluginUdpPort", "") : geyserUdpPort; @@ -622,7 +623,7 @@ public class GeyserImpl implements GeyserApi { this.erosionUnixListener.close(); } - ResourcePack.PACKS.clear(); + Registries.RESOURCE_PACKS.get().clear(); this.eventBus.fire(new GeyserShutdownEvent(this.extensionManager, this.eventBus)); this.extensionManager.disableExtensions(); @@ -681,6 +682,18 @@ public class GeyserImpl implements GeyserApi { return getConfig().getBedrock(); } + @Override + @NonNull + public Path configDirectory() { + return bootstrap.getConfigFolder(); + } + + @Override + @NonNull + public Path packDirectory() { + return bootstrap.getConfigFolder().resolve("packs"); + } + public int buildNumber() { if (!this.isProductionEnvironment()) { return 0; diff --git a/core/src/main/java/org/geysermc/geyser/event/type/SessionLoadResourcePacksEventImpl.java b/core/src/main/java/org/geysermc/geyser/event/type/SessionLoadResourcePacksEventImpl.java new file mode 100644 index 000000000..5ed0f8d22 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/event/type/SessionLoadResourcePacksEventImpl.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2019-2023 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.event.type; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.api.event.bedrock.SessionLoadResourcePacksEvent; +import org.geysermc.geyser.api.pack.ResourcePack; +import org.geysermc.geyser.session.GeyserSession; + +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public class SessionLoadResourcePacksEventImpl extends SessionLoadResourcePacksEvent { + + private final Map packs; + + public SessionLoadResourcePacksEventImpl(GeyserSession session, Map packMap) { + super(session); + this.packs = packMap; + } + + public @NonNull Map getPacks() { + return packs; + } + + @Override + public @NonNull List resourcePacks() { + return List.copyOf(packs.values()); + } + + @Override + public boolean register(@NonNull ResourcePack resourcePack) { + String packID = resourcePack.manifest().header().uuid().toString(); + if (packs.containsValue(resourcePack) || packs.containsKey(packID)) { + return false; + } + packs.put(resourcePack.manifest().header().uuid().toString(), resourcePack); + return true; + } + + @Override + public boolean unregister(@NonNull UUID uuid) { + return packs.remove(uuid.toString()) != null; + } +} diff --git a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java index 225f8207a..b7955e218 100644 --- a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java +++ b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java @@ -49,9 +49,12 @@ import org.cloudburstmc.protocol.common.PacketSignal; import org.geysermc.geyser.Constants; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.network.AuthType; +import org.geysermc.geyser.api.pack.PackCodec; +import org.geysermc.geyser.api.pack.ResourcePack; +import org.geysermc.geyser.api.pack.ResourcePackManifest; import org.geysermc.geyser.configuration.GeyserConfiguration; -import org.geysermc.geyser.pack.ResourcePack; -import org.geysermc.geyser.pack.ResourcePackManifest; +import org.geysermc.geyser.event.type.SessionLoadResourcePacksEventImpl; +import org.geysermc.geyser.pack.GeyserResourcePack; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.session.GeyserSession; @@ -61,16 +64,20 @@ import org.geysermc.geyser.util.LoginEncryptionUtils; import org.geysermc.geyser.util.MathUtils; import org.geysermc.geyser.util.VersionCheckUtils; -import java.io.FileInputStream; -import java.io.InputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.SeekableByteChannel; import java.util.ArrayDeque; import java.util.Deque; +import java.util.HashMap; import java.util.OptionalInt; public class UpstreamPacketHandler extends LoggingPacketHandler { private boolean networkSettingsRequested = false; - private Deque packsToSent = new ArrayDeque<>(); + private final Deque packsToSent = new ArrayDeque<>(); + + private SessionLoadResourcePacksEventImpl resourcePackLoadEvent; public UpstreamPacketHandler(GeyserImpl geyser, GeyserSession session) { super(geyser, session); @@ -172,12 +179,16 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { geyser.getSessionManager().addPendingSession(session); + this.resourcePackLoadEvent = new SessionLoadResourcePacksEventImpl(session, new HashMap<>(Registries.RESOURCE_PACKS.get())); + this.geyser.eventBus().fire(this.resourcePackLoadEvent); + ResourcePacksInfoPacket resourcePacksInfo = new ResourcePacksInfoPacket(); - for(ResourcePack resourcePack : ResourcePack.PACKS.values()) { - ResourcePackManifest.Header header = resourcePack.getManifest().getHeader(); + for (ResourcePack pack : this.resourcePackLoadEvent.resourcePacks()) { + PackCodec codec = pack.codec(); + ResourcePackManifest.Header header = pack.manifest().header(); resourcePacksInfo.getResourcePackInfos().add(new ResourcePacksInfoPacket.Entry( - header.getUuid().toString(), header.getVersionString(), resourcePack.getFile().length(), - resourcePack.getContentKey(), "", header.getUuid().toString(), false, false)); + header.uuid().toString(), header.version().toString(), codec.size(), pack.contentKey(), + "", header.uuid().toString(), false, false)); } resourcePacksInfo.setForcedToAccept(GeyserImpl.getInstance().getConfig().isForceResourcePacks()); session.sendUpstreamPacket(resourcePacksInfo); @@ -210,9 +221,9 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { stackPacket.setForcedToAccept(false); // Leaving this as false allows the player to choose to download or not stackPacket.setGameVersion(session.getClientData().getGameVersion()); - for (ResourcePack pack : ResourcePack.PACKS.values()) { - ResourcePackManifest.Header header = pack.getManifest().getHeader(); - stackPacket.getResourcePacks().add(new ResourcePackStackPacket.Entry(header.getUuid().toString(), header.getVersionString(), "")); + for (ResourcePack pack : this.resourcePackLoadEvent.resourcePacks()) { + ResourcePackManifest.Header header = pack.manifest().header(); + stackPacket.getResourcePacks().add(new ResourcePackStackPacket.Entry(header.uuid().toString(), header.version().toString(), "")); } if (GeyserImpl.getInstance().getConfig().isAddNonBedrockItems()) { @@ -291,21 +302,22 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { @Override public PacketSignal handle(ResourcePackChunkRequestPacket packet) { ResourcePackChunkDataPacket data = new ResourcePackChunkDataPacket(); - ResourcePack pack = ResourcePack.PACKS.get(packet.getPackId().toString()); + ResourcePack pack = this.resourcePackLoadEvent.getPacks().get(packet.getPackId().toString()); + PackCodec codec = pack.codec(); data.setChunkIndex(packet.getChunkIndex()); - data.setProgress(packet.getChunkIndex() * ResourcePack.CHUNK_SIZE); + data.setProgress((long) packet.getChunkIndex() * GeyserResourcePack.CHUNK_SIZE); data.setPackVersion(packet.getPackVersion()); data.setPackId(packet.getPackId()); - int offset = packet.getChunkIndex() * ResourcePack.CHUNK_SIZE; - long remainingSize = pack.getFile().length() - offset; - byte[] packData = new byte[(int) MathUtils.constrain(remainingSize, 0, ResourcePack.CHUNK_SIZE)]; + int offset = packet.getChunkIndex() * GeyserResourcePack.CHUNK_SIZE; + long remainingSize = codec.size() - offset; + byte[] packData = new byte[(int) MathUtils.constrain(remainingSize, 0, GeyserResourcePack.CHUNK_SIZE)]; - try (InputStream inputStream = new FileInputStream(pack.getFile())) { - inputStream.skip(offset); - inputStream.read(packData, 0, packData.length); - } catch (Exception e) { + try (SeekableByteChannel channel = codec.serialize(pack)) { + channel.position(offset); + channel.read(ByteBuffer.wrap(packData, 0, packData.length)); + } catch (IOException e) { e.printStackTrace(); } @@ -314,7 +326,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { session.sendUpstreamPacket(data); // Check if it is the last chunk and send next pack in queue when available. - if (remainingSize <= ResourcePack.CHUNK_SIZE && !packsToSent.isEmpty()) { + if (remainingSize <= GeyserResourcePack.CHUNK_SIZE && !packsToSent.isEmpty()) { sendPackDataInfo(packsToSent.pop()); } @@ -324,15 +336,16 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { private void sendPackDataInfo(String id) { ResourcePackDataInfoPacket data = new ResourcePackDataInfoPacket(); String[] packID = id.split("_"); - ResourcePack pack = ResourcePack.PACKS.get(packID[0]); - ResourcePackManifest.Header header = pack.getManifest().getHeader(); + ResourcePack pack = this.resourcePackLoadEvent.getPacks().get(packID[0]); + PackCodec codec = pack.codec(); + ResourcePackManifest.Header header = pack.manifest().header(); - data.setPackId(header.getUuid()); - int chunkCount = (int) Math.ceil((int) pack.getFile().length() / (double) ResourcePack.CHUNK_SIZE); + data.setPackId(header.uuid()); + int chunkCount = (int) Math.ceil(codec.size() / (double) GeyserResourcePack.CHUNK_SIZE); data.setChunkCount(chunkCount); - data.setCompressedPackSize(pack.getFile().length()); - data.setMaxChunkSize(ResourcePack.CHUNK_SIZE); - data.setHash(pack.getSha256()); + data.setCompressedPackSize(codec.size()); + data.setMaxChunkSize(GeyserResourcePack.CHUNK_SIZE); + data.setHash(codec.sha256()); data.setPackVersion(packID[1]); data.setPremium(false); data.setType(ResourcePackType.RESOURCES); diff --git a/core/src/main/java/org/geysermc/geyser/pack/GeyserResourcePack.java b/core/src/main/java/org/geysermc/geyser/pack/GeyserResourcePack.java new file mode 100644 index 000000000..82408b6e7 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/pack/GeyserResourcePack.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2019-2023 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.pack; + +import org.geysermc.geyser.api.pack.PackCodec; +import org.geysermc.geyser.api.pack.ResourcePack; +import org.geysermc.geyser.api.pack.ResourcePackManifest; + +public record GeyserResourcePack(PackCodec codec, ResourcePackManifest manifest, String contentKey) implements ResourcePack { + + /** + * The size of each chunk to use when sending the resource packs to clients in bytes + */ + public static final int CHUNK_SIZE = 102400; +} diff --git a/core/src/main/java/org/geysermc/geyser/pack/GeyserResourcePackManifest.java b/core/src/main/java/org/geysermc/geyser/pack/GeyserResourcePackManifest.java new file mode 100644 index 000000000..ddcee6ad5 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/pack/GeyserResourcePackManifest.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2019-2023 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.pack; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import org.geysermc.geyser.api.pack.ResourcePackManifest; +import org.jetbrains.annotations.NotNull; + +import java.io.IOException; +import java.util.Collection; +import java.util.UUID; + +public record GeyserResourcePackManifest(@JsonProperty("format_version") int formatVersion, Header header, Collection modules, Collection dependencies) implements ResourcePackManifest { + + public record Header(UUID uuid, Version version, String name, String description, @JsonProperty("min_engine_version") Version minimumSupportedMinecraftVersion) implements ResourcePackManifest.Header { } + + public record Module(UUID uuid, Version version, String type, String description) implements ResourcePackManifest.Module { } + + public record Dependency(UUID uuid, Version version) implements ResourcePackManifest.Dependency { } + + @JsonDeserialize(using = Version.VersionDeserializer.class) + public record Version(int major, int minor, int patch) implements ResourcePackManifest.Version { + + @Override + public @NotNull String toString() { + return major + "." + minor + "." + patch; + } + + public static class VersionDeserializer extends JsonDeserializer { + @Override + public Version deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + int[] version = ctxt.readValue(p, int[].class); + return new Version(version[0], version[1], version[2]); + } + } + } +} + diff --git a/core/src/main/java/org/geysermc/geyser/pack/ResourcePack.java b/core/src/main/java/org/geysermc/geyser/pack/ResourcePack.java deleted file mode 100644 index 07d56194a..000000000 --- a/core/src/main/java/org/geysermc/geyser/pack/ResourcePack.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * 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.pack; - -import lombok.Getter; -import org.geysermc.geyser.GeyserImpl; -import org.geysermc.geyser.api.event.lifecycle.GeyserLoadResourcePacksEvent; -import org.geysermc.geyser.text.GeyserLocale; -import org.geysermc.geyser.util.FileUtils; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -/** - * This represents a resource pack and all the data relevant to it - */ -public class ResourcePack { - /** - * The list of loaded resource packs - */ - public static final Map PACKS = new HashMap<>(); - - /** - * The size of each chunk to use when sending the resource packs to clients in bytes - */ - public static final int CHUNK_SIZE = 102400; - - private byte[] sha256; - private File file; - private ResourcePackManifest manifest; - private ResourcePackManifest.Version version; - - @Getter - private String contentKey; - - /** - * Loop through the packs directory and locate valid resource pack files - */ - public static void loadPacks() { - Path directory = GeyserImpl.getInstance().getBootstrap().getConfigFolder().resolve("packs"); - - if (!Files.exists(directory)) { - try { - Files.createDirectory(directory); - } catch (IOException e) { - GeyserImpl.getInstance().getLogger().error("Could not create packs directory", e); - } - - // As we just created the directory it will be empty - return; - } - - List resourcePacks; - try { - resourcePacks = Files.walk(directory).collect(Collectors.toList()); - } catch (IOException e) { - GeyserImpl.getInstance().getLogger().error("Could not list packs directory", e); - return; - } - - GeyserLoadResourcePacksEvent event = new GeyserLoadResourcePacksEvent(resourcePacks); - GeyserImpl.getInstance().eventBus().fire(event); - - for (Path path : event.resourcePacks()) { - File file = path.toFile(); - - if (file.getName().endsWith(".zip") || file.getName().endsWith(".mcpack")) { - ResourcePack pack = new ResourcePack(); - - pack.sha256 = FileUtils.calculateSHA256(file); - - try (ZipFile zip = new ZipFile(file); - Stream stream = zip.stream()) { - stream.forEach((x) -> { - String name = x.getName(); - if (name.length() >= 80) { - GeyserImpl.getInstance().getLogger().warning("The resource pack " + file.getName() - + " has a file in it that meets or exceeds 80 characters in its path (" + name - + ", " + name.length() + " characters long). This will cause problems on some Bedrock platforms." + - " Please rename it to be shorter, or reduce the amount of folders needed to get to the file."); - } - if (name.contains("manifest.json")) { - try { - ResourcePackManifest manifest = FileUtils.loadJson(zip.getInputStream(x), ResourcePackManifest.class); - // Sometimes a pack_manifest file is present and not in a valid format, - // but a manifest file is, so we null check through that one - if (manifest.getHeader().getUuid() != null) { - pack.file = file; - pack.manifest = manifest; - pack.version = ResourcePackManifest.Version.fromArray(manifest.getHeader().getVersion()); - - PACKS.put(pack.getManifest().getHeader().getUuid().toString(), pack); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - - // Check if a file exists with the same name as the resource pack suffixed by .key, - // and set this as content key. (e.g. test.zip, key file would be test.zip.key) - File keyFile = new File(file.getParentFile(), file.getName() + ".key"); - pack.contentKey = keyFile.exists() ? Files.readString(keyFile.toPath(), StandardCharsets.UTF_8) : ""; - } catch (Exception e) { - GeyserImpl.getInstance().getLogger().error(GeyserLocale.getLocaleStringLog("geyser.resource_pack.broken", file.getName())); - e.printStackTrace(); - } - } - } - } - - public byte[] getSha256() { - return sha256; - } - - public File getFile() { - return file; - } - - public ResourcePackManifest getManifest() { - return manifest; - } - - public ResourcePackManifest.Version getVersion() { - return version; - } -} diff --git a/core/src/main/java/org/geysermc/geyser/pack/ResourcePackManifest.java b/core/src/main/java/org/geysermc/geyser/pack/ResourcePackManifest.java deleted file mode 100644 index 2b14eade3..000000000 --- a/core/src/main/java/org/geysermc/geyser/pack/ResourcePackManifest.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * 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.pack; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.ToString; -import lombok.Value; - -import java.util.Collection; -import java.util.Collections; -import java.util.UUID; - -/** - * author: NukkitX - * Nukkit Project - */ -@Getter -@EqualsAndHashCode -public class ResourcePackManifest { - @JsonProperty("format_version") - private Integer formatVersion; - private Header header; - private Collection modules; - protected Collection dependencies; - - public Collection getModules() { - return Collections.unmodifiableCollection(modules); - } - - @Getter - @ToString - public static class Header { - private String description; - private String name; - private UUID uuid; - private int[] version; - @JsonProperty("min_engine_version") - private int[] minimumSupportedMinecraftVersion; - - public String getVersionString() { - return version[0] + "." + version[1] + "." + version[2]; - } - } - - @Getter - @ToString - public static class Module { - private String description; - private String name; - private UUID uuid; - private int[] version; - } - - @Getter - @ToString - public static class Dependency { - private UUID uuid; - private int[] version; - } - - @Value - public static class Version { - private final int major; - private final int minor; - private final int patch; - - public static Version fromString(String ver) { - String[] split = ver.replace(']', ' ') - .replace('[', ' ') - .replaceAll(" ", "").split(","); - - return new Version(Integer.parseInt(split[0]), Integer.parseInt(split[1]), Integer.parseInt(split[2])); - } - - public static Version fromArray(int[] ver) { - return new Version(ver[0], ver[1], ver[2]); - } - - private Version(int major, int minor, int patch) { - this.major = major; - this.minor = minor; - this.patch = patch; - } - - - @Override - public String toString() { - return major + "." + minor + "." + patch; - } - } -} - diff --git a/core/src/main/java/org/geysermc/geyser/pack/path/GeyserPathPackCodec.java b/core/src/main/java/org/geysermc/geyser/pack/path/GeyserPathPackCodec.java new file mode 100644 index 000000000..84067600f --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/pack/path/GeyserPathPackCodec.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2019-2023 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.pack.path; + +import lombok.RequiredArgsConstructor; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.pack.PathPackCodec; +import org.geysermc.geyser.api.pack.ResourcePack; +import org.geysermc.geyser.registry.loader.ResourcePackLoader; +import org.geysermc.geyser.util.FileUtils; + +import java.io.IOException; +import java.nio.channels.FileChannel; +import java.nio.channels.SeekableByteChannel; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.attribute.FileTime; + +@RequiredArgsConstructor +public class GeyserPathPackCodec extends PathPackCodec { + private final Path path; + private FileTime lastModified; + + private byte[] sha256; + private long size = -1; + + @Override + public @NonNull Path path() { + this.checkLastModified(); + return this.path; + } + + @Override + public byte @NonNull [] sha256() { + this.checkLastModified(); + if (this.sha256 != null) { + return this.sha256; + } + + return this.sha256 = FileUtils.calculateSHA256(this.path); + } + + @Override + public long size() { + this.checkLastModified(); + if (this.size != -1) { + return this.size; + } + + try { + return this.size = Files.size(this.path); + } catch (IOException e) { + throw new RuntimeException("Could not get file size of path " + this.path, e); + } + } + + @Override + public @NonNull SeekableByteChannel serialize(@NonNull ResourcePack resourcePack) throws IOException { + return FileChannel.open(this.path); + } + + @Override + protected @NonNull ResourcePack create() { + return ResourcePackLoader.readPack(this.path); + } + + private void checkLastModified() { + try { + FileTime lastModified = Files.getLastModifiedTime(this.path); + if (this.lastModified == null) { + this.lastModified = lastModified; + return; + } + + if (lastModified.toInstant().isAfter(this.lastModified.toInstant())) { + GeyserImpl.getInstance().getLogger().warning("Detected a change in the resource pack " + path + ". This is likely to cause undefined behavior for new clients joining. It is suggested you restart Geyser."); + this.lastModified = lastModified; + this.sha256 = null; + this.size = -1; + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/core/src/main/java/org/geysermc/geyser/registry/DeferredRegistry.java b/core/src/main/java/org/geysermc/geyser/registry/DeferredRegistry.java new file mode 100644 index 000000000..bf3050a61 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/DeferredRegistry.java @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2019-2023 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; + +import org.geysermc.geyser.registry.loader.RegistryLoader; +import org.geysermc.geyser.registry.loader.RegistryLoaders; + +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +/** + * A deferred registry is a registry that is not loaded until it is needed. + * This is useful for registries that are not needed until after other parts + * of the lifecycle have been completed. + *

+ * This class is slightly different from other registries in that it acts as + * a wrapper around another registry. This is to allow for any kind of registry + * type to be deferred. + * + * @param the value being held by the registry + */ +public final class DeferredRegistry implements IRegistry { + private final Registry backingRegistry; + private final Supplier loader; + + private boolean loaded; + + private DeferredRegistry(Function, Registry> registryLoader, RegistryLoader deferredLoader) { + this.backingRegistry = registryLoader.apply(RegistryLoaders.uninitialized()); + this.loader = () -> deferredLoader.load(null); + } + + private DeferredRegistry(Function, Registry> registryLoader, Supplier> deferredLoader) { + this.backingRegistry = registryLoader.apply(RegistryLoaders.uninitialized()); + this.loader = () -> deferredLoader.get().load(null); + } + + private DeferredRegistry(I input, RegistryInitializer registryInitializer, RegistryLoader deferredLoader) { + this.backingRegistry = registryInitializer.initialize(input, RegistryLoaders.uninitialized()); + this.loader = () -> deferredLoader.load(input); + } + + private DeferredRegistry(I input, RegistryInitializer registryInitializer, Supplier> deferredLoader) { + this.backingRegistry = registryInitializer.initialize(input, RegistryLoaders.uninitialized()); + this.loader = () -> deferredLoader.get().load(input); + } + + @Override + public M get() { + if (!this.loaded) { + throw new IllegalStateException("Registry has not been loaded yet!"); + } + + return this.backingRegistry.get(); + } + + @Override + public void set(M mappings) { + if (!this.loaded) { + throw new IllegalStateException("Registry has not been loaded yet!"); + } + + this.backingRegistry.set(mappings); + } + + @Override + public void register(Consumer consumer) { + if (!this.loaded) { + throw new IllegalStateException("Registry has not been loaded yet!"); + } + + this.backingRegistry.register(consumer); + } + + /** + * Loads the registry. + */ + public void load() { + if (this.loaded) { + throw new IllegalStateException("Registry has already been loaded!"); + } + + this.backingRegistry.set(this.loader.get()); + this.loaded = true; + } + + /** + * Creates a new deferred registry. + * + * @param registryLoader the registry loader + * @param deferredLoader the deferred loader + * @param the input type + * @param the registry type + * @return the new deferred registry + */ + public static DeferredRegistry create(Function, Registry> registryLoader, RegistryLoader deferredLoader) { + return new DeferredRegistry<>(registryLoader, deferredLoader); + } + + /** + * Creates a new deferred registry. + * + * @param registryLoader the registry loader + * @param deferredLoader the deferred loader + * @param the input type + * @param the registry type + * @return the new deferred registry + */ + public static DeferredRegistry create(Function, Registry> registryLoader, Supplier> deferredLoader) { + return new DeferredRegistry<>(registryLoader, deferredLoader); + } + + /** + * Creates a new deferred registry. + * + * @param registryInitializer the registry initializer + * @param deferredLoader the deferred loader + * @param the input type + * @param the registry type + * @return the new deferred registry + */ + public static DeferredRegistry create(I input, RegistryInitializer registryInitializer, RegistryLoader deferredLoader) { + return new DeferredRegistry<>(input, registryInitializer, deferredLoader); + } + + /** + * Creates a new deferred registry. + * + * @param registryInitializer the registry initializer + * @param deferredLoader the deferred loader + * @param the input type + * @param the registry type + * @return the new deferred registry + */ + public static DeferredRegistry create(I input, RegistryInitializer registryInitializer, Supplier> deferredLoader) { + return new DeferredRegistry<>(input, registryInitializer, deferredLoader); + } + + /** + * A registry initializer. + * + * @param the registry type + */ + interface RegistryInitializer { + + /** + * Initializes the registry. + * + * @param input the input + * @param registryLoader the registry loader + * @param the input type + * @return the initialized registry + */ + Registry initialize(I input, RegistryLoader registryLoader); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/registry/IRegistry.java b/core/src/main/java/org/geysermc/geyser/registry/IRegistry.java new file mode 100644 index 000000000..fdb5f8c77 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/IRegistry.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2019-2023 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; + +import java.util.function.Consumer; + +/** + * Represents a registry. + * + * @param the value being held by the registry + */ +interface IRegistry { + + /** + * Gets the underlying value held by this registry. + * + * @return the underlying value held by this registry. + */ + M get(); + + /** + * Sets the underlying value held by this registry. + * Clears any existing data associated with the previous + * value. + * + * @param mappings the underlying value held by this registry + */ + void set(M mappings); + + /** + * Registers what is specified in the given + * {@link Consumer} into the underlying value. + * + * @param consumer the consumer + */ + void register(Consumer consumer); +} diff --git a/core/src/main/java/org/geysermc/geyser/registry/Registries.java b/core/src/main/java/org/geysermc/geyser/registry/Registries.java index 0bf6ae078..73ae23e9e 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/Registries.java +++ b/core/src/main/java/org/geysermc/geyser/registry/Registries.java @@ -41,6 +41,8 @@ import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.PotionMixData; import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.RecipeData; import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket; +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.pack.ResourcePack; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.inventory.item.Enchantment.JavaEnchantment; import org.geysermc.geyser.inventory.recipe.GeyserRecipe; @@ -158,6 +160,11 @@ public final class Registries { */ public static final IntMappedRegistry RECORDS = IntMappedRegistry.create(RegistryLoaders.empty(Int2ObjectOpenHashMap::new)); + /** + * A mapped registry holding {@link ResourcePack}'s with the pack uuid as keys. + */ + public static final DeferredRegistry> RESOURCE_PACKS = DeferredRegistry.create(GeyserImpl.getInstance().packDirectory(), SimpleMappedRegistry::create, RegistryLoaders.RESOURCE_PACKS); + /** * A mapped registry holding sound identifiers to their corresponding {@link SoundMapping}. */ diff --git a/core/src/main/java/org/geysermc/geyser/registry/Registry.java b/core/src/main/java/org/geysermc/geyser/registry/Registry.java index afee87b08..f6be19af2 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/Registry.java +++ b/core/src/main/java/org/geysermc/geyser/registry/Registry.java @@ -64,7 +64,7 @@ import java.util.function.Consumer; * * @param the value being held by the registry */ -public abstract class Registry { +public abstract class Registry implements IRegistry { protected M mappings; /** @@ -85,6 +85,7 @@ public abstract class Registry { * * @return the underlying value held by this registry. */ + @Override public M get() { return this.mappings; } @@ -96,6 +97,7 @@ public abstract class Registry { * * @param mappings the underlying value held by this registry */ + @Override public void set(M mappings) { this.mappings = mappings; } @@ -106,6 +108,7 @@ public abstract class Registry { * * @param consumer the consumer */ + @Override public void register(Consumer consumer) { consumer.accept(this.mappings); } diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/ProviderRegistryLoader.java b/core/src/main/java/org/geysermc/geyser/registry/loader/ProviderRegistryLoader.java index 99a9213fe..d32b11cc0 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/loader/ProviderRegistryLoader.java +++ b/core/src/main/java/org/geysermc/geyser/registry/loader/ProviderRegistryLoader.java @@ -31,13 +31,16 @@ import org.geysermc.geyser.api.extension.Extension; 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.api.pack.PathPackCodec; import org.geysermc.geyser.command.GeyserCommandManager; import org.geysermc.geyser.event.GeyserEventRegistrar; import org.geysermc.geyser.item.GeyserCustomItemData; import org.geysermc.geyser.item.GeyserCustomItemOptions; import org.geysermc.geyser.item.GeyserNonVanillaCustomItemData; +import org.geysermc.geyser.pack.path.GeyserPathPackCodec; import org.geysermc.geyser.registry.provider.ProviderSupplier; +import java.nio.file.Path; import java.util.Map; /** @@ -47,11 +50,15 @@ public class ProviderRegistryLoader implements RegistryLoader, Prov @Override public Map, ProviderSupplier> load(Map, ProviderSupplier> providers) { + // misc providers.put(Command.Builder.class, args -> new GeyserCommandManager.CommandBuilder<>((Extension) args[0])); + providers.put(EventRegistrar.class, args -> new GeyserEventRegistrar(args[0])); + providers.put(PathPackCodec.class, args -> new GeyserPathPackCodec((Path) args[0])); + + // items providers.put(CustomItemData.Builder.class, args -> new GeyserCustomItemData.CustomItemDataBuilder()); providers.put(CustomItemOptions.Builder.class, args -> new GeyserCustomItemOptions.CustomItemOptionsBuilder()); providers.put(NonVanillaCustomItemData.Builder.class, args -> new GeyserNonVanillaCustomItemData.NonVanillaCustomItemDataBuilder()); - providers.put(EventRegistrar.class, args -> new GeyserEventRegistrar(args[0])); return providers; } diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/RegistryLoaders.java b/core/src/main/java/org/geysermc/geyser/registry/loader/RegistryLoaders.java index 62b6e4737..eaede3b15 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/loader/RegistryLoaders.java +++ b/core/src/main/java/org/geysermc/geyser/registry/loader/RegistryLoaders.java @@ -36,7 +36,12 @@ public final class RegistryLoaders { /** * The {@link RegistryLoader} responsible for loading NBT. */ - public static NbtRegistryLoader NBT = new NbtRegistryLoader(); + public static final NbtRegistryLoader NBT = new NbtRegistryLoader(); + + /** + * The {@link RegistryLoader} responsible for loading resource packs. + */ + public static final ResourcePackLoader RESOURCE_PACKS = new ResourcePackLoader(); /** * Wraps the surrounding {@link Supplier} in a {@link RegistryLoader} which does @@ -51,10 +56,14 @@ public final class RegistryLoaders { } /** + * Returns a {@link RegistryLoader} which has not taken + * in any input value. + * + * @param the input * @param the value * @return a RegistryLoader that is yet to contain a value. */ - public static RegistryLoader uninitialized() { + public static RegistryLoader uninitialized() { return input -> null; } diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/ResourcePackLoader.java b/core/src/main/java/org/geysermc/geyser/registry/loader/ResourcePackLoader.java new file mode 100644 index 000000000..afb5a2fe8 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/loader/ResourcePackLoader.java @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2019-2023 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.loader; + +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.event.lifecycle.GeyserLoadResourcePacksEvent; +import org.geysermc.geyser.api.pack.ResourcePack; +import org.geysermc.geyser.pack.GeyserResourcePack; +import org.geysermc.geyser.pack.GeyserResourcePackManifest; +import org.geysermc.geyser.pack.path.GeyserPathPackCodec; +import org.geysermc.geyser.text.GeyserLocale; +import org.geysermc.geyser.util.FileUtils; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.PathMatcher; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +/** + * Loads {@link ResourcePack}s within a {@link Path} directory, firing the {@link GeyserLoadResourcePacksEvent}. + */ +public class ResourcePackLoader implements RegistryLoader> { + + static final PathMatcher PACK_MATCHER = FileSystems.getDefault().getPathMatcher("glob:**.{zip,mcpack}"); + + private static final boolean SHOW_RESOURCE_PACK_LENGTH_WARNING = Boolean.parseBoolean(System.getProperty("Geyser.ShowResourcePackLengthWarning", "true")); + + /** + * Loop through the packs directory and locate valid resource pack files + */ + @Override + public Map load(Path directory) { + Map packMap = new HashMap<>(); + + if (!Files.exists(directory)) { + try { + Files.createDirectory(directory); + } catch (IOException e) { + GeyserImpl.getInstance().getLogger().error("Could not create packs directory", e); + } + } + + List resourcePacks; + try (Stream stream = Files.walk(directory)) { + resourcePacks = stream.filter(PACK_MATCHER::matches) + .collect(Collectors.toCollection(ArrayList::new)); // toList() does not guarantee mutability + } catch (Exception e) { + GeyserImpl.getInstance().getLogger().error("Could not list packs directory", e); + + // Ensure the event is fired even if there was an issue reading + // from our own resource pack directory. External projects may have + // resource packs located at different locations. + resourcePacks = new ArrayList<>(); + } + + GeyserLoadResourcePacksEvent event = new GeyserLoadResourcePacksEvent(resourcePacks); + GeyserImpl.getInstance().eventBus().fire(event); + + for (Path path : event.resourcePacks()) { + try { + GeyserResourcePack pack = readPack(path); + packMap.put(pack.manifest().header().uuid().toString(), pack); + } catch (Exception e) { + e.printStackTrace(); + } + } + return packMap; + } + + /** + * Reads a resource pack at the given file. Also searches for a file in the same directory, with the same name + * but suffixed by ".key", containing the content key. If such file does not exist, no content key is stored. + * + * @param path the file to read from, in ZIP format + * @return a {@link ResourcePack} representation + * @throws IllegalArgumentException if the pack manifest was invalid or there was any processing exception + */ + public static GeyserResourcePack readPack(Path path) throws IllegalArgumentException { + if (!path.getFileName().toString().endsWith(".mcpack") && !path.getFileName().toString().endsWith(".zip")) { + throw new IllegalArgumentException("Resource pack " + path.getFileName() + " must be a .zip or .mcpack file!"); + } + + AtomicReference manifestReference = new AtomicReference<>(); + + try (ZipFile zip = new ZipFile(path.toFile()); + Stream stream = zip.stream()) { + stream.forEach(x -> { + String name = x.getName(); + if (SHOW_RESOURCE_PACK_LENGTH_WARNING && name.length() >= 80) { + GeyserImpl.getInstance().getLogger().warning("The resource pack " + path.getFileName() + + " has a file in it that meets or exceeds 80 characters in its path (" + name + + ", " + name.length() + " characters long). This will cause problems on some Bedrock platforms." + + " Please rename it to be shorter, or reduce the amount of folders needed to get to the file."); + } + if (name.contains("manifest.json")) { + try { + GeyserResourcePackManifest manifest = FileUtils.loadJson(zip.getInputStream(x), GeyserResourcePackManifest.class); + if (manifest.header().uuid() != null) { + manifestReference.set(manifest); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + }); + + GeyserResourcePackManifest manifest = manifestReference.get(); + if (manifest == null) { + throw new IllegalArgumentException(path.getFileName() + " does not contain a valid pack_manifest.json or manifest.json"); + } + + // Check if a file exists with the same name as the resource pack suffixed by .key, + // and set this as content key. (e.g. test.zip, key file would be test.zip.key) + Path keyFile = path.resolveSibling(path.getFileName().toString() + ".key"); + String contentKey = Files.exists(keyFile) ? Files.readString(path, StandardCharsets.UTF_8) : ""; + + return new GeyserResourcePack(new GeyserPathPackCodec(path), manifest, contentKey); + } catch (Exception e) { + throw new IllegalArgumentException(GeyserLocale.getLocaleStringLog("geyser.resource_pack.broken", path.getFileName()), e); + } + } +} diff --git a/core/src/main/java/org/geysermc/geyser/skin/ProvidedSkins.java b/core/src/main/java/org/geysermc/geyser/skin/ProvidedSkins.java index 999df0929..58c8f0072 100644 --- a/core/src/main/java/org/geysermc/geyser/skin/ProvidedSkins.java +++ b/core/src/main/java/org/geysermc/geyser/skin/ProvidedSkins.java @@ -30,10 +30,9 @@ import org.geysermc.geyser.util.AssetUtils; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; -import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.nio.file.Files; import java.nio.file.Path; import java.util.Objects; import java.util.UUID; @@ -80,14 +79,14 @@ public final class ProvidedSkins { .resolve(slim ? "slim" : "wide"); String assetName = asset.substring(asset.lastIndexOf('/') + 1); - File location = folder.resolve(assetName).toFile(); - AssetUtils.addTask(!location.exists(), new AssetUtils.ClientJarTask("assets/minecraft/" + asset, + Path location = folder.resolve(assetName); + AssetUtils.addTask(!Files.exists(location), new AssetUtils.ClientJarTask("assets/minecraft/" + asset, (stream) -> AssetUtils.saveFile(location, stream), () -> { try { // TODO lazy initialize? BufferedImage image; - try (InputStream stream = new FileInputStream(location)) { + try (InputStream stream = Files.newInputStream(location)) { image = ImageIO.read(stream); } diff --git a/core/src/main/java/org/geysermc/geyser/text/MinecraftLocale.java b/core/src/main/java/org/geysermc/geyser/text/MinecraftLocale.java index fa048cecf..260b45136 100644 --- a/core/src/main/java/org/geysermc/geyser/text/MinecraftLocale.java +++ b/core/src/main/java/org/geysermc/geyser/text/MinecraftLocale.java @@ -34,6 +34,7 @@ import org.geysermc.geyser.util.WebUtils; import javax.annotation.Nullable; import java.io.*; import java.nio.file.Files; +import java.nio.file.Path; import java.util.HashMap; import java.util.Iterator; import java.util.Locale; @@ -57,8 +58,8 @@ public class MinecraftLocale { } public static void ensureEN_US() { - File localeFile = getFile("en_us"); - AssetUtils.addTask(!localeFile.exists(), new AssetUtils.ClientJarTask("assets/minecraft/lang/en_us.json", + Path localeFile = getPath("en_us"); + AssetUtils.addTask(!Files.exists(localeFile), new AssetUtils.ClientJarTask("assets/minecraft/lang/en_us.json", (stream) -> AssetUtils.saveFile(localeFile, stream), () -> { if ("en_us".equals(GeyserLocale.getDefaultLocale())) { @@ -106,10 +107,10 @@ public class MinecraftLocale { if (locale.equals("en_us")) { return; } - File localeFile = getFile(locale); + Path localeFile = getPath(locale); // Check if we have already downloaded the locale file - if (localeFile.exists()) { + if (Files.exists(localeFile)) { String curHash = byteArrayToHexString(FileUtils.calculateSHA1(localeFile)); String targetHash = AssetUtils.getAsset("minecraft/lang/" + locale + ".json").getHash(); @@ -130,8 +131,8 @@ public class MinecraftLocale { } } - private static File getFile(String locale) { - return GeyserImpl.getInstance().getBootstrap().getConfigFolder().resolve("locales/" + locale + ".json").toFile(); + private static Path getPath(String locale) { + return GeyserImpl.getInstance().getBootstrap().getConfigFolder().resolve("locales/" + locale + ".json"); } /** diff --git a/core/src/main/java/org/geysermc/geyser/util/AssetUtils.java b/core/src/main/java/org/geysermc/geyser/util/AssetUtils.java index 299e63e0e..6bdae6dfe 100644 --- a/core/src/main/java/org/geysermc/geyser/util/AssetUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/AssetUtils.java @@ -192,8 +192,8 @@ public final class AssetUtils { } } - public static void saveFile(File location, InputStream fileStream) throws IOException { - try (FileOutputStream outStream = new FileOutputStream(location)) { + public static void saveFile(Path location, InputStream fileStream) throws IOException { + try (OutputStream outStream = Files.newOutputStream(location)) { // Write the file to the locale dir byte[] buf = new byte[fileStream.available()]; diff --git a/core/src/main/java/org/geysermc/geyser/util/FileUtils.java b/core/src/main/java/org/geysermc/geyser/util/FileUtils.java index 6df9c2177..2fde1547d 100644 --- a/core/src/main/java/org/geysermc/geyser/util/FileUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/FileUtils.java @@ -129,14 +129,14 @@ public class FileUtils { /** * Calculate the SHA256 hash of a file * - * @param file File to calculate the hash for + * @param path Path to calculate the hash for * @return A byte[] representation of the hash */ - public static byte[] calculateSHA256(File file) { + public static byte[] calculateSHA256(Path path) { byte[] sha256; try { - sha256 = MessageDigest.getInstance("SHA-256").digest(readAllBytes(file)); + sha256 = MessageDigest.getInstance("SHA-256").digest(Files.readAllBytes(path)); } catch (Exception e) { throw new RuntimeException("Could not calculate pack hash", e); } @@ -147,14 +147,14 @@ public class FileUtils { /** * Calculate the SHA1 hash of a file * - * @param file File to calculate the hash for + * @param path Path to calculate the hash for * @return A byte[] representation of the hash */ - public static byte[] calculateSHA1(File file) { + public static byte[] calculateSHA1(Path path) { byte[] sha1; try { - sha1 = MessageDigest.getInstance("SHA-1").digest(readAllBytes(file)); + sha1 = MessageDigest.getInstance("SHA-1").digest(Files.readAllBytes(path)); } catch (Exception e) { throw new RuntimeException("Could not calculate pack hash", e); } @@ -162,20 +162,6 @@ public class FileUtils { return sha1; } - /** - * An android compatible version of {@link Files#readAllBytes} - * - * @param file File to read bytes of - * @return The byte array of the file - */ - public static byte[] readAllBytes(File file) { - try (InputStream stream = new FileInputStream(file)) { - return stream.readAllBytes(); - } catch (IOException e) { - throw new RuntimeException("Cannot read " + file); - } - } - /** * @param resource the internal resource to read off from * @return the byte array of an InputStream diff --git a/core/src/test/java/org/geysermc/geyser/registry/loader/ResourcePackLoaderTest.java b/core/src/test/java/org/geysermc/geyser/registry/loader/ResourcePackLoaderTest.java new file mode 100644 index 000000000..8150ac446 --- /dev/null +++ b/core/src/test/java/org/geysermc/geyser/registry/loader/ResourcePackLoaderTest.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2019-2023 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.loader; + +import org.junit.jupiter.api.Test; + +import java.nio.file.Path; +import java.nio.file.PathMatcher; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class ResourcePackLoaderTest { + + @Test + public void testPathMatcher() { + PathMatcher matcher = ResourcePackLoader.PACK_MATCHER; + + assertTrue(matcher.matches(Path.of("pack.mcpack"))); + assertTrue(matcher.matches(Path.of("pack.zip"))); + assertTrue(matcher.matches(Path.of("packs", "pack.mcpack"))); + assertTrue(matcher.matches(Path.of("packs", "category", "pack.mcpack"))); + + assertTrue(matcher.matches(Path.of("packs", "Resource+Pack+1.2.3.mcpack"))); + assertTrue(matcher.matches(Path.of("Resource+Pack+1.2.3.mcpack"))); + + assertTrue(matcher.matches(Path.of("packs", "Resource+Pack+1.2.3.zip"))); + assertTrue(matcher.matches(Path.of("Resource+Pack+1.2.3.zip"))); + + assertFalse(matcher.matches(Path.of("resource.pack"))); + assertFalse(matcher.matches(Path.of("pack.7zip"))); + assertFalse(matcher.matches(Path.of("packs"))); + } +} From 8d068ee28fa023f9aa638aea58c9cfa38ee05a0b Mon Sep 17 00:00:00 2001 From: chris Date: Sat, 17 Jun 2023 03:46:32 +0200 Subject: [PATCH 009/344] Add SessionJoinEvent and SessionLoginEvent (#3840) --- .../api/event/bedrock/SessionJoinEvent.java | 39 +++++++ .../api/event/bedrock/SessionLoginEvent.java | 109 ++++++++++++++++++ .../geyser/session/GeyserSession.java | 18 ++- ...SetLocalPlayerAsInitializedTranslator.java | 4 + 4 files changed, 169 insertions(+), 1 deletion(-) create mode 100644 api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionJoinEvent.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionLoginEvent.java diff --git a/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionJoinEvent.java b/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionJoinEvent.java new file mode 100644 index 000000000..ab2088c00 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionJoinEvent.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2019-2023 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.api.event.bedrock; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.api.connection.GeyserConnection; +import org.geysermc.geyser.api.event.connection.ConnectionEvent; + +/** + * Called when Geyser session connected to a Java remote server and is in a play-ready state. + */ +public final class SessionJoinEvent extends ConnectionEvent { + public SessionJoinEvent(@NonNull GeyserConnection connection) { + super(connection); + } +} diff --git a/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionLoginEvent.java b/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionLoginEvent.java new file mode 100644 index 000000000..c3c8198c1 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionLoginEvent.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2019-2023 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.api.event.bedrock; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.event.Cancellable; +import org.geysermc.geyser.api.connection.GeyserConnection; +import org.geysermc.geyser.api.event.connection.ConnectionEvent; +import org.geysermc.geyser.api.network.RemoteServer; + +/** + * Called when a session has logged in, and is about to connect to a remote java server. + * This event is cancellable, and can be used to prevent the player from connecting to the remote server. + */ +public final class SessionLoginEvent extends ConnectionEvent implements Cancellable { + private RemoteServer remoteServer; + private boolean cancelled; + private String disconnectReason; + + public SessionLoginEvent(@NonNull GeyserConnection connection, @NonNull RemoteServer remoteServer) { + super(connection); + this.remoteServer = remoteServer; + } + + /** + * Returns whether the event is cancelled. + * + * @return The cancel status of the event. + */ + @Override + public boolean isCancelled() { + return this.cancelled; + } + + /** + * Cancels the login event, and disconnects the player. + * If cancelled, the player disconnects without connecting to the remote server. + * This method will use a default disconnect reason. To specify one, use {@link #setCancelled(boolean, String)}. + * + * @param cancelled If the login event should be cancelled. + */ + @Override + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } + + /** + * Cancels the login event, and disconnects the player with the specified reason. + * If cancelled, the player disconnects without connecting to the remote server. + * + * @param cancelled If the login event should be cancelled. + * @param disconnectReason The reason for the cancellation. + */ + public void setCancelled(boolean cancelled, @NonNull String disconnectReason) { + this.cancelled = cancelled; + this.disconnectReason = disconnectReason; + } + + /** + * Returns the reason for the cancellation, or null if there is no reason given. + * + * @return The reason for the cancellation. + */ + public @Nullable String disconnectReason() { + return this.disconnectReason; + } + + /** + * Gets the {@link RemoteServer} the section will attempt to connect to. + * + * @return the {@link RemoteServer} the section will attempt to connect to. + */ + public @NonNull RemoteServer remoteServer() { + return this.remoteServer; + } + + /** + * Sets the {@link RemoteServer} to connect the session to. + * + * @param remoteServer Sets the {@link RemoteServer} to connect to. + */ + public void remoteServer(@NonNull RemoteServer remoteServer) { + this.remoteServer = remoteServer; + } +} diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 641473e22..deb5b90cc 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -56,7 +56,11 @@ import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.Server import com.github.steveice10.mc.protocol.packet.login.serverbound.ServerboundCustomQueryPacket; import com.github.steveice10.packetlib.BuiltinFlags; import com.github.steveice10.packetlib.Session; -import com.github.steveice10.packetlib.event.session.*; +import com.github.steveice10.packetlib.event.session.ConnectedEvent; +import com.github.steveice10.packetlib.event.session.DisconnectedEvent; +import com.github.steveice10.packetlib.event.session.PacketErrorEvent; +import com.github.steveice10.packetlib.event.session.PacketSendingEvent; +import com.github.steveice10.packetlib.event.session.SessionAdapter; import com.github.steveice10.packetlib.packet.Packet; import com.github.steveice10.packetlib.tcp.TcpClientSession; import com.github.steveice10.packetlib.tcp.TcpSession; @@ -82,6 +86,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.common.value.qual.IntRange; import org.cloudburstmc.math.vector.*; import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.protocol.bedrock.BedrockDisconnectReasons; import org.cloudburstmc.protocol.bedrock.BedrockServerSession; import org.cloudburstmc.protocol.bedrock.data.*; import org.cloudburstmc.protocol.bedrock.data.command.CommandEnumData; @@ -104,6 +109,7 @@ import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.connection.GeyserConnection; import org.geysermc.geyser.api.entity.type.GeyserEntity; import org.geysermc.geyser.api.entity.type.player.GeyserPlayerEntity; +import org.geysermc.geyser.api.event.bedrock.SessionLoginEvent; import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.api.network.RemoteServer; import org.geysermc.geyser.command.GeyserCommandSource; @@ -879,6 +885,16 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { * After getting whatever credentials needed, we attempt to join the Java server. */ private void connectDownstream() { + SessionLoginEvent loginEvent = new SessionLoginEvent(this, remoteServer); + GeyserImpl.getInstance().eventBus().fire(loginEvent); + if (loginEvent.isCancelled()) { + String disconnectReason = loginEvent.disconnectReason() == null ? + BedrockDisconnectReasons.DISCONNECTED : loginEvent.disconnectReason(); + disconnect(disconnectReason); + return; + } + + this.remoteServer = loginEvent.remoteServer(); boolean floodgate = this.remoteServer.authType() == AuthType.FLOODGATE; // Start ticking diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockSetLocalPlayerAsInitializedTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockSetLocalPlayerAsInitializedTranslator.java index defe58a8e..de2df0cb7 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockSetLocalPlayerAsInitializedTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockSetLocalPlayerAsInitializedTranslator.java @@ -26,6 +26,8 @@ package org.geysermc.geyser.translator.protocol.bedrock; import org.cloudburstmc.protocol.bedrock.packet.SetLocalPlayerAsInitializedPacket; +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.event.bedrock.SessionJoinEvent; import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; @@ -68,6 +70,8 @@ public class BedrockSetLocalPlayerAsInitializedTranslator extends PacketTranslat // What am I to expect - as of Bedrock 1.18 session.getFormCache().resendAllForms(); + + GeyserImpl.getInstance().eventBus().fire(new SessionJoinEvent(session)); } } } From f272ed93831acf2b1b851f416486765b83991d51 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Sat, 17 Jun 2023 02:56:50 +0100 Subject: [PATCH 010/344] Move PlatformType to API and expose it for extensions (#3798) * Move PlatformType to API and expose it for extensions * Move to a record --- .../org/geysermc/geyser/api/GeyserApi.java | 9 ++++++ .../geyser/api/util}/PlatformType.java | 30 ++++++++----------- .../bungeecord/GeyserBungeePlugin.java | 2 +- .../platform/fabric/GeyserFabricMod.java | 2 +- .../platform/spigot/GeyserSpigotPlugin.java | 2 +- .../platform/sponge/GeyserSpongePlugin.java | 2 +- .../standalone/GeyserStandaloneBootstrap.java | 2 +- .../velocity/GeyserVelocityPlugin.java | 2 +- .../geysermc/connector/GeyserConnector.java | 2 +- .../java/org/geysermc/geyser/GeyserImpl.java | 12 ++++++-- .../geyser/command/GeyserCommandManager.java | 2 +- .../defaults/ConnectionTestCommand.java | 2 +- .../geyser/command/defaults/DumpCommand.java | 2 +- .../geyser/command/defaults/HelpCommand.java | 2 +- .../command/defaults/ReloadCommand.java | 2 +- .../geyser/command/defaults/StopCommand.java | 2 +- .../command/defaults/VersionCommand.java | 2 +- .../geyser/dump/BootstrapDumpInfo.java | 2 +- .../geyser/session/GeyserSession.java | 2 +- .../level/block/entity/PistonBlockEntity.java | 2 +- .../BedrockCommandRequestTranslator.java | 2 +- .../java/JavaLoginDisconnectTranslator.java | 2 +- .../java/level/JavaBlockEventTranslator.java | 2 +- .../java/level/JavaBlockUpdateTranslator.java | 2 +- 24 files changed, 52 insertions(+), 41 deletions(-) rename {common/src/main/java/org/geysermc/common => api/src/main/java/org/geysermc/geyser/api/util}/PlatformType.java (62%) diff --git a/api/src/main/java/org/geysermc/geyser/api/GeyserApi.java b/api/src/main/java/org/geysermc/geyser/api/GeyserApi.java index 84cb445ad..de5c78678 100644 --- a/api/src/main/java/org/geysermc/geyser/api/GeyserApi.java +++ b/api/src/main/java/org/geysermc/geyser/api/GeyserApi.java @@ -35,6 +35,7 @@ import org.geysermc.geyser.api.event.EventRegistrar; import org.geysermc.geyser.api.extension.ExtensionManager; import org.geysermc.geyser.api.network.BedrockListener; import org.geysermc.geyser.api.network.RemoteServer; +import org.geysermc.geyser.api.util.PlatformType; import java.nio.file.Path; import java.util.List; @@ -124,6 +125,14 @@ public interface GeyserApi extends GeyserApiBase { @NonNull Path packDirectory(); + /** + * Gets {@link PlatformType} the extension is running on + * + * @return type of platform + */ + @NonNull + PlatformType platformType(); + /** * Gets the current {@link GeyserApiBase} instance. * diff --git a/common/src/main/java/org/geysermc/common/PlatformType.java b/api/src/main/java/org/geysermc/geyser/api/util/PlatformType.java similarity index 62% rename from common/src/main/java/org/geysermc/common/PlatformType.java rename to api/src/main/java/org/geysermc/geyser/api/util/PlatformType.java index 667d49a7a..185e73168 100644 --- a/common/src/main/java/org/geysermc/common/PlatformType.java +++ b/api/src/main/java/org/geysermc/geyser/api/util/PlatformType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2023 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 @@ -23,21 +23,17 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.common; +package org.geysermc.geyser.api.util; -import lombok.AllArgsConstructor; -import lombok.Getter; - -@Getter -@AllArgsConstructor -public enum PlatformType { - ANDROID("Android"), - BUNGEECORD("BungeeCord"), - FABRIC("Fabric"), - SPIGOT("Spigot"), - SPONGE("Sponge"), - STANDALONE("Standalone"), - VELOCITY("Velocity"); - - private final String platformName; +/** + * Represents the platform Geyser is running on. + */ +public record PlatformType(String platformName) { + public static PlatformType ANDROID = new PlatformType("Android"); + public static PlatformType BUNGEECORD = new PlatformType("BungeeCord"); + public static PlatformType FABRIC = new PlatformType("Fabric"); + public static PlatformType SPIGOT = new PlatformType("Spigot"); + public static PlatformType SPONGE = new PlatformType("Sponge"); + public static PlatformType STANDALONE = new PlatformType("Standalone"); + public static PlatformType VELOCITY = new PlatformType("Velocity"); } diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java index 4141a8dbc..538e00a05 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java @@ -31,7 +31,7 @@ import net.md_5.bungee.api.config.ListenerInfo; import net.md_5.bungee.api.plugin.Plugin; import net.md_5.bungee.protocol.ProtocolConstants; import org.checkerframework.checker.nullness.qual.Nullable; -import org.geysermc.common.PlatformType; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.command.Command; diff --git a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMod.java b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMod.java index 0b9bcea68..64b050ec5 100644 --- a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMod.java +++ b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMod.java @@ -36,7 +36,7 @@ import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.server.MinecraftServer; import org.apache.logging.log4j.LogManager; -import org.geysermc.common.PlatformType; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserLogger; diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java index a660d735b..16ee13c82 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java @@ -42,7 +42,7 @@ import org.bukkit.permissions.Permission; import org.bukkit.permissions.PermissionDefault; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.java.JavaPlugin; -import org.geysermc.common.PlatformType; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.Constants; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; diff --git a/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongePlugin.java b/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongePlugin.java index dd84bf31c..a20f1617f 100644 --- a/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongePlugin.java +++ b/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongePlugin.java @@ -27,7 +27,7 @@ package org.geysermc.geyser.platform.sponge; import com.google.inject.Inject; import org.apache.logging.log4j.Logger; -import org.geysermc.common.PlatformType; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.command.Command; diff --git a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java index c4271be4c..64686f5f5 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java @@ -38,7 +38,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.core.Appender; import org.apache.logging.log4j.core.Logger; import org.apache.logging.log4j.core.appender.ConsoleAppender; -import org.geysermc.common.PlatformType; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.command.GeyserCommandManager; diff --git a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java index 92b3a71a7..aac27fb65 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java @@ -36,7 +36,7 @@ import com.velocitypowered.api.plugin.Plugin; import com.velocitypowered.api.proxy.ProxyServer; import lombok.Getter; import net.kyori.adventure.util.Codec; -import org.geysermc.common.PlatformType; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.command.Command; diff --git a/core/src/main/java/org/geysermc/connector/GeyserConnector.java b/core/src/main/java/org/geysermc/connector/GeyserConnector.java index 2616b91d3..381282a2a 100644 --- a/core/src/main/java/org/geysermc/connector/GeyserConnector.java +++ b/core/src/main/java/org/geysermc/connector/GeyserConnector.java @@ -26,7 +26,7 @@ package org.geysermc.connector; import org.geysermc.api.Geyser; -import org.geysermc.common.PlatformType; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.geyser.GeyserImpl; diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index 796e5ed06..5814348ed 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -43,7 +43,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.api.Geyser; -import org.geysermc.common.PlatformType; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.cumulus.form.Form; import org.geysermc.cumulus.form.util.FormBuilder; import org.geysermc.erosion.packet.Packets; @@ -411,7 +411,7 @@ public class GeyserImpl implements GeyserApi { metrics.addCustomChart(new Metrics.SingleLineChart("players", sessionManager::size)); // Prevent unwanted words best we can metrics.addCustomChart(new Metrics.SimplePie("authMode", () -> config.getRemote().authType().toString().toLowerCase(Locale.ROOT))); - metrics.addCustomChart(new Metrics.SimplePie("platform", platformType::getPlatformName)); + metrics.addCustomChart(new Metrics.SimplePie("platform", platformType::platformName)); metrics.addCustomChart(new Metrics.SimplePie("defaultLocale", GeyserLocale::getDefaultLocale)); metrics.addCustomChart(new Metrics.SimplePie("version", () -> GeyserImpl.VERSION)); metrics.addCustomChart(new Metrics.AdvancedPie("playerPlatform", () -> { @@ -447,7 +447,7 @@ public class GeyserImpl implements GeyserApi { if (minecraftVersion != null) { Map> versionMap = new HashMap<>(); Map platformMap = new HashMap<>(); - platformMap.put(platformType.getPlatformName(), 1); + platformMap.put(platformType.platformName(), 1); versionMap.put(minecraftVersion, platformMap); metrics.addCustomChart(new Metrics.DrilldownPie("minecraftServerVersion", () -> { @@ -694,6 +694,12 @@ public class GeyserImpl implements GeyserApi { return bootstrap.getConfigFolder().resolve("packs"); } + @Override + @NonNull + public PlatformType platformType() { + return platformType; + } + public int buildNumber() { if (!this.isProductionEnvironment()) { return 0; diff --git a/core/src/main/java/org/geysermc/geyser/command/GeyserCommandManager.java b/core/src/main/java/org/geysermc/geyser/command/GeyserCommandManager.java index d28f9d24e..483e8d4a7 100644 --- a/core/src/main/java/org/geysermc/geyser/command/GeyserCommandManager.java +++ b/core/src/main/java/org/geysermc/geyser/command/GeyserCommandManager.java @@ -29,7 +29,7 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import lombok.Getter; import lombok.RequiredArgsConstructor; import org.checkerframework.checker.nullness.qual.NonNull; -import org.geysermc.common.PlatformType; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.command.Command; import org.geysermc.geyser.api.command.CommandExecutor; diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/ConnectionTestCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/ConnectionTestCommand.java index 95c115769..8471fcd3f 100644 --- a/core/src/main/java/org/geysermc/geyser/command/defaults/ConnectionTestCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/ConnectionTestCommand.java @@ -26,7 +26,7 @@ package org.geysermc.geyser.command.defaults; import com.fasterxml.jackson.databind.JsonNode; -import org.geysermc.common.PlatformType; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.command.GeyserCommand; import org.geysermc.geyser.command.GeyserCommandSource; diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/DumpCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/DumpCommand.java index 60683d34a..544be7446 100644 --- a/core/src/main/java/org/geysermc/geyser/command/defaults/DumpCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/DumpCommand.java @@ -30,7 +30,7 @@ import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.checkerframework.checker.nullness.qual.NonNull; -import org.geysermc.common.PlatformType; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.command.GeyserCommand; import org.geysermc.geyser.command.GeyserCommandSource; diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/HelpCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/HelpCommand.java index 6e7ad2f04..d4ec7d161 100644 --- a/core/src/main/java/org/geysermc/geyser/command/defaults/HelpCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/HelpCommand.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.command.defaults; -import org.geysermc.common.PlatformType; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.command.Command; import org.geysermc.geyser.command.GeyserCommand; diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/ReloadCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/ReloadCommand.java index 843e93de0..8f147cdab 100644 --- a/core/src/main/java/org/geysermc/geyser/command/defaults/ReloadCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/ReloadCommand.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.command.defaults; -import org.geysermc.common.PlatformType; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.command.GeyserCommand; import org.geysermc.geyser.command.GeyserCommandSource; diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/StopCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/StopCommand.java index 151aa2d84..7db539cc5 100644 --- a/core/src/main/java/org/geysermc/geyser/command/defaults/StopCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/StopCommand.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.command.defaults; -import org.geysermc.common.PlatformType; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.command.GeyserCommand; import org.geysermc.geyser.command.GeyserCommandSource; diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/VersionCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/VersionCommand.java index b2b5d54a3..378e43ee0 100644 --- a/core/src/main/java/org/geysermc/geyser/command/defaults/VersionCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/VersionCommand.java @@ -26,7 +26,7 @@ package org.geysermc.geyser.command.defaults; import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; -import org.geysermc.common.PlatformType; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.command.GeyserCommand; import org.geysermc.geyser.command.GeyserCommandSource; diff --git a/core/src/main/java/org/geysermc/geyser/dump/BootstrapDumpInfo.java b/core/src/main/java/org/geysermc/geyser/dump/BootstrapDumpInfo.java index fda0566fd..6a56c536a 100644 --- a/core/src/main/java/org/geysermc/geyser/dump/BootstrapDumpInfo.java +++ b/core/src/main/java/org/geysermc/geyser/dump/BootstrapDumpInfo.java @@ -27,7 +27,7 @@ package org.geysermc.geyser.dump; import lombok.AllArgsConstructor; import lombok.Getter; -import org.geysermc.common.PlatformType; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.text.AsteriskSerializer; diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index deb5b90cc..0bbbf5d45 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -99,7 +99,7 @@ import org.cloudburstmc.protocol.common.util.OptionalBoolean; import org.geysermc.api.util.BedrockPlatform; import org.geysermc.api.util.InputMode; import org.geysermc.api.util.UiProfile; -import org.geysermc.common.PlatformType; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.cumulus.form.Form; import org.geysermc.cumulus.form.util.FormBuilder; import org.geysermc.floodgate.crypto.FloodgateCipher; 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 691ca3c88..cab42f3d0 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 @@ -36,7 +36,7 @@ import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import lombok.Getter; -import org.geysermc.common.PlatformType; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.physics.Axis; import org.geysermc.geyser.level.physics.BoundingBox; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockCommandRequestTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockCommandRequestTranslator.java index b981516eb..322d64cce 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockCommandRequestTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockCommandRequestTranslator.java @@ -26,7 +26,7 @@ package org.geysermc.geyser.translator.protocol.bedrock; import org.cloudburstmc.protocol.bedrock.packet.CommandRequestPacket; -import org.geysermc.common.PlatformType; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginDisconnectTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginDisconnectTranslator.java index 0720963fb..56309c058 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginDisconnectTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginDisconnectTranslator.java @@ -29,7 +29,7 @@ import com.github.steveice10.mc.protocol.packet.login.clientbound.ClientboundLog import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.TranslatableComponent; -import org.geysermc.common.PlatformType; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.GeyserLocale; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEventTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEventTranslator.java index e4b278c48..7e774175a 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEventTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEventTranslator.java @@ -33,7 +33,7 @@ import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket; import org.cloudburstmc.protocol.bedrock.packet.BlockEventPacket; import it.unimi.dsi.fastutil.objects.Object2IntMaps; -import org.geysermc.common.PlatformType; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.physics.Direction; import org.geysermc.geyser.session.GeyserSession; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockUpdateTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockUpdateTranslator.java index 6a8a2a5ba..b66edd3e0 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockUpdateTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockUpdateTranslator.java @@ -29,7 +29,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.Clientb import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEventPacket; -import org.geysermc.common.PlatformType; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.type.BlockMapping; import org.geysermc.geyser.session.GeyserSession; From bed7b5d10e03b346eed2d7272627afe48ae6348c Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Sat, 17 Jun 2023 11:47:42 -0400 Subject: [PATCH 011/344] Bump logj4 (#3888) --- bootstrap/standalone/build.gradle.kts | 6 ++---- .../geyser/platform/standalone/GeyserStandaloneLogger.java | 1 + bootstrap/standalone/src/main/resources/log4j2.xml | 4 ++-- gradle/libs.versions.toml | 6 +++--- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/bootstrap/standalone/build.gradle.kts b/bootstrap/standalone/build.gradle.kts index b5fae9db3..eaf895108 100644 --- a/bootstrap/standalone/build.gradle.kts +++ b/bootstrap/standalone/build.gradle.kts @@ -7,10 +7,8 @@ dependencies { api(projects.core) implementation(libs.terminalconsoleappender) { - exclude("org.apache.logging.log4j", "log4j-core") - exclude("org.jline", "jline-reader") - exclude("org.jline", "jline-terminal") - exclude("org.jline", "jline-terminal-jna") + exclude("org.apache.logging.log4j") + exclude("org.jline") } implementation(libs.bundles.jline) diff --git a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneLogger.java b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneLogger.java index e7e24a465..3c29bc648 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneLogger.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneLogger.java @@ -92,6 +92,7 @@ public class GeyserStandaloneLogger extends SimpleTerminalConsole implements Gey Configurator.setLevel(log.getName(), debug ? Level.DEBUG : Level.INFO); } + @Override public boolean isDebug() { return log.isDebugEnabled(); } diff --git a/bootstrap/standalone/src/main/resources/log4j2.xml b/bootstrap/standalone/src/main/resources/log4j2.xml index 0738acdcd..54f6f9528 100644 --- a/bootstrap/standalone/src/main/resources/log4j2.xml +++ b/bootstrap/standalone/src/main/resources/log4j2.xml @@ -2,10 +2,10 @@ - + - + diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d179c7576..31c732712 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -18,7 +18,7 @@ adventure = "4.14.0-20230424.215040-7" adventure-platform = "4.1.2" junit = "5.9.2" checkerframework = "3.19.0" -log4j = "2.17.1" +log4j = "2.20.0" jline = "3.21.0" terminalconsoleappender = "1.2.0" folia = "1.19.4-R0.1-SNAPSHOT" @@ -65,7 +65,7 @@ netty-transport-native-kqueue = { group = "io.netty", name = "netty-transport-na log4j-api = { group = "org.apache.logging.log4j", name = "log4j-api", version.ref = "log4j" } log4j-core = { group = "org.apache.logging.log4j", name = "log4j-core", version.ref = "log4j" } -log4j-slf4j18-impl = { group = "org.apache.logging.log4j", name = "log4j-slf4j18-impl", version.ref = "log4j" } +log4j-slf4j2-impl = { group = "org.apache.logging.log4j", name = "log4j-slf4j2-impl", version.ref = "log4j" } jline-terminal = { group = "org.jline", name = "jline-terminal", version.ref = "jline" } jline-terminal-jna = { group = "org.jline", name = "jline-terminal-jna", version.ref = "jline" } @@ -103,6 +103,6 @@ protocol-connection = { group = "org.cloudburstmc.protocol", name = "bedrock-con jackson = [ "jackson-annotations", "jackson-core", "jackson-dataformat-yaml" ] fastutil = [ "fastutil-int-int-maps", "fastutil-int-long-maps", "fastutil-int-byte-maps", "fastutil-int-boolean-maps", "fastutil-object-int-maps", "fastutil-object-object-maps" ] adventure = [ "adventure-text-serializer-gson", "adventure-text-serializer-legacy", "adventure-text-serializer-plain" ] -log4j = [ "log4j-api", "log4j-core", "log4j-slf4j18-impl" ] +log4j = [ "log4j-api", "log4j-core", "log4j-slf4j2-impl" ] jline = [ "jline-terminal", "jline-terminal-jna", "jline-reader" ] protocol = [ "protocol-common", "protocol-codec", "protocol-connection" ] From 2368b63ad5f6f1d3f0a15d203aac1ea0fcc9b39d Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Sun, 18 Jun 2023 17:45:25 -0400 Subject: [PATCH 012/344] Allow deferred registries to be loaded/set more than once (#3892) --- .../geyser/registry/DeferredRegistry.java | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/registry/DeferredRegistry.java b/core/src/main/java/org/geysermc/geyser/registry/DeferredRegistry.java index bf3050a61..6a2f2ae37 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/DeferredRegistry.java +++ b/core/src/main/java/org/geysermc/geyser/registry/DeferredRegistry.java @@ -69,6 +69,12 @@ public final class DeferredRegistry implements IRegistry { this.loader = () -> deferredLoader.get().load(input); } + /** + * Gets the underlying value held by this registry. + * + * @return the underlying value held by this registry + * @throws IllegalStateException if this deferred registry has not been loaded yet + */ @Override public M get() { if (!this.loaded) { @@ -80,13 +86,15 @@ public final class DeferredRegistry implements IRegistry { @Override public void set(M mappings) { - if (!this.loaded) { - throw new IllegalStateException("Registry has not been loaded yet!"); - } - this.backingRegistry.set(mappings); } + /** + * Registers what is specified in the given {@link Consumer} into the underlying value. + * + * @param consumer the consumer + * @throws IllegalStateException if this deferred registry has not been loaded yet + */ @Override public void register(Consumer consumer) { if (!this.loaded) { @@ -100,10 +108,6 @@ public final class DeferredRegistry implements IRegistry { * Loads the registry. */ public void load() { - if (this.loaded) { - throw new IllegalStateException("Registry has already been loaded!"); - } - this.backingRegistry.set(this.loader.get()); this.loaded = true; } From e5aa320d220eefc733c6053bc0414d2be63066bf Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Sun, 18 Jun 2023 17:45:59 -0400 Subject: [PATCH 013/344] Fix condition for using author's api branch (#3893) --- .github/workflows/pullrequest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 23e1576ae..5f4127b2b 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -31,7 +31,7 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} - name: Use author's API repo if it exists - if: steps.find_forks.outputs.target_branch_found == 'true' + if: ${{ steps.find_forks.outputs.target_branch_found == 'true' }} env: API_FORK_URL: ${{ steps.find_forks.outputs.user_fork_url }} API_FORK_BRANCH: ${{ github.event.pull_request.head.ref }} From 811aba3339d9be8ecb04f888c6e9e8036930ba9d Mon Sep 17 00:00:00 2001 From: Amberichu <4722249+davchoo@users.noreply.github.com> Date: Sun, 18 Jun 2023 20:02:27 -0400 Subject: [PATCH 014/344] Validate written_book tags and fix writable book losing changes (#3894) * Validate NBT tags of written_book like Java edition * Update page count and character count limits The maximum number of characters allowed in Java's book edit screen is 1024 for each page and 16 for the title. However, the packet itself has a limit of 8192 * 3 bytes for each page and 128 * 3 bytes for the title. * Fix writable book losing changes when signing Bedrock sends a 3 action InventoryTransactionPacket after the player changes a page. This causes Geyser to send a ServerboundEditBookPacket with an outdated NBT. The Java responses with a ClientboundContainerSetSlotPacket that overwrites any NBT Changes from BedrockBookEditTranslator. * Add a comment for the title length check * Specify color in Component.translatable --- .../inventory/item/StoredItemMappings.java | 2 + .../java/org/geysermc/geyser/item/Items.java | 4 +- ...bleBookItem.java => WritableBookItem.java} | 7 +- .../geyser/item/type/WrittenBookItem.java | 98 +++++++++++++++++++ .../geyser/session/cache/BookEditCache.java | 2 +- .../bedrock/BedrockBookEditTranslator.java | 12 ++- ...BedrockInventoryTransactionTranslator.java | 10 ++ 7 files changed, 122 insertions(+), 13 deletions(-) rename core/src/main/java/org/geysermc/geyser/item/type/{ReadableBookItem.java => WritableBookItem.java} (93%) create mode 100644 core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java b/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java index c4137fba9..42b9ae1a0 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java @@ -51,6 +51,7 @@ public class StoredItemMappings { private final ItemMapping egg; private final ItemMapping shield; private final ItemMapping wheat; + private final ItemMapping writableBook; public StoredItemMappings(Map itemMappings) { this.bamboo = load(itemMappings, Items.BAMBOO); @@ -64,6 +65,7 @@ public class StoredItemMappings { this.egg = load(itemMappings, Items.EGG); this.shield = load(itemMappings, Items.SHIELD); this.wheat = load(itemMappings, Items.WHEAT); + this.writableBook = load(itemMappings, Items.WRITABLE_BOOK); } @Nonnull diff --git a/core/src/main/java/org/geysermc/geyser/item/Items.java b/core/src/main/java/org/geysermc/geyser/item/Items.java index 1339f166a..303665c79 100644 --- a/core/src/main/java/org/geysermc/geyser/item/Items.java +++ b/core/src/main/java/org/geysermc/geyser/item/Items.java @@ -1084,8 +1084,8 @@ public final class Items { public static final Item ZOMBIFIED_PIGLIN_SPAWN_EGG = register(new SpawnEggItem("zombified_piglin_spawn_egg", builder())); public static final Item EXPERIENCE_BOTTLE = register(new Item("experience_bottle", builder())); public static final Item FIRE_CHARGE = register(new Item("fire_charge", builder())); - public static final Item WRITABLE_BOOK = register(new ReadableBookItem("writable_book", builder().stackSize(1))); - public static final Item WRITTEN_BOOK = register(new ReadableBookItem("written_book", builder().stackSize(16))); + public static final Item WRITABLE_BOOK = register(new WritableBookItem("writable_book", builder().stackSize(1))); + public static final Item WRITTEN_BOOK = register(new WrittenBookItem("written_book", builder().stackSize(16))); public static final Item ITEM_FRAME = register(new Item("item_frame", builder())); public static final Item GLOW_ITEM_FRAME = register(new Item("glow_item_frame", builder())); public static final Item FLOWER_POT = register(new BlockItem("flower_pot", builder())); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ReadableBookItem.java b/core/src/main/java/org/geysermc/geyser/item/type/WritableBookItem.java similarity index 93% rename from core/src/main/java/org/geysermc/geyser/item/type/ReadableBookItem.java rename to core/src/main/java/org/geysermc/geyser/item/type/WritableBookItem.java index 814a6264e..dfebecf7d 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ReadableBookItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/WritableBookItem.java @@ -37,11 +37,8 @@ import org.geysermc.geyser.translator.text.MessageTranslator; import java.util.ArrayList; import java.util.List; -/** - * Encapsulates written books and writable books. Customly named class to share common code. - */ -public class ReadableBookItem extends Item { - public ReadableBookItem(String javaIdentifier, Builder builder) { +public class WritableBookItem extends Item { + public WritableBookItem(String javaIdentifier, Builder builder) { super(javaIdentifier, builder); } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java b/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java new file mode 100644 index 000000000..045aaa416 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2019-2023 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.item.type; + +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.ListTag; +import com.github.steveice10.opennbt.tag.builtin.StringTag; +import com.github.steveice10.opennbt.tag.builtin.Tag; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.text.MessageTranslator; + +import java.util.List; + +public class WrittenBookItem extends WritableBookItem { + public static final int MAXIMUM_PAGE_EDIT_LENGTH = 1024; + public static final int MAXIMUM_PAGE_LENGTH = 32768; + public static final int MAXIMUM_PAGE_COUNT = 100; // Java edition limit. Bedrock edition has a limit of 50 pages. + public static final int MAXIMUM_TITLE_LENGTH = 16; + + public WrittenBookItem(String javaIdentifier, Builder builder) { + super(javaIdentifier, builder); + } + + @Override + public void translateNbtToBedrock(@NonNull GeyserSession session, @NonNull CompoundTag tag) { + boolean isValid = isValidWrittenBook(tag); + if (!isValid) { + tag.remove("pages"); + } + + super.translateNbtToBedrock(session, tag); + + if (!isValid) { + CompoundTag invalidTagPage = new CompoundTag(""); + invalidTagPage.put(new StringTag("photoname", "")); + invalidTagPage.put(new StringTag( + "text", + MessageTranslator.convertMessage( + Component.translatable("book.invalid.tag", NamedTextColor.DARK_RED), + session.locale() + ) + )); + tag.put(new ListTag("pages", List.of(invalidTagPage))); + } + } + + private boolean isValidWrittenBook(CompoundTag tag) { + if (!(tag.get("title") instanceof StringTag title)) { + return false; + } + if (title.getValue().length() > (MAXIMUM_TITLE_LENGTH * 2)) { + // Java rejects books with titles more than 2x the maximum length allowed in the input box + return false; + } + + if (!(tag.get("author") instanceof StringTag)) { + return false; + } + + if (!(tag.get("pages") instanceof ListTag pages)) { + return false; + } + for (Tag pageTag : pages) { + if (pageTag instanceof StringTag page) { + if (page.getValue().length() > MAXIMUM_PAGE_LENGTH) { + return false; + } + } + } + return true; + } +} diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/BookEditCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/BookEditCache.java index 5cd112a5f..35bea7295 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/BookEditCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/BookEditCache.java @@ -62,7 +62,7 @@ public class BookEditCache { if ((System.currentTimeMillis() - lastBookUpdate) < 1000) { return; } - // Don't send the update if the player isn't not holding a book, shouldn't happen if we catch all interactions + // Don't send the update if the player is not holding a book, shouldn't happen if we catch all interactions GeyserItemStack itemStack = session.getPlayerInventory().getItemInHand(); if (itemStack == null || itemStack.asItem() != Items.WRITABLE_BOOK) { packet = null; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBookEditTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBookEditTranslator.java index 1d5c5828c..6547044c3 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBookEditTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBookEditTranslator.java @@ -33,12 +33,12 @@ import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import org.cloudburstmc.protocol.bedrock.packet.BookEditPacket; import org.geysermc.geyser.inventory.GeyserItemStack; +import org.geysermc.geyser.item.type.WrittenBookItem; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.translator.text.MessageTranslator; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; @@ -46,12 +46,10 @@ import java.util.List; @Translator(packet = BookEditPacket.class) public class BedrockBookEditTranslator extends PacketTranslator { - private static final int MAXIMUM_PAGE_LENGTH = 8192 * 4; - private static final int MAXIMUM_TITLE_LENGTH = 128 * 4; @Override public void translate(GeyserSession session, BookEditPacket packet) { - if (packet.getText() != null && !packet.getText().isEmpty() && packet.getText().getBytes(StandardCharsets.UTF_8).length > MAXIMUM_PAGE_LENGTH) { + if (packet.getText() != null && !packet.getText().isEmpty() && packet.getText().length() > WrittenBookItem.MAXIMUM_PAGE_EDIT_LENGTH) { session.getGeyser().getLogger().warning("Page length greater than server allowed!"); return; } @@ -63,6 +61,10 @@ public class BedrockBookEditTranslator extends PacketTranslator List pages = tag.contains("pages") ? new LinkedList<>(((ListTag) tag.get("pages")).getValue()) : new LinkedList<>(); int page = packet.getPageNumber(); + if (page < 0 || WrittenBookItem.MAXIMUM_PAGE_COUNT <= page) { + session.getGeyser().getLogger().warning("Edited page is out of acceptable bounds!"); + return; + } switch (packet.getAction()) { case ADD_PAGE: { // Add empty pages in between @@ -129,7 +131,7 @@ public class BedrockBookEditTranslator extends PacketTranslator if (packet.getAction() == BookEditPacket.Action.SIGN_BOOK) { // Add title to packet so the server knows we're signing title = MessageTranslator.convertToPlainText(packet.getTitle()); - if (title.getBytes(StandardCharsets.UTF_8).length > MAXIMUM_TITLE_LENGTH) { + if (title.length() > WrittenBookItem.MAXIMUM_TITLE_LENGTH) { session.getGeyser().getLogger().warning("Book title larger than server allows!"); return; } 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 5bfb2dd6a..bf2c8b1cc 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 @@ -44,6 +44,7 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.transaction.InventoryActionData; import org.cloudburstmc.protocol.bedrock.data.inventory.transaction.InventorySource; +import org.cloudburstmc.protocol.bedrock.data.inventory.transaction.InventoryTransactionType; import org.cloudburstmc.protocol.bedrock.data.inventory.transaction.LegacySetItemSlotData; import org.cloudburstmc.protocol.bedrock.packet.ContainerOpenPacket; import org.cloudburstmc.protocol.bedrock.packet.InventoryTransactionPacket; @@ -93,6 +94,15 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator Date: Tue, 20 Jun 2023 15:28:31 +0200 Subject: [PATCH 015/344] Fix/proxy protocol missing message (#3898) * Show proxy protocol ip for debug message * Make sure that first message that contains proxy protocol also gets sent. This caused issues with serverlists and console players --- .../geysermc/geyser/network/netty/GeyserServer.java | 11 ++++++++++- .../network/netty/proxy/ProxyServerHandler.java | 4 ++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java b/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java index 31a355011..22f46ee22 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java @@ -187,7 +187,16 @@ public final class GeyserServer { public BedrockPong onQuery(InetSocketAddress inetSocketAddress) { if (geyser.getConfig().isDebugMode() && PRINT_DEBUG_PINGS) { - String ip = geyser.getConfig().isLogPlayerIpAddresses() ? inetSocketAddress.toString() : ""; + String ip; + if (geyser.getConfig().isLogPlayerIpAddresses()) { + if (geyser.getConfig().getBedrock().isEnableProxyProtocol()) { + ip = this.proxiedAddresses.getOrDefault(inetSocketAddress, inetSocketAddress).toString(); + } else { + ip = inetSocketAddress.toString(); + } + } else { + ip = ""; + } geyser.getLogger().debug(GeyserLocale.getLocaleStringLog("geyser.network.pinged", ip)); } diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/proxy/ProxyServerHandler.java b/core/src/main/java/org/geysermc/geyser/network/netty/proxy/ProxyServerHandler.java index 68d3a298c..0d61ed0d4 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/proxy/ProxyServerHandler.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/proxy/ProxyServerHandler.java @@ -73,10 +73,10 @@ public class ProxyServerHandler extends SimpleChannelInboundHandler Date: Tue, 20 Jun 2023 09:28:51 -0400 Subject: [PATCH 016/344] Update piglin head variants (#3901) --- core/src/main/resources/mappings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/resources/mappings b/core/src/main/resources/mappings index dbc7aea1b..bff5fad32 160000 --- a/core/src/main/resources/mappings +++ b/core/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit dbc7aea1ba4d7926191cfabff0a5268461947bf0 +Subproject commit bff5fad3284864fdfad4e7f66aea45cdb20cf401 From 70db98eeaf977226f1840b587095c95ddfc5221d Mon Sep 17 00:00:00 2001 From: Amberichu <4722249+davchoo@users.noreply.github.com> Date: Thu, 22 Jun 2023 17:38:05 -0400 Subject: [PATCH 017/344] Fix updating villager trade experience (#3906) * Fix villager experience not updating Remove unnecessary fake trade experience stuff * Hide trade level for wandering traders --- .../entity/type/player/SessionPlayerEntity.java | 9 --------- .../geysermc/geyser/inventory/MerchantContainer.java | 10 +++++++--- .../java/inventory/JavaMerchantOffersTranslator.java | 12 ++++++++++-- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java index 279429242..540aa989f 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java @@ -67,10 +67,6 @@ public class SessionPlayerEntity extends PlayerEntity { */ @Getter private boolean isRidingInFront; - /** - * Used for villager inventory emulation. - */ - private int fakeTradeXp; public SessionPlayerEntity(GeyserSession session) { super(session, -1, 1, null, Vector3f.ZERO, Vector3f.ZERO, 0, 0, 0, null, null); @@ -175,11 +171,6 @@ public class SessionPlayerEntity extends PlayerEntity { this.isRidingInFront = position != null && position.getX() > 0; } - public void addFakeTradeExperience(int tradeXp) { - fakeTradeXp += tradeXp; - dirtyMetadata.put(EntityDataTypes.TRADE_EXPERIENCE, fakeTradeXp); - } - @Override public AttributeData createHealthAttribute() { // Max health must be divisible by two in bedrock diff --git a/core/src/main/java/org/geysermc/geyser/inventory/MerchantContainer.java b/core/src/main/java/org/geysermc/geyser/inventory/MerchantContainer.java index 93c1917d2..105b5ca5b 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/MerchantContainer.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/MerchantContainer.java @@ -30,6 +30,7 @@ import com.github.steveice10.mc.protocol.data.game.inventory.VillagerTrade; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.inventory.ClientboundMerchantOffersPacket; import lombok.Getter; import lombok.Setter; +import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.session.GeyserSession; @@ -40,6 +41,8 @@ public class MerchantContainer extends Container { private VillagerTrade[] villagerTrades; @Getter @Setter private ClientboundMerchantOffersPacket pendingOffersPacket; + @Getter @Setter + private int tradeExperience; public MerchantContainer(String title, int id, int size, ContainerType containerType, PlayerInventory playerInventory) { super(title, id, size, containerType, playerInventory); @@ -49,9 +52,10 @@ public class MerchantContainer extends Container { if (villagerTrades != null && slot >= 0 && slot < villagerTrades.length) { VillagerTrade trade = villagerTrades[slot]; setItem(2, GeyserItemStack.from(trade.getOutput()), session); - // TODO this logic doesn't add up - session.getPlayerEntity().addFakeTradeExperience(trade.getXp()); - session.getPlayerEntity().updateBedrockMetadata(); + + tradeExperience += trade.getXp(); + villager.getDirtyMetadata().put(EntityDataTypes.TRADE_EXPERIENCE, tradeExperience); + villager.updateBedrockMetadata(); } } } 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 d4cb46a1c..2758902d4 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 @@ -73,9 +73,17 @@ public class JavaMerchantOffersTranslator extends PacketTranslator Date: Thu, 22 Jun 2023 18:05:07 -0400 Subject: [PATCH 018/344] Fix serverbound hanging sign updates (#3904) --- .../geyser/level/block/BlockStateValues.java | 18 ------------------ .../BedrockBlockEntityDataTranslator.java | 4 ++-- .../org/geysermc/geyser/util/SignUtils.java | 4 ++-- 3 files changed, 4 insertions(+), 22 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 1a4e96bca..6b09881bb 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 @@ -45,7 +45,6 @@ import java.util.Locale; */ public final class BlockStateValues { private static final IntSet ALL_CAULDRONS = new IntOpenHashSet(); - private static final IntSet HANGING_SIGNS = new IntOpenHashSet(); private static final Int2IntMap BANNER_COLORS = new FixedInt2IntMap(); private static final Int2ByteMap BED_COLORS = new FixedInt2ByteMap(); private static final Int2IntMap BRUSH_PROGRESS = new Int2IntOpenHashMap(); @@ -88,12 +87,6 @@ public final class BlockStateValues { * @param blockData JsonNode of info about the block from blocks.json */ public static void storeBlockStateValues(String javaId, int javaBlockState, JsonNode blockData) { - if (javaId.contains("_hanging_sign")) { - // covers hanging_sign and wall_hanging_sign - HANGING_SIGNS.add(javaBlockState); - return; - } - JsonNode bannerColor = blockData.get("banner_color"); if (bannerColor != null) { BANNER_COLORS.put(javaBlockState, (byte) bannerColor.intValue()); @@ -220,17 +213,6 @@ public final class BlockStateValues { } } - /** - * Hanging signs have a different maximum text width than "normal" signs. As a result, when the client - * updates the text of a sign without indication of the sign type, we must determine it. - * - * @param state BlockState of the block - * @return true if the sign is any hanging variant - */ - public static boolean isHangingSign(int state) { - return HANGING_SIGNS.contains(state); - } - /** * Banner colors are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock. * This gives an integer color that Bedrock can use. diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockEntityDataTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockEntityDataTranslator.java index 7e972c3da..f280f144f 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockEntityDataTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockEntityDataTranslator.java @@ -43,9 +43,9 @@ public class BedrockBlockEntityDataTranslator extends PacketTranslator Date: Mon, 26 Jun 2023 12:04:28 -0400 Subject: [PATCH 019/344] Implement interaction entity (#3916) --- .../geyser/entity/EntityDefinitions.java | 10 +++ .../geyser/entity/type/InteractionEntity.java | 89 +++++++++++++++++++ .../registry/PacketTranslatorRegistry.java | 2 + 3 files changed, 101 insertions(+) create mode 100644 core/src/main/java/org/geysermc/geyser/entity/type/InteractionEntity.java diff --git a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java index de58cc26c..a8d35b6f3 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java +++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java @@ -104,6 +104,7 @@ public final class EntityDefinitions { public static final EntityDefinition HORSE; public static final EntityDefinition HUSK; public static final EntityDefinition ILLUSIONER; // Not present on Bedrock + public static final EntityDefinition INTERACTION; public static final EntityDefinition IRON_GOLEM; public static final EntityDefinition ITEM; public static final EntityDefinition ITEM_FRAME; @@ -319,6 +320,15 @@ public final class EntityDefinitions { .addTranslator(MetadataType.CHAT, TextDisplayEntity::setText) .build(); + INTERACTION = EntityDefinition.inherited(InteractionEntity::new, entityBase) + .type(EntityType.INTERACTION) + .heightAndWidth(1.0f) // default size until server specifies otherwise + .identifier("minecraft:armor_stand") + .addTranslator(MetadataType.FLOAT, InteractionEntity::setWidth) + .addTranslator(MetadataType.FLOAT, InteractionEntity::setHeight) + .addTranslator(MetadataType.BOOLEAN, InteractionEntity::setResponse) + .build(); + EntityDefinition fireballBase = EntityDefinition.inherited(FireballEntity::new, entityBase) .addTranslator(null) // Item .build(); diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/InteractionEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/InteractionEntity.java new file mode 100644 index 000000000..c88f90f19 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/entity/type/InteractionEntity.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2019-2023 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.entity.type; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.FloatEntityMetadata; +import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; +import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundSwingPacket; +import org.cloudburstmc.math.vector.Vector3f; +import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; +import org.cloudburstmc.protocol.bedrock.packet.AnimatePacket; +import org.geysermc.geyser.entity.EntityDefinition; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.util.InteractionResult; + +import java.util.UUID; + +public class InteractionEntity extends Entity { + + /** + * true - java client hears swing sound when attacking, and arm swings when right-clicking + * false - java client hears no swing sound when attacking, and arm does not swing when right-clicking + */ + private boolean response = false; + + public InteractionEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { + super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); + } + + @Override + protected void initializeMetadata() { + super.initializeMetadata(); + + // hide the armor stand but keep the hitbox active + setFlag(EntityFlag.INVISIBLE, true); + } + + @Override + public InteractionResult interact(Hand hand) { + // these InteractionResults do mirror the java client + // but the bedrock client won't arm swing itself because of our armor stand workaround + if (response) { + AnimatePacket animatePacket = new AnimatePacket(); + animatePacket.setRuntimeEntityId(session.getPlayerEntity().getGeyserId()); + animatePacket.setAction(AnimatePacket.Action.SWING_ARM); + session.sendUpstreamPacket(animatePacket); + + session.sendDownstreamPacket(new ServerboundSwingPacket(hand)); + return InteractionResult.SUCCESS; + } + + return InteractionResult.CONSUME; + } + + public void setWidth(FloatEntityMetadata width) { + setBoundingBoxWidth(width.getPrimitiveValue()); + } + + public void setHeight(FloatEntityMetadata height) { + setBoundingBoxHeight(height.getPrimitiveValue()); + } + + public void setResponse(BooleanEntityMetadata response) { + this.response = response.getPrimitiveValue(); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java b/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java index 0acfeee93..61999d4f6 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java +++ b/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.registry; +import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundDelimiterPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundTabListPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundLightUpdatePacket; import io.netty.channel.EventLoop; @@ -44,6 +45,7 @@ public class PacketTranslatorRegistry extends AbstractMappedRegistry Date: Mon, 26 Jun 2023 14:44:25 -0400 Subject: [PATCH 020/344] Move to a text box for commands on Geyser standalone GUI (#3915) --- .../standalone/GeyserStandaloneBootstrap.java | 8 +- .../platform/standalone/gui/ColorPane.java | 4 +- .../standalone/gui/GeyserStandaloneGUI.java | 259 +++++++++--------- .../java/org/geysermc/geyser/GeyserImpl.java | 20 +- core/src/main/resources/languages | 2 +- 5 files changed, 138 insertions(+), 155 deletions(-) diff --git a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java index 64686f5f5..b505b361e 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java @@ -181,14 +181,14 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap { } } + this.geyserLogger = new GeyserStandaloneLogger(); + if (useGui && gui == null) { - gui = new GeyserStandaloneGUI(); + gui = new GeyserStandaloneGUI(geyserLogger); gui.redirectSystemStreams(); gui.startUpdateThread(); } - geyserLogger = new GeyserStandaloneLogger(); - LoopbackUtil.checkAndApplyLoopback(geyserLogger); try { @@ -224,7 +224,7 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap { geyserCommandManager.init(); if (gui != null) { - gui.setupInterface(geyserLogger, geyserCommandManager); + gui.enableCommands(geyser.getScheduledThread(), geyserCommandManager); } geyserPingPassthrough = GeyserLegacyPingPassthrough.init(geyser); diff --git a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/gui/ColorPane.java b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/gui/ColorPane.java index c08f602d4..1bdc90123 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/gui/ColorPane.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/gui/ColorPane.java @@ -86,7 +86,7 @@ public class ColorPane extends JTextPane { while (stillSearching) { mIndex = addString.indexOf("m", aPos); // find the end of the escape sequence if (mIndex < 0) { // the buffer ends halfway through the ansi string! - remaining = addString.substring(aPos, addString.length()); + remaining = addString.substring(aPos); stillSearching = false; continue; } else { @@ -99,7 +99,7 @@ public class ColorPane extends JTextPane { aIndex = addString.indexOf("\u001B", aPos); if (aIndex == -1) { // if that was the last sequence of the input, send remaining text - tmpString = addString.substring(aPos, addString.length()); + tmpString = addString.substring(aPos); append(colorCurrent, tmpString); stillSearching = false; continue; // jump out of loop early, as the whole string has been sent now diff --git a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/gui/GeyserStandaloneGUI.java b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/gui/GeyserStandaloneGUI.java index 41cbafb25..af3e1069f 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/gui/GeyserStandaloneGUI.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/gui/GeyserStandaloneGUI.java @@ -26,10 +26,8 @@ package org.geysermc.geyser.platform.standalone.gui; import org.geysermc.geyser.GeyserImpl; -import org.geysermc.geyser.api.command.Command; -import org.geysermc.geyser.command.GeyserCommand; +import org.geysermc.geyser.GeyserLogger; import org.geysermc.geyser.command.GeyserCommandManager; -import org.geysermc.geyser.platform.standalone.GeyserStandaloneLogger; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.GeyserLocale; @@ -45,28 +43,37 @@ import java.io.PrintStream; import java.net.URL; import java.util.ArrayList; import java.util.List; -import java.util.Map; import java.util.Vector; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; public class GeyserStandaloneGUI { - private static final DefaultTableModel playerTableModel = new DefaultTableModel(); - private static final List ramValues = new ArrayList<>(); - - private static final ColorPane consolePane = new ColorPane(); - private static final GraphPanel ramGraph = new GraphPanel(); - private static final JTable playerTable = new JTable(playerTableModel); - private static final int originalFontSize = consolePane.getFont().getSize(); - private static final long MEGABYTE = 1024L * 1024L; - private final JMenu commandsMenu; - private final JMenu optionsMenu; + private final GeyserLogger logger; + + private final ColorPane consolePane = new ColorPane(); + private final int originalFontSize = consolePane.getFont().getSize(); + private final JTextField commandInput = new JTextField(); + private final CommandListener commandListener = new CommandListener(); + + private final GraphPanel ramGraph = new GraphPanel(); + private final List ramValues = new ArrayList<>(); + + private final DefaultTableModel playerTableModel = new DefaultTableModel(); + private final JTable playerTable = new JTable(playerTableModel); + + /** + * Create and show the Geyser-Standalone GUI + * + * @param logger the logger for determining debug mode, and executing commands from the console + */ + public GeyserStandaloneGUI(GeyserLogger logger) { + this.logger = logger; - public GeyserStandaloneGUI() { // Create the frame and setup basic settings JFrame frame = new JFrame(GeyserLocale.getLocaleStringLog("geyser.gui.title")); frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); @@ -81,8 +88,7 @@ public class GeyserStandaloneGUI { // Show a confirm dialog on close frame.addWindowListener(new WindowAdapter() { @Override - public void windowClosing(WindowEvent we) - { + public void windowClosing(WindowEvent we) { String[] buttons = {GeyserLocale.getLocaleStringLog("geyser.gui.exit.confirm"), GeyserLocale.getLocaleStringLog("geyser.gui.exit.deny")}; int result = JOptionPane.showOptionDialog(frame, GeyserLocale.getLocaleStringLog("geyser.gui.exit.message"), frame.getTitle(), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, buttons, buttons[1]); if (result == JOptionPane.YES_OPTION) { @@ -100,91 +106,41 @@ public class GeyserStandaloneGUI { frame.setIconImage(icon.getImage()); } + // File, View, Options, etc + setupMenuBar(frame); + // Setup the split pane and event listeners JSplitPane splitPane = new JSplitPane(); splitPane.setDividerLocation(600); - splitPane.addPropertyChangeListener("dividerLocation", e -> splitPaneLimit((JSplitPane)e.getSource())); + splitPane.addPropertyChangeListener("dividerLocation", e -> splitPaneLimit((JSplitPane) e.getSource())); splitPane.addComponentListener(new ComponentAdapter() { public void componentResized(ComponentEvent e) { - splitPaneLimit((JSplitPane)e.getSource()); + splitPaneLimit((JSplitPane) e.getSource()); } }); cp.add(splitPane, BorderLayout.CENTER); - // Set the background and disable input for the text pane + // Holds console and command input components + JPanel leftPane = new JPanel(new BorderLayout()); + splitPane.setLeftComponent(leftPane); + + // Set the background and disable editing of the console consolePane.setBackground(Color.BLACK); consolePane.setEditable(false); // Wrap the text pane in a scroll pane and add it to the form JScrollPane consoleScrollPane = new JScrollPane(consolePane); - //cp.add(consoleScrollPane, BorderLayout.CENTER); - splitPane.setLeftComponent(consoleScrollPane); + leftPane.add(consoleScrollPane, BorderLayout.CENTER); - // Create a new menu bar for the top of the frame - JMenuBar menuBar = new JMenuBar(); - - // Create 'File' - JMenu fileMenu = new JMenu(GeyserLocale.getLocaleStringLog("geyser.gui.menu.file")); - fileMenu.setMnemonic(KeyEvent.VK_F); - menuBar.add(fileMenu); - - // 'Open Geyser folder' button - JMenuItem openButton = new JMenuItem(GeyserLocale.getLocaleStringLog("geyser.gui.menu.file.open_folder"), KeyEvent.VK_O); - openButton.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_MASK)); - openButton.addActionListener(e -> { - try { - Desktop.getDesktop().open(new File("./")); - } catch (IOException ignored) { } - }); - fileMenu.add(openButton); - - fileMenu.addSeparator(); - - // 'Exit' button - JMenuItem exitButton = new JMenuItem(GeyserLocale.getLocaleStringLog("geyser.gui.menu.file.exit"), KeyEvent.VK_X); - exitButton.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F4, InputEvent.ALT_MASK)); - exitButton.addActionListener(e -> System.exit(0)); - fileMenu.add(exitButton); - - // Create 'Commands' - commandsMenu = new JMenu(GeyserLocale.getLocaleStringLog("geyser.gui.menu.commands")); - commandsMenu.setMnemonic(KeyEvent.VK_C); - menuBar.add(commandsMenu); - - // Create 'View' - JMenu viewMenu = new JMenu(GeyserLocale.getLocaleStringLog("geyser.gui.menu.view")); - viewMenu.setMnemonic(KeyEvent.VK_V); - menuBar.add(viewMenu); - - // 'Zoom in' button - JMenuItem zoomInButton = new JMenuItem(GeyserLocale.getLocaleStringLog("geyser.gui.menu.view.zoom_in")); - zoomInButton.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_EQUALS, InputEvent.CTRL_DOWN_MASK)); - zoomInButton.addActionListener(e -> consolePane.setFont(new Font(consolePane.getFont().getName(), consolePane.getFont().getStyle(), consolePane.getFont().getSize() + 1))); - viewMenu.add(zoomInButton); - - // 'Zoom in' button - JMenuItem zoomOutButton = new JMenuItem(GeyserLocale.getLocaleStringLog("geyser.gui.menu.view.zoom_out")); - zoomOutButton.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_MINUS, InputEvent.CTRL_DOWN_MASK)); - zoomOutButton.addActionListener(e -> consolePane.setFont(new Font(consolePane.getFont().getName(), consolePane.getFont().getStyle(), consolePane.getFont().getSize() - 1))); - viewMenu.add(zoomOutButton); - - // 'Reset Zoom' button - JMenuItem resetZoomButton = new JMenuItem(GeyserLocale.getLocaleStringLog("geyser.gui.menu.view.reset_zoom")); - resetZoomButton.addActionListener(e -> consolePane.setFont(new Font(consolePane.getFont().getName(), consolePane.getFont().getStyle(), originalFontSize))); - viewMenu.add(resetZoomButton); - - // create 'Options' - optionsMenu = new JMenu(GeyserLocale.getLocaleStringLog("geyser.gui.menu.options")); - viewMenu.setMnemonic(KeyEvent.VK_O); - menuBar.add(optionsMenu); - - // Set the frames menu bar - frame.setJMenuBar(menuBar); + // a bit taller than the default layout - width is ignored fortunately + commandInput.setPreferredSize(new Dimension(100, 25)); + commandInput.setEnabled(false); // disabled until command handler is initialized + commandInput.addActionListener(commandListener); + leftPane.add(commandInput, BorderLayout.SOUTH); JPanel rightPane = new JPanel(); rightPane.setLayout(new CardLayout(5, 5)); - //cp.add(rightPane, BorderLayout.EAST); splitPane.setRightComponent(rightPane); JPanel rightContentPane = new JPanel(); @@ -209,12 +165,75 @@ public class GeyserStandaloneGUI { frame.setVisible(true); } + private void setupMenuBar(JFrame frame) { + // Create a new menu bar for the top of the frame + JMenuBar menuBar = new JMenuBar(); + + // Create 'File' + JMenu fileMenu = new JMenu(GeyserLocale.getLocaleStringLog("geyser.gui.menu.file")); + fileMenu.setMnemonic(KeyEvent.VK_F); + menuBar.add(fileMenu); + + // 'Open Geyser folder' button + JMenuItem openButton = new JMenuItem(GeyserLocale.getLocaleStringLog("geyser.gui.menu.file.open_folder"), KeyEvent.VK_O); + openButton.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_DOWN_MASK)); + openButton.addActionListener(e -> { + try { + Desktop.getDesktop().open(new File("./")); + } catch (IOException ignored) { } + }); + fileMenu.add(openButton); + + fileMenu.addSeparator(); + + // 'Exit' button + JMenuItem exitButton = new JMenuItem(GeyserLocale.getLocaleStringLog("geyser.gui.menu.file.exit"), KeyEvent.VK_X); + exitButton.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F4, InputEvent.ALT_DOWN_MASK)); + exitButton.addActionListener(e -> System.exit(0)); + fileMenu.add(exitButton); + + // Create 'View' + JMenu viewMenu = new JMenu(GeyserLocale.getLocaleStringLog("geyser.gui.menu.view")); + viewMenu.setMnemonic(KeyEvent.VK_V); + menuBar.add(viewMenu); + + // 'Zoom in' button + JMenuItem zoomInButton = new JMenuItem(GeyserLocale.getLocaleStringLog("geyser.gui.menu.view.zoom_in")); + zoomInButton.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_EQUALS, InputEvent.CTRL_DOWN_MASK)); + zoomInButton.addActionListener(e -> consolePane.setFont(new Font(consolePane.getFont().getName(), consolePane.getFont().getStyle(), consolePane.getFont().getSize() + 1))); + viewMenu.add(zoomInButton); + + // 'Zoom in' button + JMenuItem zoomOutButton = new JMenuItem(GeyserLocale.getLocaleStringLog("geyser.gui.menu.view.zoom_out")); + zoomOutButton.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_MINUS, InputEvent.CTRL_DOWN_MASK)); + zoomOutButton.addActionListener(e -> consolePane.setFont(new Font(consolePane.getFont().getName(), consolePane.getFont().getStyle(), consolePane.getFont().getSize() - 1))); + viewMenu.add(zoomOutButton); + + // 'Reset Zoom' button + JMenuItem resetZoomButton = new JMenuItem(GeyserLocale.getLocaleStringLog("geyser.gui.menu.view.reset_zoom")); + resetZoomButton.addActionListener(e -> consolePane.setFont(new Font(consolePane.getFont().getName(), consolePane.getFont().getStyle(), originalFontSize))); + viewMenu.add(resetZoomButton); + + // create 'Options' + JMenu optionsMenu = new JMenu(GeyserLocale.getLocaleStringLog("geyser.gui.menu.options")); + viewMenu.setMnemonic(KeyEvent.VK_O); + menuBar.add(optionsMenu); + + JCheckBoxMenuItem debugMode = new JCheckBoxMenuItem(GeyserLocale.getLocaleStringLog("geyser.gui.menu.options.toggle_debug_mode")); + debugMode.setSelected(logger.isDebug()); + debugMode.addActionListener(e -> logger.setDebug(debugMode.getState())); + optionsMenu.add(debugMode); + + // Set the frames menu bar + frame.setJMenuBar(menuBar); + } + /** * Queue up an update to the text pane so we don't block the main thread * * @param text The text to append */ - private void updateTextPane(final String text) { + private void appendConsole(final String text) { SwingUtilities.invokeLater(() -> { consolePane.appendANSI(text); Document doc = consolePane.getDocument(); @@ -230,12 +249,12 @@ public class GeyserStandaloneGUI { OutputStream out = new OutputStream() { @Override public void write(final int b) { - updateTextPane(String.valueOf((char) b)); + appendConsole(String.valueOf((char) b)); } @Override public void write(byte[] b, int off, int len) { - updateTextPane(new String(b, off, len)); + appendConsole(new String(b, off, len)); } @Override @@ -251,50 +270,17 @@ public class GeyserStandaloneGUI { } /** - * Add all the Geyser commands to the commands menu, and setup the debug mode toggle + * Enable the command input box. * - * @param geyserStandaloneLogger The current logger - * @param geyserCommandManager The commands manager + * @param executor the executor for running commands off the GUI thread + * @param commandManager the command manager to delegate commands to */ - public void setupInterface(GeyserStandaloneLogger geyserStandaloneLogger, GeyserCommandManager geyserCommandManager) { - commandsMenu.removeAll(); - optionsMenu.removeAll(); - - for (Map.Entry entry : geyserCommandManager.getCommands().entrySet()) { - // Remove the offhand command and any alias commands to prevent duplicates in the list - if (!entry.getValue().isExecutableOnConsole() || entry.getValue().aliases().contains(entry.getKey())) { - continue; - } - - GeyserCommand command = (GeyserCommand) entry.getValue(); - // Create the button that runs the command - boolean hasSubCommands = !entry.getValue().subCommands().isEmpty(); - // Add an extra menu if there are more commands that can be run - JMenuItem commandButton = hasSubCommands ? new JMenu(entry.getValue().name()) : new JMenuItem(entry.getValue().name()); - commandButton.getAccessibleContext().setAccessibleDescription(entry.getValue().description()); - if (!hasSubCommands) { - commandButton.addActionListener(e -> command.execute(null, geyserStandaloneLogger, new String[]{ })); - } else { - // Add a submenu that's the same name as the menu can't be pressed - JMenuItem otherCommandButton = new JMenuItem(entry.getValue().name()); - otherCommandButton.getAccessibleContext().setAccessibleDescription(entry.getValue().description()); - otherCommandButton.addActionListener(e -> command.execute(null, geyserStandaloneLogger, new String[]{ })); - commandButton.add(otherCommandButton); - // Add a menu option for all possible subcommands - for (String subCommandName : entry.getValue().subCommands()) { - JMenuItem item = new JMenuItem(subCommandName); - item.addActionListener(e -> command.execute(null, geyserStandaloneLogger, new String[]{subCommandName})); - commandButton.add(item); - } - } - commandsMenu.add(commandButton); - } - - // 'Debug Mode' toggle - JCheckBoxMenuItem debugMode = new JCheckBoxMenuItem(GeyserLocale.getLocaleStringLog("geyser.gui.menu.options.toggle_debug_mode")); - debugMode.setSelected(geyserStandaloneLogger.isDebug()); - debugMode.addActionListener(e -> geyserStandaloneLogger.setDebug(!geyserStandaloneLogger.isDebug())); - optionsMenu.add(debugMode); + public void enableCommands(ScheduledExecutorService executor, GeyserCommandManager commandManager) { + // we don't want to block the GUI thread with the command execution + // todo: once cloud is used, an AsynchronousCommandExecutionCoordinator can be used to avoid this scheduler + commandListener.handler = cmd -> executor.schedule(() -> commandManager.runCommand(logger, cmd), 0, TimeUnit.SECONDS); + commandInput.setEnabled(true); + commandInput.requestFocusInWindow(); } /** @@ -322,14 +308,14 @@ public class GeyserStandaloneGUI { // Update ram graph final long freeMemory = Runtime.getRuntime().freeMemory(); final long totalMemory = Runtime.getRuntime().totalMemory(); - final int freePercent = (int)(freeMemory * 100.0 / totalMemory + 0.5); + final int freePercent = (int) (freeMemory * 100.0 / totalMemory + 0.5); ramValues.add(100 - freePercent); ramGraph.setXLabel(GeyserLocale.getLocaleStringLog("geyser.gui.graph.usage", String.format("%,d", (totalMemory - freeMemory) / MEGABYTE), freePercent)); // Trim the list int k = ramValues.size(); - if ( k > 10 ) + if (k > 10) ramValues.subList(0, k - 10).clear(); // Update the graph @@ -354,4 +340,17 @@ public class GeyserStandaloneGUI { splitPane.setDividerLocation(frame.getWidth() - 200); } } + + private class CommandListener implements ActionListener { + + private Consumer handler; + + @Override + public void actionPerformed(ActionEvent e) { + String command = commandInput.getText(); + appendConsole(command + "\n"); // show what was run in the console + handler.accept(command); // run the command + commandInput.setText(""); // clear the input + } + } } diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index 5814348ed..d13836e9a 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -218,25 +218,9 @@ public class GeyserImpl implements GeyserApi { GeyserConfiguration config = bootstrap.getGeyserConfig(); - boolean isGui = false; - // This will check if we are in standalone and get the 'useGui' variable from there - if (platformType == PlatformType.STANDALONE) { - try { - Class cls = Class.forName("org.geysermc.geyser.platform.standalone.GeyserStandaloneBootstrap"); - isGui = (boolean) cls.getMethod("isUseGui").invoke(cls.cast(bootstrap)); - } catch (Exception e) { - logger.debug("Failed detecting if standalone is using a GUI; if this is a GeyserConnect instance this can be safely ignored."); - } - } - double completeTime = (System.currentTimeMillis() - startupTime) / 1000D; - String message = GeyserLocale.getLocaleStringLog("geyser.core.finish.done", new DecimalFormat("#.###").format(completeTime)) + " "; - if (isGui) { - message += GeyserLocale.getLocaleStringLog("geyser.core.finish.gui"); - } else { - message += GeyserLocale.getLocaleStringLog("geyser.core.finish.console"); - } - + String message = GeyserLocale.getLocaleStringLog("geyser.core.finish.done", new DecimalFormat("#.###").format(completeTime)); + message += " " + GeyserLocale.getLocaleStringLog("geyser.core.finish.console"); logger.info(message); if (platformType == PlatformType.STANDALONE) { diff --git a/core/src/main/resources/languages b/core/src/main/resources/languages index f6685c4cc..fda08c186 160000 --- a/core/src/main/resources/languages +++ b/core/src/main/resources/languages @@ -1 +1 @@ -Subproject commit f6685c4ccc6e77b07402d45cb41213559004b7d6 +Subproject commit fda08c186de979ff89b01d2b66f48daa5e218d01 From c7304f04e9bbefbe944c5c21c1c65017af30bfe9 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Mon, 26 Jun 2023 15:18:29 -0400 Subject: [PATCH 021/344] Make PlatformType fields final (#3917) --- .../org/geysermc/geyser/api/util/PlatformType.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/api/src/main/java/org/geysermc/geyser/api/util/PlatformType.java b/api/src/main/java/org/geysermc/geyser/api/util/PlatformType.java index 185e73168..2244d3a2a 100644 --- a/api/src/main/java/org/geysermc/geyser/api/util/PlatformType.java +++ b/api/src/main/java/org/geysermc/geyser/api/util/PlatformType.java @@ -29,11 +29,11 @@ package org.geysermc.geyser.api.util; * Represents the platform Geyser is running on. */ public record PlatformType(String platformName) { - public static PlatformType ANDROID = new PlatformType("Android"); - public static PlatformType BUNGEECORD = new PlatformType("BungeeCord"); - public static PlatformType FABRIC = new PlatformType("Fabric"); - public static PlatformType SPIGOT = new PlatformType("Spigot"); - public static PlatformType SPONGE = new PlatformType("Sponge"); - public static PlatformType STANDALONE = new PlatformType("Standalone"); - public static PlatformType VELOCITY = new PlatformType("Velocity"); + public static final PlatformType ANDROID = new PlatformType("Android"); + public static final PlatformType BUNGEECORD = new PlatformType("BungeeCord"); + public static final PlatformType FABRIC = new PlatformType("Fabric"); + public static final PlatformType SPIGOT = new PlatformType("Spigot"); + public static final PlatformType SPONGE = new PlatformType("Sponge"); + public static final PlatformType STANDALONE = new PlatformType("Standalone"); + public static final PlatformType VELOCITY = new PlatformType("Velocity"); } From b43bc3d86e50fdfa93b8129e8be49a324f1b4429 Mon Sep 17 00:00:00 2001 From: Tim203 Date: Tue, 27 Jun 2023 12:59:55 +0200 Subject: [PATCH 022/344] Updated protocol version for jwt changes --- gradle/libs.versions.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 31c732712..f5d19df5e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,8 +9,8 @@ netty = "4.1.80.Final" guava = "29.0-jre" gson = "2.3.1" # Provided by Spigot 1.8.8 websocket = "1.5.1" -protocol = "3.0.0.Beta1-20230613.104224-93" -protocol-connection = "3.0.0.Beta1-20230613.104224-92" +protocol = "3.0.0.Beta1-20230627.180522-98" +protocol-connection = "3.0.0.Beta1-20230627.180522-97" raknet = "1.0.0.CR1-20230609.174844-8" mcauthlib = "d9d773e" mcprotocollib = "1.20-1-20230607.135651-6" # Temporary hack - needs to be updated to release once publishing is fixed From 40775149f572cecd8855daf1c3764608b7985896 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Wed, 28 Jun 2023 00:31:03 -0400 Subject: [PATCH 023/344] NMS adapter for spigot 1.20 (#3911) --- bootstrap/spigot/build.gradle.kts | 4 +++- gradle/libs.versions.toml | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/bootstrap/spigot/build.gradle.kts b/bootstrap/spigot/build.gradle.kts index 85a46598c..129064cd4 100644 --- a/bootstrap/spigot/build.gradle.kts +++ b/bootstrap/spigot/build.gradle.kts @@ -4,7 +4,9 @@ dependencies { isTransitive = false } - implementation(libs.adapters.spigot) + implementation(variantOf(libs.adapters.spigot) { + classifier("all") // otherwise the unshaded jar is used without the shaded NMS implementations + }) implementation(libs.commodore) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f5d19df5e..7ec4dcaf6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -23,7 +23,7 @@ jline = "3.21.0" terminalconsoleappender = "1.2.0" folia = "1.19.4-R0.1-SNAPSHOT" viaversion = "4.0.0" -adapters = "1.8-SNAPSHOT" +adapters = "1.9-SNAPSHOT" commodore = "2.2" bungeecord = "a7c6ede" velocity = "3.0.0" From b344e21f7f729998eb4b1b7d948bc184594b8864 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Thu, 29 Jun 2023 07:22:13 -0400 Subject: [PATCH 024/344] Fix loading contents keys of encrypted resource packs (#3925) --- .../registry/loader/ResourcePackLoader.java | 2 +- .../loader/ResourcePackLoaderTest.java | 27 ++++++++++++++++++ core/src/test/resources/empty_pack.mcpack | Bin 0 -> 557 bytes core/src/test/resources/encrypted_pack.zip | Bin 0 -> 638 bytes .../src/test/resources/encrypted_pack.zip.key | 1 + 5 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 core/src/test/resources/empty_pack.mcpack create mode 100644 core/src/test/resources/encrypted_pack.zip create mode 100644 core/src/test/resources/encrypted_pack.zip.key diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/ResourcePackLoader.java b/core/src/main/java/org/geysermc/geyser/registry/loader/ResourcePackLoader.java index afb5a2fe8..452550d87 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/loader/ResourcePackLoader.java +++ b/core/src/main/java/org/geysermc/geyser/registry/loader/ResourcePackLoader.java @@ -146,7 +146,7 @@ public class ResourcePackLoader implements RegistryLoader#cN7U>5-)p0QV&T2^S9&+y{XgRv`?Jz zuUvc^hi~uQ%WuvY=Np~>{#UkT`j%TIS4`(;thu69*`Q?We{Uj}$--i{<;xsS_r8fu znf!d^BKHcHM3esv&0*Dt1*@d${Fv)3Lzw0jY{*#fwd*+V%Qlr*R_$94XGk2h{I0qr zCgGm9VN%3a(fiYP_gu3)$>BI{W7D+AeJfqhMr_oU+#3sNhAlvzAtM6=FOW{o&nrpID=F5?D$dWldvGCNlY<1q z1MRYS2Q#zY|Hle99ZpI+cj#H##yjgHwn*@>`B<5oEl&}e>bD?Z!DJ5>g%4sZ95$@? z-K%n^RHhhg-?F(Z#!!|eTq7V$ae}n>lUfG|G9jpFXFAH^zP$>Iu`u)tDpDzx( zy!_E9u(tfq1&)7gMjU?%p0Ne8TQ7gzW*^IKwUK?sgRj=y9d_)zX2CBfrT_3LXtPb~ zm;N}o*F$mpA~}|FlZ6g>x2#|7w9z{?XRW4nN%HdVZ`Uo_ zH*M;afT>w4*1q!1uUa}QcJ+#w_4BVMS;uhQnqA|hvp9a?zeh_`|9vYuFCH$o;0oK8 zZ5!T;{LN0>Q3LckBa=M?uDDVG1_KBvfJwBN Date: Sun, 2 Jul 2023 17:00:46 -0400 Subject: [PATCH 025/344] Camera shake and fog effect api (#3931) --- .../api/bedrock/camera/CameraShake.java | 31 +++++++ .../api/connection/GeyserConnection.java | 45 +++++++++- build.gradle.kts | 2 +- .../geyser/level/BedrockDimension.java | 6 +- .../geyser/session/GeyserSession.java | 86 ++++++++++++------- .../protocol/java/JavaLoginTranslator.java | 2 +- .../geysermc/geyser/util/DimensionUtils.java | 16 ++-- gradle.properties | 6 -- 8 files changed, 142 insertions(+), 52 deletions(-) create mode 100644 api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraShake.java diff --git a/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraShake.java b/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraShake.java new file mode 100644 index 000000000..18bafb428 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraShake.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019-2023 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.api.bedrock.camera; + +public enum CameraShake { + POSITIONAL, + ROTATIONAL; +} diff --git a/api/src/main/java/org/geysermc/geyser/api/connection/GeyserConnection.java b/api/src/main/java/org/geysermc/geyser/api/connection/GeyserConnection.java index 8d695bf02..7094812a0 100644 --- a/api/src/main/java/org/geysermc/geyser/api/connection/GeyserConnection.java +++ b/api/src/main/java/org/geysermc/geyser/api/connection/GeyserConnection.java @@ -29,10 +29,12 @@ import org.checkerframework.checker.index.qual.NonNegative; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.api.connection.Connection; +import org.geysermc.geyser.api.bedrock.camera.CameraShake; import org.geysermc.geyser.api.command.CommandSource; import org.geysermc.geyser.api.entity.type.GeyserEntity; import org.geysermc.geyser.api.entity.type.player.GeyserPlayerEntity; +import java.util.Set; import java.util.concurrent.CompletableFuture; /** @@ -47,9 +49,50 @@ public interface GeyserConnection extends Connection, CommandSource { CompletableFuture<@Nullable GeyserEntity> entityByJavaId(@NonNegative int javaId); /** + * Displays a player entity as emoting to this client. * * @param emoter the player entity emoting. - * @param emoteId the emote ID to send to the client. + * @param emoteId the emote ID to send to this client. */ void showEmote(@NonNull GeyserPlayerEntity emoter, @NonNull String emoteId); + + /** + * Shakes the client's camera.

+ * If the camera is already shaking with the same {@link CameraShake} type, then the additional intensity + * will be layered on top of the existing intensity, with their own distinct durations.
+ * If the existing shake type is different and the new intensity/duration are not positive, the existing shake only + * switches to the new type. Otherwise, the existing shake is completely overridden. + * + * @param intensity the intensity of the shake. The client has a maximum total intensity of 4. + * @param duration the time in seconds that the shake will occur for + * @param type the type of shake + */ + void shakeCamera(float intensity, float duration, @NonNull CameraShake type); + + /** + * Stops all camera shake of any type. + */ + void stopCameraShake(); + + /** + * Adds the given fog IDs to the fog cache, then sends all fog IDs in the cache to the client. + *

+ * Fog IDs can be found here + * + * @param fogNameSpaces the fog IDs to add. If empty, the existing cached IDs will still be sent. + */ + void sendFog(String... fogNameSpaces); + + /** + * Removes the given fog IDs from the fog cache, then sends all fog IDs in the cache to the client. + * + * @param fogNameSpaces the fog IDs to remove. If empty, all fog IDs will be removed. + */ + void removeFog(String... fogNameSpaces); + + /** + * Returns an immutable copy of all fog affects currently applied to this client. + */ + @NonNull + Set fogEffects(); } diff --git a/build.gradle.kts b/build.gradle.kts index c64667ad2..d8fe1c769 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,7 +6,7 @@ plugins { allprojects { group = "org.geysermc.geyser" - version = "2.1.1-SNAPSHOT" + version = "2.1.2-SNAPSHOT" description = "Allows for players from Minecraft: Bedrock Edition to join Minecraft: Java Edition servers." tasks.withType { diff --git a/core/src/main/java/org/geysermc/geyser/level/BedrockDimension.java b/core/src/main/java/org/geysermc/geyser/level/BedrockDimension.java index 78c6b2c6a..250c0f7a4 100644 --- a/core/src/main/java/org/geysermc/geyser/level/BedrockDimension.java +++ b/core/src/main/java/org/geysermc/geyser/level/BedrockDimension.java @@ -35,7 +35,7 @@ package org.geysermc.geyser.level; * @param doUpperHeightWarn whether to warn in the console if the Java dimension height exceeds Bedrock's. */ public record BedrockDimension(int minY, int height, boolean doUpperHeightWarn) { - public static BedrockDimension OVERWORLD = new BedrockDimension(-64, 384, true); - public static BedrockDimension THE_NETHER = new BedrockDimension(0, 128, false); - public static BedrockDimension THE_END = new BedrockDimension(0, 256, true); + public static final BedrockDimension OVERWORLD = new BedrockDimension(-64, 384, true); + public static final BedrockDimension THE_NETHER = new BedrockDimension(0, 128, false); + public static final BedrockDimension THE_END = new BedrockDimension(0, 256, true); } diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 73dd253f3..dba4bd112 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -98,6 +98,7 @@ import org.cloudburstmc.protocol.common.util.OptionalBoolean; import org.geysermc.api.util.BedrockPlatform; import org.geysermc.api.util.InputMode; import org.geysermc.api.util.UiProfile; +import org.geysermc.geyser.api.bedrock.camera.CameraShake; import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.cumulus.form.Form; import org.geysermc.cumulus.form.util.FormBuilder; @@ -533,7 +534,10 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { @Setter private boolean waitingForStatistics = false; - private final Set fogNameSpaces = new HashSet<>(); + /** + * All fog effects that are currently applied to the client. + */ + private final Set appliedFog = new HashSet<>(); private final Set emotes; @@ -1828,38 +1832,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { } } - /** - * Send the following fog IDs, as well as the cached ones, to the client. - * - * Fog IDs can be found here: - * https://wiki.bedrock.dev/documentation/fog-ids.html - * - * @param fogNameSpaces the fog ids to add - */ - public void sendFog(String... fogNameSpaces) { - this.fogNameSpaces.addAll(Arrays.asList(fogNameSpaces)); - - PlayerFogPacket packet = new PlayerFogPacket(); - packet.getFogStack().addAll(this.fogNameSpaces); - sendUpstreamPacket(packet); - } - - /** - * Removes the following fog IDs from the client and the cache. - * - * @param fogNameSpaces the fog ids to remove - */ - public void removeFog(String... fogNameSpaces) { - if (fogNameSpaces.length == 0) { - this.fogNameSpaces.clear(); - } else { - this.fogNameSpaces.removeAll(Arrays.asList(fogNameSpaces)); - } - PlayerFogPacket packet = new PlayerFogPacket(); - packet.getFogStack().addAll(this.fogNameSpaces); - sendUpstreamPacket(packet); - } - public boolean canUseCommandBlocks() { return instabuild && opPermissionLevel >= 2; } @@ -1971,6 +1943,54 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { sendUpstreamPacket(packet); } + @Override + public void shakeCamera(float intensity, float duration, @NonNull CameraShake type) { + CameraShakePacket packet = new CameraShakePacket(); + packet.setIntensity(intensity); + packet.setDuration(duration); + packet.setShakeType(type == CameraShake.POSITIONAL ? CameraShakeType.POSITIONAL : CameraShakeType.ROTATIONAL); + packet.setShakeAction(CameraShakeAction.ADD); + sendUpstreamPacket(packet); + } + + @Override + public void stopCameraShake() { + CameraShakePacket packet = new CameraShakePacket(); + // CameraShakeAction.STOP removes all types regardless of the given type, but regardless it can't be null + packet.setShakeType(CameraShakeType.POSITIONAL); + packet.setShakeAction(CameraShakeAction.STOP); + sendUpstreamPacket(packet); + } + + @Override + public void sendFog(String... fogNameSpaces) { + Collections.addAll(this.appliedFog, fogNameSpaces); + + PlayerFogPacket packet = new PlayerFogPacket(); + packet.getFogStack().addAll(this.appliedFog); + sendUpstreamPacket(packet); + } + + @Override + public void removeFog(String... fogNameSpaces) { + if (fogNameSpaces.length == 0) { + this.appliedFog.clear(); + } else { + for (String id : fogNameSpaces) { + this.appliedFog.remove(id); + } + } + PlayerFogPacket packet = new PlayerFogPacket(); + packet.getFogStack().addAll(this.appliedFog); + sendUpstreamPacket(packet); + } + + @Override + public @NonNull Set fogEffects() { + // Use a copy so that sendFog/removeFog can be called while iterating the returned set (avoid CME) + return Set.copyOf(this.appliedFog); + } + public void addCommandEnum(String name, String enums) { softEnumPacket(name, SoftEnumUpdateType.ADD, enums); } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java index 3d9f08ec7..9f7fd4f40 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java @@ -148,7 +148,7 @@ public class JavaLoginTranslator extends PacketTranslator Date: Sun, 2 Jul 2023 19:27:40 -0400 Subject: [PATCH 026/344] Specify Java 1.20.1 as supported --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2faefed56..11a9c1eb6 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,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.19.80 - 1.20 and Minecraft Java 1.20. +### Currently supporting Minecraft Bedrock 1.19.80 - 1.20 and Minecraft Java 1.20/1.20.1. ## Setting Up Take a look [here](https://wiki.geysermc.org/geyser/setup/) for how to set up Geyser. From d44e599925eaa8b70b43bc0b8322843477aaadfc Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Tue, 4 Jul 2023 18:06:05 -0400 Subject: [PATCH 027/344] Fix #3905 --- .../SuspiciousBlockBlockEntityTranslator.java | 27 +++++++++++++++++++ gradle/libs.versions.toml | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SuspiciousBlockBlockEntityTranslator.java diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SuspiciousBlockBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SuspiciousBlockBlockEntityTranslator.java new file mode 100644 index 000000000..2bdce3d14 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SuspiciousBlockBlockEntityTranslator.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2019-2023 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.translator.level.block.entity;public class SuspiciousBlockBlockEntityTranslator { +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7ec4dcaf6..4ff4fbc8a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ gson = "2.3.1" # Provided by Spigot 1.8.8 websocket = "1.5.1" protocol = "3.0.0.Beta1-20230627.180522-98" protocol-connection = "3.0.0.Beta1-20230627.180522-97" -raknet = "1.0.0.CR1-20230609.174844-8" +raknet = "1.0.0.CR1-20230703.195238-9" mcauthlib = "d9d773e" mcprotocollib = "1.20-1-20230607.135651-6" # Temporary hack - needs to be updated to release once publishing is fixed adventure = "4.14.0-20230424.215040-7" From 9ad7473496065172f8f6c5c6bdd579ad25d0d263 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Tue, 4 Jul 2023 18:14:32 -0400 Subject: [PATCH 028/344] Re-add this part of gradle.properties we need to build --- gradle.properties | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index c1e6d7cd3..0a463e38f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,4 +3,7 @@ org.gradle.jvmargs=-Xmx4G org.gradle.configureondemand=true org.gradle.caching=true org.gradle.parallel=true -org.gradle.vfs.watch=false \ No newline at end of file +org.gradle.vfs.watch=false + +group=org.geysermc +version=2.1.1-SNAPSHOT \ No newline at end of file From 0e3e2d0e280219eb31802b256ae3e5199fd7487b Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Tue, 4 Jul 2023 19:18:12 -0400 Subject: [PATCH 029/344] Remove unused file --- .../SuspiciousBlockBlockEntityTranslator.java | 27 ------------------- 1 file changed, 27 deletions(-) delete mode 100644 core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SuspiciousBlockBlockEntityTranslator.java diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SuspiciousBlockBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SuspiciousBlockBlockEntityTranslator.java deleted file mode 100644 index 2bdce3d14..000000000 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SuspiciousBlockBlockEntityTranslator.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2019-2023 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.translator.level.block.entity;public class SuspiciousBlockBlockEntityTranslator { -} From d1357df8f54001d81ccc9673fcec4e6c6b7406a6 Mon Sep 17 00:00:00 2001 From: chris Date: Thu, 6 Jul 2023 19:19:02 +0200 Subject: [PATCH 030/344] fix https://github.com/GeyserMC/Geyser/issues/3938 (#3947) --- .../java/org/geysermc/geyser/util/SoundUtils.java | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/util/SoundUtils.java b/core/src/main/java/org/geysermc/geyser/util/SoundUtils.java index 295e3b888..18c37d0b0 100644 --- a/core/src/main/java/org/geysermc/geyser/util/SoundUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/SoundUtils.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.util; -import com.github.steveice10.mc.protocol.data.game.level.sound.BuiltinSound; import com.github.steveice10.mc.protocol.data.game.level.sound.Sound; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.LevelEvent; @@ -66,9 +65,7 @@ public final class SoundUtils { * @return a Bedrock sound */ public static String translatePlaySound(String javaIdentifier) { - javaIdentifier = trim(javaIdentifier); - - SoundMapping soundMapping = Registries.SOUNDS.get(javaIdentifier); + SoundMapping soundMapping = Registries.SOUNDS.get(trim(javaIdentifier)); if (soundMapping == null || soundMapping.getPlaysound() == null) { // no mapping GeyserImpl.getInstance().getLogger().debug("[PlaySound] Defaulting to sound server gave us for " + javaIdentifier); @@ -104,13 +101,7 @@ public final class SoundUtils { * @param pitch the pitch */ public static void playSound(GeyserSession session, Sound javaSound, Vector3f position, float volume, float pitch) { - String packetSound; - if (!(javaSound instanceof BuiltinSound)) { - // Identifier needs trimmed probably. - packetSound = trim(javaSound.getName()); - } else { - packetSound = javaSound.getName(); - } + String packetSound = javaSound.getName(); SoundMapping soundMapping = Registries.SOUNDS.get(packetSound); if (soundMapping == null) { From 78e788dca0cca220294c317ca9addc4d8b2cb980 Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 7 Jul 2023 20:55:28 +0200 Subject: [PATCH 031/344] - indicate 1.20.1 support on modrinth (#3950) - fix plan incompatibility by setting a proper refmap json name --- bootstrap/fabric/build.gradle.kts | 6 +++++- .../fabric/src/main/resources/geyser-fabric.mixins.json | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/bootstrap/fabric/build.gradle.kts b/bootstrap/fabric/build.gradle.kts index 44714cc7c..c260703a5 100644 --- a/bootstrap/fabric/build.gradle.kts +++ b/bootstrap/fabric/build.gradle.kts @@ -35,6 +35,10 @@ dependencies { } } +loom { + mixin.defaultRefmapName.set("geyser-fabric-refmap.json") +} + repositories { mavenLocal() maven("https://repo.opencollab.dev/maven-releases/") @@ -114,7 +118,7 @@ modrinth { syncBodyFrom.set(rootProject.file("README.md").readText()) uploadFile.set(tasks.getByPath("remapModrinthJar")) - gameVersions.addAll("1.20") + gameVersions.addAll("1.20", "1.20.1") loaders.add("fabric") failSilently.set(true) diff --git a/bootstrap/fabric/src/main/resources/geyser-fabric.mixins.json b/bootstrap/fabric/src/main/resources/geyser-fabric.mixins.json index c688ace36..aeb051809 100644 --- a/bootstrap/fabric/src/main/resources/geyser-fabric.mixins.json +++ b/bootstrap/fabric/src/main/resources/geyser-fabric.mixins.json @@ -2,6 +2,7 @@ "required": true, "package": "org.geysermc.geyser.platform.fabric.mixin", "compatibilityLevel": "JAVA_16", + "refmap": "geyser-fabric-refmap.json", "client": [ "client.IntegratedServerMixin" ], From 872d7e3bb6b6c11c1edf1ff9d519138a90a422cb Mon Sep 17 00:00:00 2001 From: chris Date: Sat, 8 Jul 2023 00:14:38 +0200 Subject: [PATCH 032/344] let boats not sink down, use less choppy (but faster) animation (#3949) * let boats not sink down, use less choppy (but faster) animation * remove passenger check since that always returns true --- .../main/java/org/geysermc/geyser/entity/type/BoatEntity.java | 2 +- .../protocol/bedrock/BedrockMoveEntityAbsoluteTranslator.java | 4 ++-- .../protocol/bedrock/BedrockPlayerInputTranslator.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/BoatEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/BoatEntity.java index 25569990e..5527e773a 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/BoatEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/BoatEntity.java @@ -66,7 +66,7 @@ public class BoatEntity extends Entity { private int variant; // Looks too fast and too choppy with 0.1f, which is how I believe the Microsoftian client handles it - private final float ROWING_SPEED = 0.05f; + private final float ROWING_SPEED = 0.1f; public BoatEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { // Initial rotation is incorrect diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockMoveEntityAbsoluteTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockMoveEntityAbsoluteTranslator.java index c35c6c00a..4b5107bda 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockMoveEntityAbsoluteTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockMoveEntityAbsoluteTranslator.java @@ -36,7 +36,7 @@ import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; /** - * Sent by the client when moving a horse. + * Sent by the client when moving a horse or boat. */ @Translator(packet = MoveEntityAbsolutePacket.class) public class BedrockMoveEntityAbsoluteTranslator extends PacketTranslator { @@ -64,7 +64,7 @@ public class BedrockMoveEntityAbsoluteTranslator extends PacketTranslator= 100) { Vector3f vehiclePosition = vehicle.getPosition(); - if (vehicle instanceof BoatEntity) { + if (vehicle instanceof BoatEntity && !vehicle.isOnGround()) { // Remove some Y position to prevents boats flying up vehiclePosition = vehiclePosition.down(EntityDefinitions.BOAT.offset()); } From cc6bbf990271a095a67ce68f29248c55205888f1 Mon Sep 17 00:00:00 2001 From: chris Date: Sun, 9 Jul 2023 03:36:08 +0200 Subject: [PATCH 033/344] fix https://github.com/GeyserMC/Geyser/issues/3948 (#3955) --- .../java/org/geysermc/geyser/entity/type/LivingEntity.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java index 4f38297c3..be38098ac 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java @@ -41,7 +41,6 @@ import lombok.Setter; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.AttributeData; -import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId; @@ -211,10 +210,10 @@ public class LivingEntity extends Entity { // If an entity has a banner on them, it will be in the helmet slot in Java but the chestplate spot in Bedrock // But don't overwrite the chestplate if it isn't empty ItemMapping banner = session.getItemMappings().getStoredItems().banner(); - if (ItemDefinition.AIR.equals(chestplate.getDefinition()) && helmet.getDefinition().equals(banner)) { + if (ItemData.AIR.equals(chestplate) && helmet.getDefinition().equals(banner.getBedrockDefinition())) { chestplate = this.helmet; helmet = ItemData.AIR; - } else if (chestplate.getDefinition().equals(banner)) { + } else if (chestplate.getDefinition().equals(banner.getBedrockDefinition())) { // Prevent chestplate banners from showing erroneously chestplate = ItemData.AIR; } From 6296d4a97fec59dd916930348e017a3ffc5d5377 Mon Sep 17 00:00:00 2001 From: Tim203 Date: Mon, 10 Jul 2023 21:47:41 +0200 Subject: [PATCH 034/344] Bump Cumulus to 1.1.2 and fixed code being detected as Java 8 locally --- build.gradle.kts | 4 ---- gradle/libs.versions.toml | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index d8fe1c769..2eed8de91 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,10 +8,6 @@ allprojects { group = "org.geysermc.geyser" version = "2.1.2-SNAPSHOT" description = "Allows for players from Minecraft: Bedrock Edition to join Minecraft: Java Edition servers." - - tasks.withType { - options.encoding = "UTF-8" - } } val platforms = setOf( diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4ff4fbc8a..f32a840fa 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] base-api = "1.0.0-SNAPSHOT" -cumulus = "1.1.1" +cumulus = "1.1.2" erosion = "1.0-20230406.174837-8" events = "1.1-SNAPSHOT" jackson = "2.14.0" From 3a0c1b788a22492ac1068a2f2f17bab1cc995ef1 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Tue, 11 Jul 2023 19:17:01 -0400 Subject: [PATCH 035/344] Support for 1.20.10 (#3961) Co-authored-by: chris Co-authored-by: RednedEpic --- README.md | 2 +- .../geysermc/geyser/network/GameProtocol.java | 4 +- .../populator/BlockRegistryPopulator.java | 31 + .../CreativeItemRegistryPopulator.java | 26 +- .../populator/ItemRegistryPopulator.java | 16 +- .../geyser/registry/type/BlockMappings.java | 9 + .../protocol/java/JavaCommandsTranslator.java | 31 +- .../bedrock/block_palette.1_20_10.nbt | Bin 0 -> 108793 bytes .../bedrock/creative_items.1_20_10.json | 5793 +++++++++++++++++ .../bedrock/runtime_item_states.1_20_10.json | 5314 +++++++++++++++ gradle/libs.versions.toml | 4 +- 11 files changed, 11209 insertions(+), 21 deletions(-) create mode 100644 core/src/main/resources/bedrock/block_palette.1_20_10.nbt create mode 100644 core/src/main/resources/bedrock/creative_items.1_20_10.json create mode 100644 core/src/main/resources/bedrock/runtime_item_states.1_20_10.json diff --git a/README.md b/README.md index 11a9c1eb6..6c742de63 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,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.19.80 - 1.20 and Minecraft Java 1.20/1.20.1. +### Currently supporting Minecraft Bedrock 1.19.80 - 1.20.10 and Minecraft Java 1.20/1.20.1. ## 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/GameProtocol.java b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java index d4ab2f42e..abaea2c2b 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java @@ -30,6 +30,7 @@ import com.github.steveice10.mc.protocol.codec.PacketCodec; import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; import org.cloudburstmc.protocol.bedrock.codec.v582.Bedrock_v582; import org.cloudburstmc.protocol.bedrock.codec.v589.Bedrock_v589; +import org.cloudburstmc.protocol.bedrock.codec.v594.Bedrock_v594; import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec; import org.geysermc.geyser.session.GeyserSession; @@ -45,7 +46,7 @@ public final class GameProtocol { * Default Bedrock codec that should act as a fallback. Should represent the latest available * release of the game that Geyser supports. */ - public static final BedrockCodec DEFAULT_BEDROCK_CODEC = Bedrock_v589.CODEC; + public static final BedrockCodec DEFAULT_BEDROCK_CODEC = Bedrock_v594.CODEC; /** * A list of all supported Bedrock versions that can join Geyser @@ -62,6 +63,7 @@ public final class GameProtocol { SUPPORTED_BEDROCK_CODECS.add(Bedrock_v582.CODEC.toBuilder() .minecraftVersion("1.19.80/1.19.81") .build()); + SUPPORTED_BEDROCK_CODECS.add(Bedrock_v589.CODEC); SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC); } 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 10e6d808b..0c4a156d6 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 @@ -34,6 +34,7 @@ import it.unimi.dsi.fastutil.objects.*; import org.cloudburstmc.nbt.*; import org.cloudburstmc.protocol.bedrock.codec.v582.Bedrock_v582; import org.cloudburstmc.protocol.bedrock.codec.v589.Bedrock_v589; +import org.cloudburstmc.protocol.bedrock.codec.v594.Bedrock_v594; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.level.block.BlockStateValues; @@ -69,6 +70,34 @@ public final class BlockRegistryPopulator { private static void registerBedrockBlocks() { BiFunction emptyMapper = (bedrockIdentifier, statesBuilder) -> null; + // adapt 1.20 mappings to 1.20.10+ + BiFunction concreteAndShulkerBoxMapper = (bedrockIdentifier, statesBuilder) -> { + if (bedrockIdentifier.equals("minecraft:concrete")) { + String color = (String) statesBuilder.remove("color"); + if (color.equals("silver")) { + color = "light_gray"; + } + return "minecraft:" + color + "_concrete"; + } + if (bedrockIdentifier.equals("minecraft:shulker_box")) { + String color = (String) statesBuilder.remove("color"); + if (color.equals("silver")) { + color = "light_gray"; + } + return "minecraft:" + color + "_shulker_box"; + } + if (bedrockIdentifier.equals("minecraft:observer")) { + int direction = (int) statesBuilder.remove("facing_direction"); + statesBuilder.putString("minecraft:facing_direction", switch (direction) { + case 0 -> "east"; + case 1 -> "south"; + case 2 -> "north"; + default -> "west"; + }); + } + return null; + }; + // We are using mappings that directly support 1.20, so this maps it back to 1.19.80 BiFunction legacyMapper = (bedrockIdentifier, statesBuilder) -> { if (bedrockIdentifier.endsWith("pumpkin")) { @@ -115,6 +144,7 @@ public final class BlockRegistryPopulator { ImmutableMap, BiFunction> blockMappers = ImmutableMap., BiFunction>builder() .put(ObjectIntPair.of("1_19_80", Bedrock_v582.CODEC.getProtocolVersion()), legacyMapper) .put(ObjectIntPair.of("1_20_0", Bedrock_v589.CODEC.getProtocolVersion()), emptyMapper) + .put(ObjectIntPair.of("1_20_10", Bedrock_v594.CODEC.getProtocolVersion()), concreteAndShulkerBoxMapper) .build(); // We can keep this strong as nothing should be garbage collected @@ -242,6 +272,7 @@ public final class BlockRegistryPopulator { BlockRegistries.BLOCKS.register(palette.getKey().valueInt(), builder.blockStateVersion(stateVersion) .bedrockRuntimeMap(bedrockRuntimeMap) .javaToBedrockBlocks(javaToBedrockBlocks) + .stateDefinitionMap(blockStateOrderedMap) .itemFrames(itemFrames) .flowerPotBlocks(flowerPotBlocks) .jigsawStates(jigsawDefinitions) 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 index b60b811a2..8998b41a1 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/CreativeItemRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/CreativeItemRegistryPopulator.java @@ -26,7 +26,10 @@ package org.geysermc.geyser.registry.populator; import com.fasterxml.jackson.databind.JsonNode; +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectMaps; import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtUtils; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; @@ -34,6 +37,7 @@ 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.GeyserBedrockBlock; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -99,12 +103,32 @@ public class CreativeItemRegistryPopulator { count = countNode.asInt(); } + GeyserBedrockBlock blockDefinition = null; JsonNode blockRuntimeIdNode = itemNode.get("blockRuntimeId"); + JsonNode blockStateNode; if (blockRuntimeIdNode != null) { bedrockBlockRuntimeId = blockRuntimeIdNode.asInt(); if (bedrockBlockRuntimeId == 0 && !identifier.equals("minecraft:blue_candle")) { // FIXME bedrockBlockRuntimeId = -1; } + + blockDefinition = bedrockBlockRuntimeId == -1 ? null : blockMappings.getDefinition(bedrockBlockRuntimeId); + } else if ((blockStateNode = itemNode.get("block_state_b64")) != null) { + byte[] bytes = Base64.getDecoder().decode(blockStateNode.asText()); + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + try { + NbtMap stateTag = (NbtMap) NbtUtils.createReaderLE(bais).readTag(); + + // We remove these from the state definition map in + // BlockMappings, so we need to remove it from here + NbtMapBuilder builder = stateTag.toBuilder(); + builder.remove("name_hash"); + builder.remove("network_id"); + + blockDefinition = blockMappings.getDefinition(builder.build()); + } catch (IOException e) { + e.printStackTrace(); + } } JsonNode nbtNode = itemNode.get("nbt_b64"); @@ -129,6 +153,6 @@ public class CreativeItemRegistryPopulator { .damage(damage) .count(count) .tag(tag) - .blockDefinition(bedrockBlockRuntimeId == -1 ? null : blockMappings.getDefinition(bedrockBlockRuntimeId)); + .blockDefinition(blockDefinition); } } 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 cccdff853..b0d88c3e7 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 @@ -40,12 +40,13 @@ import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; import org.cloudburstmc.protocol.bedrock.codec.v582.Bedrock_v582; import org.cloudburstmc.protocol.bedrock.codec.v589.Bedrock_v589; +import org.cloudburstmc.protocol.bedrock.codec.v594.Bedrock_v594; +import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.definitions.SimpleItemDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; -import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.item.custom.CustomItemData; @@ -82,6 +83,7 @@ public class ItemRegistryPopulator { } public static void populate() { + // Used for the 1.19.80 item palette Map legacyJavaOnly = new HashMap<>(); legacyJavaOnly.put(Items.MUSIC_DISC_RELIC, "minecraft:music_disc_wait"); legacyJavaOnly.put(Items.PITCHER_PLANT, "minecraft:chorus_flower"); @@ -90,6 +92,7 @@ public class ItemRegistryPopulator { List paletteVersions = new ArrayList<>(2); paletteVersions.add(new PaletteVersion("1_19_80", Bedrock_v582.CODEC.getProtocolVersion(), legacyJavaOnly, (item, mapping) -> { + // Backward-map 1.20 mappings to 1.19.80 String id = item.javaIdentifier(); if (id.endsWith("pottery_sherd")) { return mapping.withBedrockIdentifier(id.replace("sherd", "shard")); @@ -102,6 +105,17 @@ public class ItemRegistryPopulator { return mapping; })); paletteVersions.add(new PaletteVersion("1_20_0", Bedrock_v589.CODEC.getProtocolVersion())); + paletteVersions.add(new PaletteVersion("1_20_10", Bedrock_v594.CODEC.getProtocolVersion(), Collections.emptyMap(), (item, mapping) -> { + // Forward-map 1.20 mappings to 1.20.10 + // 1.20.10+ received parity for concrete and shulker boxes + String id = item.javaIdentifier(); + if (id.endsWith("_concrete") || id.endsWith("_shulker_box")) { + // the first underscore in "_shulker_box" accounts for ignoring "minecraft:shulker_box" + // which is mapped to "minecraft:undyed_shulker_box" + return mapping.withBedrockIdentifier(id); + } + return mapping; + })); GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap(); 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 2efac0d4e..992ae324a 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 @@ -45,6 +45,7 @@ public class BlockMappings implements DefinitionRegistry { GeyserBedrockBlock[] javaToBedrockBlocks; + Map stateDefinitionMap; GeyserBedrockBlock[] bedrockRuntimeMap; BlockDefinition commandBlock; @@ -85,6 +86,14 @@ public class BlockMappings implements DefinitionRegistry { return bedrockRuntimeMap[bedrockId]; } + public GeyserBedrockBlock getDefinition(NbtMap tag) { + if (tag == null) { + return null; + } + + return this.stateDefinitionMap.get(tag); + } + @Override public boolean isRegistered(GeyserBedrockBlock bedrockBlock) { return getDefinition(bedrockBlock.getRuntimeId()) == bedrockBlock; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCommandsTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCommandsTranslator.java index d99313d43..e29570171 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCommandsTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCommandsTranslator.java @@ -79,8 +79,8 @@ public class JavaCommandsTranslator extends PacketTranslator treeData = rootParam.getTree(); + List treeData = rootParam.getTree(); - return treeData.toArray(new CommandParamData[0][]); + return treeData.toArray(new CommandOverloadData[0]); } - return new CommandParamData[0][0]; + return new CommandOverloadData[0]; } /** @@ -272,7 +272,7 @@ public class JavaCommandsTranslator extends PacketTranslator getTree() { - List treeParamData = new ArrayList<>(); + public List getTree() { + List treeParamData = new ArrayList<>(); for (ParamInfo child : children) { // Get the tree from the child - List childTree = child.getTree(); + List childTree = child.getTree(); // Un-pack the tree append the child node to it and push into the list - for (CommandParamData[] subChild : childTree) { + for (CommandOverloadData subChildData : childTree) { + CommandParamData[] subChild = subChildData.getOverloads(); CommandParamData[] tmpTree = new CommandParamData[subChild.length + 1]; tmpTree[0] = child.getParamData(); System.arraycopy(subChild, 0, tmpTree, 1, subChild.length); - treeParamData.add(tmpTree); + treeParamData.add(new CommandOverloadData(false, tmpTree)); } // If we have no more child parameters just the child if (childTree.size() == 0) { - treeParamData.add(new CommandParamData[] { child.getParamData() }); + treeParamData.add(new CommandOverloadData(false, new CommandParamData[] { child.getParamData() })); } } diff --git a/core/src/main/resources/bedrock/block_palette.1_20_10.nbt b/core/src/main/resources/bedrock/block_palette.1_20_10.nbt new file mode 100644 index 0000000000000000000000000000000000000000..3f4618d8d2b9e1bba0d7dda1e148a251fcc4101b GIT binary patch literal 108793 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 Date: Wed, 12 Jul 2023 19:21:29 +0200 Subject: [PATCH 036/344] fix observer mapping (#3970) --- .../geyser/registry/populator/BlockRegistryPopulator.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 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 0c4a156d6..8e30143e8 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 @@ -89,10 +89,12 @@ public final class BlockRegistryPopulator { if (bedrockIdentifier.equals("minecraft:observer")) { int direction = (int) statesBuilder.remove("facing_direction"); statesBuilder.putString("minecraft:facing_direction", switch (direction) { - case 0 -> "east"; - case 1 -> "south"; + case 0 -> "down"; + case 1 -> "up"; case 2 -> "north"; - default -> "west"; + case 3 -> "south"; + case 4 -> "west"; + default -> "east"; }); } return null; From c1d8009b4066c8e09b1b1e42ff7d61e0af8b9898 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Wed, 12 Jul 2023 19:23:07 -0400 Subject: [PATCH 037/344] Fix #3972 --- gradle/libs.versions.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d824c657c..358d6fb8d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,8 +9,8 @@ netty = "4.1.80.Final" guava = "29.0-jre" gson = "2.3.1" # Provided by Spigot 1.8.8 websocket = "1.5.1" -protocol = "3.0.0.Beta1-20230708.191602-100" -protocol-connection = "3.0.0.Beta1-20230708.191602-99" +protocol = "3.0.0.Beta1-20230712.224047-101" +protocol-connection = "3.0.0.Beta1-20230712.224047-100" raknet = "1.0.0.CR1-20230703.195238-9" mcauthlib = "d9d773e" mcprotocollib = "1.20-1-20230607.135651-6" # Temporary hack - needs to be updated to release once publishing is fixed From 396f4e490031e28b1748e2d31d8066d944a428d4 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Mon, 17 Jul 2023 14:45:45 -0400 Subject: [PATCH 038/344] Update latency translator for 1.20.10 (#3993) --- .../org/geysermc/geyser/network/GameProtocol.java | 4 ++++ .../BedrockNetworkStackLatencyTranslator.java | 12 +++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java index abaea2c2b..d15a33315 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java @@ -87,6 +87,10 @@ public final class GameProtocol { return session.getUpstream().getProtocolVersion() < Bedrock_v589.CODEC.getProtocolVersion(); } + public static boolean isPre1_20_10(GeyserSession session) { + return session.getUpstream().getProtocolVersion() < Bedrock_v594.CODEC.getProtocolVersion(); + } + /** * Gets the {@link PacketCodec} for Minecraft: Java Edition. * diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockNetworkStackLatencyTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockNetworkStackLatencyTranslator.java index 7e5643d45..0fe272ea9 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockNetworkStackLatencyTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockNetworkStackLatencyTranslator.java @@ -31,6 +31,7 @@ import org.cloudburstmc.protocol.bedrock.packet.NetworkStackLatencyPacket; import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket; import org.geysermc.floodgate.util.DeviceOs; import org.geysermc.geyser.entity.attribute.GeyserAttributeType; +import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; @@ -50,10 +51,15 @@ public class BedrockNetworkStackLatencyTranslator extends PacketTranslator Date: Wed, 19 Jul 2023 16:59:48 +0200 Subject: [PATCH 039/344] Protocol bump to fix flying issues on 1.20.10 (#4001) --- gradle/libs.versions.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 358d6fb8d..74e623f38 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,8 +9,8 @@ netty = "4.1.80.Final" guava = "29.0-jre" gson = "2.3.1" # Provided by Spigot 1.8.8 websocket = "1.5.1" -protocol = "3.0.0.Beta1-20230712.224047-101" -protocol-connection = "3.0.0.Beta1-20230712.224047-100" +protocol = "3.0.0.Beta1-20230718.000033-102" +protocol-connection = "3.0.0.Beta1-20230718.000033-101" raknet = "1.0.0.CR1-20230703.195238-9" mcauthlib = "d9d773e" mcprotocollib = "1.20-1-20230607.135651-6" # Temporary hack - needs to be updated to release once publishing is fixed From 966270d3c8e855cf77eb7564d5f6cc7a73efd30e Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Fri, 21 Jul 2023 19:25:01 -0400 Subject: [PATCH 040/344] Fix missed swing on 1.20.10 --- .../player/BedrockActionTranslator.java | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java index 5df3d66cc..932fcb96f 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java @@ -31,21 +31,14 @@ import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import com.github.steveice10.mc.protocol.data.game.entity.player.InteractAction; import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction; import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerState; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundInteractPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundPlayerAbilitiesPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundPlayerActionPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundPlayerCommandPacket; +import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.*; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.LevelEvent; import org.cloudburstmc.protocol.bedrock.data.PlayerActionType; import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; -import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket; -import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket; -import org.cloudburstmc.protocol.bedrock.packet.PlayStatusPacket; -import org.cloudburstmc.protocol.bedrock.packet.PlayerActionPacket; -import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket; +import org.cloudburstmc.protocol.bedrock.packet.*; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.ItemFrameEntity; import org.geysermc.geyser.entity.type.player.SessionPlayerEntity; @@ -244,6 +237,19 @@ public class BedrockActionTranslator extends PacketTranslator Date: Sat, 22 Jul 2023 04:25:09 +0200 Subject: [PATCH 041/344] Fix /playsound command by stripping only the Minecraft namespace (#3956) Fixes https://github.com/GeyserMC/Geyser/issues/3953 --- .../org/geysermc/geyser/util/SoundUtils.java | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/util/SoundUtils.java b/core/src/main/java/org/geysermc/geyser/util/SoundUtils.java index 18c37d0b0..b56d9873b 100644 --- a/core/src/main/java/org/geysermc/geyser/util/SoundUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/SoundUtils.java @@ -65,20 +65,20 @@ public final class SoundUtils { * @return a Bedrock sound */ public static String translatePlaySound(String javaIdentifier) { - SoundMapping soundMapping = Registries.SOUNDS.get(trim(javaIdentifier)); + String soundIdentifier = removeMinecraftNamespace(javaIdentifier); + SoundMapping soundMapping = Registries.SOUNDS.get(soundIdentifier); if (soundMapping == null || soundMapping.getPlaysound() == null) { // no mapping GeyserImpl.getInstance().getLogger().debug("[PlaySound] Defaulting to sound server gave us for " + javaIdentifier); - return javaIdentifier; + return soundIdentifier; } return soundMapping.getPlaysound(); } - private static String trim(String identifier) { - // Drop any namespace if applicable - int i = identifier.indexOf(':'); - if (i >= 0) { - return identifier.substring(i + 1); + private static String removeMinecraftNamespace(String identifier) { + // Drop any minecraft namespace if applicable + if (identifier.startsWith("minecraft:")) { + return identifier.substring("minecraft:".length()); } return identifier; } @@ -101,12 +101,12 @@ public final class SoundUtils { * @param pitch the pitch */ public static void playSound(GeyserSession session, Sound javaSound, Vector3f position, float volume, float pitch) { - String packetSound = javaSound.getName(); + String soundIdentifier = removeMinecraftNamespace(javaSound.getName()); - SoundMapping soundMapping = Registries.SOUNDS.get(packetSound); + SoundMapping soundMapping = Registries.SOUNDS.get(soundIdentifier); if (soundMapping == null) { - session.getGeyser().getLogger().debug("[Builtin] Sound mapping for " + packetSound + " not found; assuming custom."); - playSound(session, packetSound, position, volume, pitch); + session.getGeyser().getLogger().debug("[Builtin] Sound mapping for " + soundIdentifier + " not found; assuming custom."); + playSound(session, soundIdentifier, position, volume, pitch); return; } @@ -128,10 +128,10 @@ public final class SoundUtils { LevelSoundEventPacket soundPacket = new LevelSoundEventPacket(); SoundEvent sound = SoundUtils.toSoundEvent(soundMapping.getBedrock()); if (sound == null) { - sound = SoundUtils.toSoundEvent(packetSound); + sound = SoundUtils.toSoundEvent(soundIdentifier); } if (sound == null) { - session.getGeyser().getLogger().debug("[Builtin] Sound for original '" + packetSound + "' to mappings '" + soundMapping.getBedrock() + session.getGeyser().getLogger().debug("[Builtin] Sound for original '" + soundIdentifier + "' to mappings '" + soundMapping.getBedrock() + "' was not a playable level sound, or has yet to be mapped to an enum in SoundEvent."); return; } From 19914a5d7ae5d9148f0bda6f4ae0f6242131e252 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Sat, 22 Jul 2023 17:32:13 -0400 Subject: [PATCH 042/344] Update enchanting table use sound (#4007) --- core/src/main/resources/mappings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/resources/mappings b/core/src/main/resources/mappings index bff5fad32..d44a1e360 160000 --- a/core/src/main/resources/mappings +++ b/core/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit bff5fad3284864fdfad4e7f66aea45cdb20cf401 +Subproject commit d44a1e36059aba666b66e6c545b054c86c1fadac From 3949fb19880f2007647a3d46cc8d1fd89461c1a9 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Tue, 25 Jul 2023 13:33:50 -0400 Subject: [PATCH 043/344] Check if Items of campfire block entity is null (#3986) * Check if items of campfire block entity is null * Use instanceof for Items --- .../block/entity/CampfireBlockEntityTranslator.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/CampfireBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/CampfireBlockEntityTranslator.java index 02dc12f71..5a15ebbb7 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/CampfireBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/CampfireBlockEntityTranslator.java @@ -39,11 +39,12 @@ import org.geysermc.geyser.registry.type.ItemMapping; public class CampfireBlockEntityTranslator extends BlockEntityTranslator { @Override public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) { - ListTag items = tag.get("Items"); - int i = 1; - for (Tag itemTag : items.getValue()) { - builder.put("Item" + i, getItem((CompoundTag) itemTag)); - i++; + if (tag.get("Items") instanceof ListTag items) { + int i = 1; + for (Tag itemTag : items.getValue()) { + builder.put("Item" + i, getItem((CompoundTag) itemTag)); + i++; + } } } From d147ee37dc56b9828d6c47d30feac93b387c46c2 Mon Sep 17 00:00:00 2001 From: chris Date: Sun, 30 Jul 2023 01:51:16 +0200 Subject: [PATCH 044/344] send system chat overlay and actionbar as jukebox_popup messages (#3941) * send actionbar and systemchat overlay messages as jukebox text to avoid clashes with armor/air UI * add explaining comment --- .../protocol/java/JavaSystemChatTranslator.java | 2 +- .../title/JavaSetActionBarTextTranslator.java | 17 ++++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaSystemChatTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaSystemChatTranslator.java index 03660b147..c1f318645 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaSystemChatTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaSystemChatTranslator.java @@ -52,7 +52,7 @@ public class JavaSystemChatTranslator extends PacketTranslator Date: Sun, 30 Jul 2023 16:48:29 -0400 Subject: [PATCH 045/344] Fix double sending ServerboundPlayerActionPacket in creative (both of which Spigot interprets as a BlockBreakEvent) (Fixes #4021) (#3996) --- .../player/BedrockActionTranslator.java | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java index 932fcb96f..f0b2a3526 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java @@ -144,19 +144,22 @@ public class BedrockActionTranslator extends PacketTranslator Date: Mon, 31 Jul 2023 16:56:28 -0400 Subject: [PATCH 046/344] Ignore invalid animations in ClientboundAnimatePacket (#4025) --- .../protocol/java/entity/JavaAnimateTranslator.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaAnimateTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaAnimateTranslator.java index f82c33032..7df6b710c 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaAnimateTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaAnimateTranslator.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.entity; +import com.github.steveice10.mc.protocol.data.game.entity.player.Animation; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundAnimatePacket; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.packet.AnimateEntityPacket; @@ -44,12 +45,17 @@ public class JavaAnimateTranslator extends PacketTranslator Date: Tue, 1 Aug 2023 10:58:59 -0400 Subject: [PATCH 047/344] Cache the Keep Alive timestamp for forwarding ping (#4002) * Cache the (clientbound) Keep Alive timestamp and use that for forwarding ping * Use a Queue of keep alive IDs to handle KeepAlive packets sent in succession * Don't force NetworkStackLatencyTranslator on the session's event loop * Send clientbound NetworkStackLatencyPacket immediately * Avoid sending negative NetworkStackLatencyPackets that are not from the form-image-hack in FormCache * Downsize timestamps that would lead to overflow on the client --- .../geyser/session/GeyserSession.java | 8 +++ .../geyser/session/cache/FormCache.java | 9 ++- .../BedrockNetworkStackLatencyTranslator.java | 59 +++++++++---------- .../java/JavaKeepAliveTranslator.java | 24 +++++++- 4 files changed, 67 insertions(+), 33 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index dba4bd112..8960fb626 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -114,6 +114,7 @@ import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.api.network.RemoteServer; import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.configuration.EmoteOffhandWorkaroundOption; +import org.geysermc.geyser.configuration.GeyserConfiguration; import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.attribute.GeyserAttributeType; import org.geysermc.geyser.entity.type.Entity; @@ -155,6 +156,7 @@ import java.nio.charset.StandardCharsets; import java.time.Instant; import java.util.*; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; @@ -564,6 +566,12 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { @Setter private ScheduledFuture mountVehicleScheduledFuture = null; + /** + * A cache of IDs from ClientboundKeepAlivePackets that have been sent to the Bedrock client, but haven't been returned to the server. + * Only used if {@link GeyserConfiguration#isForwardPlayerPing()} is enabled. + */ + private final Queue keepAliveCache = new ConcurrentLinkedQueue<>(); + private MinecraftProtocol protocol; public GeyserSession(GeyserImpl geyser, BedrockServerSession bedrockServerSession, EventLoop eventLoop) { diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/FormCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/FormCache.java index 6ba6a1b7e..3f7df97c1 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/FormCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/FormCache.java @@ -42,6 +42,13 @@ import java.util.concurrent.atomic.AtomicInteger; @RequiredArgsConstructor public class FormCache { + + /** + * The magnitude of this doesn't actually matter, but it must be negative so that + * BedrockNetworkStackLatencyTranslator can detect the hack. + */ + private static final long MAGIC_FORM_IMAGE_HACK_TIMESTAMP = -1234567890L; + private final FormDefinitions formDefinitions = FormDefinitions.instance(); private final AtomicInteger formIdCounter = new AtomicInteger(0); private final Int2ObjectMap
forms = new Int2ObjectOpenHashMap<>(); @@ -73,7 +80,7 @@ public class FormCache { if (form instanceof SimpleForm) { NetworkStackLatencyPacket latencyPacket = new NetworkStackLatencyPacket(); latencyPacket.setFromServer(true); - latencyPacket.setTimestamp(-System.currentTimeMillis()); + latencyPacket.setTimestamp(MAGIC_FORM_IMAGE_HACK_TIMESTAMP); session.scheduleInEventLoop( () -> session.sendUpstreamPacket(latencyPacket), 500, TimeUnit.MILLISECONDS diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockNetworkStackLatencyTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockNetworkStackLatencyTranslator.java index 0fe272ea9..1ccd5ced9 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockNetworkStackLatencyTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockNetworkStackLatencyTranslator.java @@ -29,9 +29,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundKe import org.cloudburstmc.protocol.bedrock.data.AttributeData; import org.cloudburstmc.protocol.bedrock.packet.NetworkStackLatencyPacket; import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket; -import org.geysermc.floodgate.util.DeviceOs; import org.geysermc.geyser.entity.attribute.GeyserAttributeType; -import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; @@ -47,42 +45,43 @@ public class BedrockNetworkStackLatencyTranslator extends PacketTranslator 0) { + if (packet.getTimestamp() >= 0) { if (session.getGeyser().getConfig().isForwardPlayerPing()) { - ServerboundKeepAlivePacket keepAlivePacket = new ServerboundKeepAlivePacket(pingId); + // use our cached value because + // a) bedrock can be inaccurate with the value returned + // b) playstation replies with a different magnitude than other platforms + // c) 1.20.10 and later reply with a different magnitude + Long keepAliveId = session.getKeepAliveCache().poll(); + if (keepAliveId == null) { + session.getGeyser().getLogger().debug("Received a latency packet that we don't have a KeepAlive for: " + packet); + return; + } + + ServerboundKeepAlivePacket keepAlivePacket = new ServerboundKeepAlivePacket(keepAliveId); session.sendDownstreamPacket(keepAlivePacket); } return; } - // Hack to fix the url image loading bug - UpdateAttributesPacket attributesPacket = new UpdateAttributesPacket(); - attributesPacket.setRuntimeEntityId(session.getPlayerEntity().getGeyserId()); + session.scheduleInEventLoop(() -> { + // Hack to fix the url image loading bug + UpdateAttributesPacket attributesPacket = new UpdateAttributesPacket(); + attributesPacket.setRuntimeEntityId(session.getPlayerEntity().getGeyserId()); - AttributeData attribute = session.getPlayerEntity().getAttributes().get(GeyserAttributeType.EXPERIENCE_LEVEL); - if (attribute != null) { - attributesPacket.setAttributes(Collections.singletonList(attribute)); - } else { - attributesPacket.setAttributes(Collections.singletonList(GeyserAttributeType.EXPERIENCE_LEVEL.getAttribute(0))); - } + AttributeData attribute = session.getPlayerEntity().getAttributes().get(GeyserAttributeType.EXPERIENCE_LEVEL); + if (attribute != null) { + attributesPacket.setAttributes(Collections.singletonList(attribute)); + } else { + attributesPacket.setAttributes(Collections.singletonList(GeyserAttributeType.EXPERIENCE_LEVEL.getAttribute(0))); + } - session.scheduleInEventLoop(() -> session.sendUpstreamPacket(attributesPacket), - 500, TimeUnit.MILLISECONDS); + session.sendUpstreamPacket(attributesPacket); + }, 500, TimeUnit.MILLISECONDS); + } + + @Override + public boolean shouldExecuteInEventLoop() { + return false; } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaKeepAliveTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaKeepAliveTranslator.java index 41eb5062a..dc7b7f316 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaKeepAliveTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaKeepAliveTranslator.java @@ -42,10 +42,30 @@ public class JavaKeepAliveTranslator extends PacketTranslator 1e10) { + timestamp /= 10; + } + NetworkStackLatencyPacket latencyPacket = new NetworkStackLatencyPacket(); latencyPacket.setFromServer(true); - latencyPacket.setTimestamp(packet.getPingId() * 1000); - session.sendUpstreamPacket(latencyPacket); + latencyPacket.setTimestamp(timestamp); + session.sendUpstreamPacketImmediately(latencyPacket); } @Override From 176ef83ed148935b2444fb238df864cd6ba9e6e3 Mon Sep 17 00:00:00 2001 From: chris Date: Mon, 7 Aug 2023 02:15:13 +0200 Subject: [PATCH 048/344] Fix fox height/width (#4039) --- .../main/java/org/geysermc/geyser/entity/EntityDefinitions.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java index a8d35b6f3..a88eff111 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java +++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java @@ -788,7 +788,7 @@ public final class EntityDefinitions { .build(); FOX = EntityDefinition.inherited(FoxEntity::new, ageableEntityBase) .type(EntityType.FOX) - .height(0.5f).width(1.25f) + .height(0.7f).width(0.6f) .addTranslator(MetadataType.INT, FoxEntity::setFoxVariant) .addTranslator(MetadataType.BYTE, FoxEntity::setFoxFlags) .addTranslator(null) // Trusted player 1 From b1f04a9012e9c64c9931a86f7045aa4cebb769c4 Mon Sep 17 00:00:00 2001 From: chris Date: Mon, 7 Aug 2023 02:22:05 +0200 Subject: [PATCH 049/344] Allow custom unusable-space blocker item (#4038) * Allow the "unusable-space-block" to be a custom item (specified by bedrock identifier) * add space for log error * don't use ugly atomic reference --- .../geysermc/geyser/util/InventoryUtils.java | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java index 55af9eb11..728f03def 100644 --- a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java @@ -208,12 +208,21 @@ public class InventoryUtils { private static ItemDefinition getUnusableSpaceBlockDefinition(int protocolVersion) { String unusableSpaceBlock = GeyserImpl.getInstance().getConfig().getUnusableSpaceBlock(); - ItemMapping unusableSpaceBlockID = Registries.ITEMS.forVersion(protocolVersion).getMapping(unusableSpaceBlock); - if (unusableSpaceBlockID != null) { - return unusableSpaceBlockID.getBedrockDefinition(); - } else { - GeyserImpl.getInstance().getLogger().error("Invalid value" + unusableSpaceBlock + ". Resorting to barrier block."); + ItemDefinition itemDefinition = null; + + // looping through all the items to find the one with the specified Bedrock identifier + for (ItemDefinition definition : Registries.ITEMS.forVersion(protocolVersion).getItemDefinitions().values()) { + if (definition.getIdentifier().equals(unusableSpaceBlock)) { + itemDefinition = definition; + break; + } + } + + if (itemDefinition == null) { + GeyserImpl.getInstance().getLogger().error("Invalid value " + unusableSpaceBlock + ". Resorting to barrier block."); return Registries.ITEMS.forVersion(protocolVersion).getStoredItems().barrier().getBedrockDefinition(); + } else { + return itemDefinition; } } From 2361f587dabf70cac333308d90aa09df0e71fced Mon Sep 17 00:00:00 2001 From: chris Date: Mon, 7 Aug 2023 02:39:27 +0200 Subject: [PATCH 050/344] Don't send softEnumPackets when command suggestions are false (#4037) * Don't send SoftEnums if command suggestions are set to false, add system property to not send team suggestions * address review --- .../java/org/geysermc/geyser/scoreboard/Scoreboard.java | 6 ++++-- .../java/org/geysermc/geyser/session/GeyserSession.java | 4 ++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/scoreboard/Scoreboard.java b/core/src/main/java/org/geysermc/geyser/scoreboard/Scoreboard.java index 5a70fddf5..c49e8afc4 100644 --- a/core/src/main/java/org/geysermc/geyser/scoreboard/Scoreboard.java +++ b/core/src/main/java/org/geysermc/geyser/scoreboard/Scoreboard.java @@ -52,6 +52,7 @@ import static org.geysermc.geyser.scoreboard.UpdateType.*; public final class Scoreboard { private static final boolean SHOW_SCOREBOARD_LOGS = Boolean.parseBoolean(System.getProperty("Geyser.ShowScoreboardLogs", "true")); + private static final boolean ADD_TEAM_SUGGESTIONS = Boolean.parseBoolean(System.getProperty("Geyser.AddTeamSuggestions", "true")); private final GeyserSession session; private final GeyserLogger logger; @@ -150,8 +151,9 @@ public final class Scoreboard { teams.put(teamName, team); // Update command parameters - is safe to send even if the command enum doesn't exist on the client (as of 1.19.51) - session.addCommandEnum("Geyser_Teams", team.getId()); - + if (ADD_TEAM_SUGGESTIONS) { + session.addCommandEnum("Geyser_Teams", team.getId()); + } return team; } diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 8960fb626..721fb0dfe 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -2008,6 +2008,10 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { } private void softEnumPacket(String name, SoftEnumUpdateType type, String enums) { + // There is no need to send command enums if command suggestions are disabled + if (!this.geyser.getConfig().isCommandSuggestions()) { + return; + } UpdateSoftEnumPacket packet = new UpdateSoftEnumPacket(); packet.setType(type); packet.setSoftEnum(new CommandEnumData(name, Collections.singletonMap(enums, Collections.emptySet()), true)); From 941275586ddebbd578dbc9256eb28e6eda06ec01 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Mon, 7 Aug 2023 08:01:10 -0700 Subject: [PATCH 051/344] Use chunk version 9 (#4040) Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .../geyser/level/chunk/GeyserChunkSection.java | 17 +++++++++++------ .../JavaLevelChunkWithLightTranslator.java | 8 ++++---- .../org/geysermc/geyser/util/ChunkUtils.java | 2 +- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/level/chunk/GeyserChunkSection.java b/core/src/main/java/org/geysermc/geyser/level/chunk/GeyserChunkSection.java index 14a74fb99..58f61fb4a 100644 --- a/core/src/main/java/org/geysermc/geyser/level/chunk/GeyserChunkSection.java +++ b/core/src/main/java/org/geysermc/geyser/level/chunk/GeyserChunkSection.java @@ -30,16 +30,19 @@ import org.cloudburstmc.protocol.common.util.Preconditions; public class GeyserChunkSection { - private static final int CHUNK_SECTION_VERSION = 8; + // As of at least 1.19.80 + private static final int CHUNK_SECTION_VERSION = 9; private final BlockStorage[] storage; + private final int sectionY; - public GeyserChunkSection(int airBlockId) { - this(new BlockStorage[]{new BlockStorage(airBlockId), new BlockStorage(airBlockId)}); + public GeyserChunkSection(int airBlockId, int sectionY) { + this(new BlockStorage[]{new BlockStorage(airBlockId), new BlockStorage(airBlockId)}, sectionY); } - public GeyserChunkSection(BlockStorage[] storage) { + public GeyserChunkSection(BlockStorage[] storage, int sectionY) { this.storage = storage; + this.sectionY = sectionY; } public int getFullBlock(int x, int y, int z, int layer) { @@ -57,6 +60,8 @@ public class GeyserChunkSection { public void writeToNetwork(ByteBuf buffer) { buffer.writeByte(CHUNK_SECTION_VERSION); buffer.writeByte(this.storage.length); + // Required for chunk version 9+ + buffer.writeByte(this.sectionY); for (BlockStorage blockStorage : this.storage) { blockStorage.writeToNetwork(buffer); } @@ -83,12 +88,12 @@ public class GeyserChunkSection { return true; } - public GeyserChunkSection copy() { + public GeyserChunkSection copy(int sectionY) { BlockStorage[] storage = new BlockStorage[this.storage.length]; for (int i = 0; i < storage.length; i++) { storage[i] = this.storage[i].copy(); } - return new GeyserChunkSection(storage); + return new GeyserChunkSection(storage, sectionY); } public static int blockPosition(int x, int y, int z) { 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 a6d5fe09c..b4d9c1bf7 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 @@ -132,7 +132,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator Date: Tue, 8 Aug 2023 18:18:43 +0100 Subject: [PATCH 052/344] Update Geyser download URL (#4045) * Update Geyser download URL * Use existing constant instead of duplicating string --- core/src/main/java/org/geysermc/geyser/Constants.java | 2 +- .../org/geysermc/geyser/command/defaults/VersionCommand.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/Constants.java b/core/src/main/java/org/geysermc/geyser/Constants.java index 9ae2109e2..12e8b0d8c 100644 --- a/core/src/main/java/org/geysermc/geyser/Constants.java +++ b/core/src/main/java/org/geysermc/geyser/Constants.java @@ -36,7 +36,7 @@ public final class Constants { public static final String FLOODGATE_DOWNLOAD_LOCATION = "https://ci.opencollab.dev/job/GeyserMC/job/Floodgate/job/master/"; - public static final String GEYSER_DOWNLOAD_LOCATION = "https://ci.geysermc.org"; + public static final String GEYSER_DOWNLOAD_LOCATION = "https://geysermc.org/download"; public static final String UPDATE_PERMISSION = "geyser.update"; static final String SAVED_REFRESH_TOKEN_FILE = "saved-refresh-tokens.json"; diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/VersionCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/VersionCommand.java index 378e43ee0..b263d6727 100644 --- a/core/src/main/java/org/geysermc/geyser/command/defaults/VersionCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/VersionCommand.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.command.defaults; import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; +import org.geysermc.geyser.Constants; import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.command.GeyserCommand; @@ -84,7 +85,7 @@ public class VersionCommand extends GeyserCommand { sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.version.no_updates", sender.locale())); } else { sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.version.outdated", - sender.locale(), (latestBuildNum - buildNum), "https://ci.geysermc.org/")); + sender.locale(), (latestBuildNum - buildNum), Constants.GEYSER_DOWNLOAD_LOCATION)); } } else { throw new AssertionError("buildNumber missing"); From a99d2bcca886706dfd005e786c4b0fd6583e90d4 Mon Sep 17 00:00:00 2001 From: Tim203 Date: Tue, 15 Aug 2023 17:52:07 +0200 Subject: [PATCH 053/344] Common module should still target Java 8 --- common/build.gradle.kts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/common/build.gradle.kts b/common/build.gradle.kts index db3fe3a77..efba08c8d 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -6,3 +6,9 @@ dependencies { api(libs.cumulus) api(libs.gson) } + +indra { + javaVersions { + target(8) + } +} From 706d1b96270df004b8dda74f0611e28d689747ff Mon Sep 17 00:00:00 2001 From: chris Date: Thu, 17 Aug 2023 04:42:17 +0200 Subject: [PATCH 054/344] Fix smithing tables on pre-1.20 servers (#4056) --- .../inventory/item/StoredItemMappings.java | 6 +- .../geyser/registry/type/ItemMappings.java | 21 ++- .../geyser/session/GeyserSession.java | 8 + .../inventory/OldSmithingTableTranslator.java | 147 ++++++++++++++++++ .../java/JavaUpdateRecipesTranslator.java | 69 ++++++-- .../inventory/JavaOpenScreenTranslator.java | 11 ++ .../geysermc/geyser/util/InventoryUtils.java | 16 +- 7 files changed, 252 insertions(+), 26 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/translator/inventory/OldSmithingTableTranslator.java diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java b/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java index 42b9ae1a0..16fd7cde6 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java @@ -45,11 +45,12 @@ public class StoredItemMappings { private final ItemMapping barrier; private final ItemMapping compass; private final ItemMapping crossbow; + private final ItemMapping egg; private final ItemMapping glassBottle; private final ItemMapping milkBucket; private final ItemMapping powderSnowBucket; - private final ItemMapping egg; private final ItemMapping shield; + private final ItemMapping upgradeTemplate; private final ItemMapping wheat; private final ItemMapping writableBook; @@ -59,11 +60,12 @@ public class StoredItemMappings { this.barrier = load(itemMappings, Items.BARRIER); this.compass = load(itemMappings, Items.COMPASS); this.crossbow = load(itemMappings, Items.CROSSBOW); + this.egg = load(itemMappings, Items.EGG); this.glassBottle = load(itemMappings, Items.GLASS_BOTTLE); this.milkBucket = load(itemMappings, Items.MILK_BUCKET); this.powderSnowBucket = load(itemMappings, Items.POWDER_SNOW_BUCKET); - this.egg = load(itemMappings, Items.EGG); this.shield = load(itemMappings, Items.SHIELD); + this.upgradeTemplate = load(itemMappings, Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE); this.wheat = load(itemMappings, Items.WHEAT); this.writableBook = load(itemMappings, Items.WRITABLE_BOOK); } 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 0b45d881a..65cc28420 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 @@ -29,6 +29,8 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import lombok.Builder; import lombok.Value; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; @@ -39,7 +41,6 @@ import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.item.type.PotionItem; -import javax.annotation.Nonnull; import java.util.List; import java.util.Map; import java.util.Set; @@ -77,7 +78,7 @@ public class ItemMappings implements DefinitionRegistry { * @param itemStack the itemstack * @return an item entry from the given java edition identifier */ - @Nonnull + @NonNull public ItemMapping getMapping(ItemStack itemStack) { return this.getMapping(itemStack.getId()); } @@ -89,11 +90,12 @@ public class ItemMappings implements DefinitionRegistry { * @param javaId the id * @return an item entry from the given java edition identifier */ - @Nonnull + @NonNull public ItemMapping getMapping(int javaId) { return javaId >= 0 && javaId < this.items.length ? this.items[javaId] : ItemMapping.AIR; } + @Nullable public ItemMapping getMapping(Item javaItem) { return getMapping(javaItem.javaIdentifier()); } @@ -105,6 +107,7 @@ public class ItemMappings implements DefinitionRegistry { * @param javaIdentifier the block state identifier * @return an item entry from the given java edition identifier */ + @Nullable public ItemMapping getMapping(String javaIdentifier) { return this.cachedJavaMappings.computeIfAbsent(javaIdentifier, key -> { for (ItemMapping mapping : this.items) { @@ -122,6 +125,7 @@ public class ItemMappings implements DefinitionRegistry { * @param data the item data * @return an item entry from the given item data */ + @NonNull public ItemMapping getMapping(ItemData data) { ItemDefinition definition = data.getDefinition(); if (ItemDefinition.AIR.equals(definition)) { @@ -158,11 +162,22 @@ public class ItemMappings implements DefinitionRegistry { return ItemMapping.AIR; } + @Nullable @Override public ItemDefinition getDefinition(int bedrockId) { return this.itemDefinitions.get(bedrockId); } + @Nullable + public ItemDefinition getDefinition(String bedrockIdentifier) { + for (ItemDefinition itemDefinition : this.itemDefinitions.values()) { + if (itemDefinition.getIdentifier().equals(bedrockIdentifier)) { + return itemDefinition; + } + } + return null; + } + @Override public boolean isRegistered(ItemDefinition definition) { return getDefinition(definition.getRuntimeId()) == definition; diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 721fb0dfe..e09cff9e4 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -425,6 +425,14 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { @Setter private boolean emulatePost1_18Logic = true; + /** + * Whether to emulate pre-1.20 smithing table behavior. + * Adapts ViaVersion's furnace UI to one Bedrock can use. + * See {@link org.geysermc.geyser.translator.inventory.OldSmithingTableTranslator}. + */ + @Setter + private boolean oldSmithingTable = false; + /** * The current attack speed of the player. Used for sending proper cooldown timings. * Setting a default fixes cooldowns not showing up on a fresh world. diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/OldSmithingTableTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/OldSmithingTableTranslator.java new file mode 100644 index 000000000..5f08f1b8a --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/OldSmithingTableTranslator.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2019-2023 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.translator.inventory; + +import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId; +import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; +import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; +import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; +import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequest; +import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData; +import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.DropAction; +import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.ItemStackRequestAction; +import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.PlaceAction; +import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.SwapAction; +import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.TakeAction; +import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.response.ItemStackResponse; +import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket; +import org.geysermc.geyser.inventory.BedrockContainerSlot; +import org.geysermc.geyser.inventory.Inventory; +import org.geysermc.geyser.inventory.updater.UIInventoryUpdater; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.util.InventoryUtils; + +import java.util.function.IntFunction; + +/** + * Translator for smithing tables for pre-1.20 servers. + * This adapts ViaVersion's furnace ui to the 1.20+ smithing table; with the addition of a fake smithing template so Bedrock clients can use it. + */ +public class OldSmithingTableTranslator extends AbstractBlockInventoryTranslator { + + public static final OldSmithingTableTranslator INSTANCE = new OldSmithingTableTranslator(); + + private static final IntFunction UPGRADE_TEMPLATE = InventoryUtils.getUpgradeTemplate(); + + private OldSmithingTableTranslator() { + super(3, "minecraft:smithing_table", ContainerType.SMITHING_TABLE, UIInventoryUpdater.INSTANCE); + } + + @Override + public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) { + return switch (slotInfoData.getContainer()) { + case SMITHING_TABLE_INPUT -> 0; + case SMITHING_TABLE_MATERIAL -> 1; + case SMITHING_TABLE_RESULT, CREATED_OUTPUT -> 2; + default -> super.bedrockSlotToJava(slotInfoData); + }; + } + + @Override + public BedrockContainerSlot javaSlotToBedrockContainer(int slot) { + return switch (slot) { + case 0 -> new BedrockContainerSlot(ContainerSlotType.SMITHING_TABLE_INPUT, 51); + case 1 -> new BedrockContainerSlot(ContainerSlotType.SMITHING_TABLE_MATERIAL, 52); + case 2 -> new BedrockContainerSlot(ContainerSlotType.SMITHING_TABLE_RESULT, 50); + default -> super.javaSlotToBedrockContainer(slot); + }; + } + + @Override + public int javaSlotToBedrock(int slot) { + return switch (slot) { + case 0 -> 51; + case 1 -> 52; + case 2 -> 50; + default -> super.javaSlotToBedrock(slot); + }; + } + + @Override + public boolean shouldHandleRequestFirst(ItemStackRequestAction action, Inventory inventory) { + return true; + } + + @Override + protected ItemStackResponse translateSpecialRequest(GeyserSession session, Inventory inventory, ItemStackRequest request) { + for (var action: request.getActions()) { + switch (action.getType()) { + case DROP -> { + if (isInvalidAction(((DropAction) action).getSource())) { + return rejectRequest(request, false); + } + } + case TAKE -> { + if (isInvalidAction(((TakeAction) action).getSource()) || + isInvalidAction(((TakeAction) action).getDestination())) { + return rejectRequest(request, false); + } + } + case SWAP -> { + if (isInvalidAction(((SwapAction) action).getSource()) || + isInvalidAction(((SwapAction) action).getDestination())) { + return rejectRequest(request, false); + } + } + case PLACE -> { + if (isInvalidAction(((PlaceAction) action).getSource()) || + isInvalidAction(((PlaceAction) action).getDestination())) { + return rejectRequest(request, false); + } + } + } + } + // Allow everything else that doesn't involve the fake template + return super.translateRequest(session, inventory, request); + } + + private boolean isInvalidAction(ItemStackRequestSlotData slotData) { + return slotData.getContainer().equals(ContainerSlotType.SMITHING_TABLE_TEMPLATE); + } + + @Override + public void openInventory(GeyserSession session, Inventory inventory) { + super.openInventory(session, inventory); + + // pre-1.20 server has no concept of templates, but we are working with a 1.20 client + // put a fake netherite upgrade template in the template slot otherwise the client doesn't recognize a valid recipe + InventorySlotPacket slotPacket = new InventorySlotPacket(); + slotPacket.setContainerId(ContainerId.UI); + slotPacket.setSlot(53); + slotPacket.setItem(UPGRADE_TEMPLATE.apply(session.getUpstream().getProtocolVersion())); + session.sendUpstreamPacket(slotPacket); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java index bef6b9884..1af0ff814 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java @@ -46,6 +46,7 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.descriptor.DefaultDescri import org.cloudburstmc.protocol.bedrock.data.inventory.descriptor.ItemDescriptorWithCount; import org.cloudburstmc.protocol.bedrock.packet.CraftingDataPacket; import org.cloudburstmc.protocol.bedrock.packet.TrimDataPacket; +import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.inventory.recipe.GeyserRecipe; import org.geysermc.geyser.inventory.recipe.GeyserShapedRecipe; import org.geysermc.geyser.inventory.recipe.GeyserShapelessRecipe; @@ -81,11 +82,24 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator NETHERITE_UPGRADES = List.of( + "minecraft:netherite_sword", + "minecraft:netherite_shovel", + "minecraft:netherite_pickaxe", + "minecraft:netherite_axe", + "minecraft:netherite_hoe", + "minecraft:netherite_helmet", + "minecraft:netherite_chestplate", + "minecraft:netherite_leggings", + "minecraft:netherite_boots" + ); + @Override public void translate(GeyserSession session, ClientboundUpdateRecipesPacket packet) { Map> recipeTypes = Registries.CRAFTING_DATA.forVersion(session.getUpstream().getProtocolVersion()); // Get the last known network ID (first used for the pregenerated recipes) and increment from there. int netId = InventoryUtils.LAST_RECIPE_NET_ID + 1; + boolean sendTrimRecipes = false; Int2ObjectMap recipeMap = new Int2ObjectOpenHashMap<>(Registries.RECIPES.forVersion(session.getUpstream().getProtocolVersion())); Int2ObjectMap> unsortedStonecutterData = new Int2ObjectOpenHashMap<>(); @@ -168,6 +182,7 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator { + sendTrimRecipes = true; // ignored currently - see below } default -> { @@ -214,23 +229,28 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator getSmithingTransformRecipes(GeyserSession session) { + List recipes = new ArrayList<>(); + ItemMapping template = session.getItemMappings().getStoredItems().upgradeTemplate(); + + for (String identifier : NETHERITE_UPGRADES) { + recipes.add(org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.SmithingTransformRecipeData.of(identifier + "_smithing", + getDescriptorFromId(session, template.getBedrockIdentifier()), + getDescriptorFromId(session, identifier.replace("netherite", "diamond")), + getDescriptorFromId(session, "minecraft:netherite_ingot"), + ItemData.builder().definition(Objects.requireNonNull(session.getItemMappings().getDefinition(identifier))).count(1).build(), + "smithing_table", + session.getLastRecipeNetId().getAndIncrement())); + } + return recipes; + } + + private ItemDescriptorWithCount getDescriptorFromId(GeyserSession session, String bedrockId) { + ItemDefinition bedrockDefinition = session.getItemMappings().getDefinition(bedrockId); + if (bedrockDefinition != null) { + return ItemDescriptorWithCount.fromItem(ItemData.builder().definition(bedrockDefinition).count(1).build()); + } + GeyserImpl.getInstance().getLogger().debug("Unable to find item with identifier " + bedrockId); + return ItemDescriptorWithCount.EMPTY; + } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaOpenScreenTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaOpenScreenTranslator.java index 8730d5ac1..fd733773e 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaOpenScreenTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaOpenScreenTranslator.java @@ -25,11 +25,14 @@ package org.geysermc.geyser.translator.protocol.java.inventory; +import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.inventory.ClientboundOpenScreenPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClosePacket; +import net.kyori.adventure.text.Component; import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.inventory.InventoryTranslator; +import org.geysermc.geyser.translator.inventory.OldSmithingTableTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.translator.text.MessageTranslator; @@ -38,6 +41,8 @@ import org.geysermc.geyser.util.InventoryUtils; @Translator(packet = ClientboundOpenScreenPacket.class) public class JavaOpenScreenTranslator extends PacketTranslator { + private static final Component SMITHING_TABLE_COMPONENT = Component.translatable("container.upgrade"); + @Override public void translate(GeyserSession session, ClientboundOpenScreenPacket packet) { if (packet.getContainerId() == 0) { @@ -46,6 +51,12 @@ public class JavaOpenScreenTranslator extends PacketTranslator getUpgradeTemplate() { + return protocolVersion -> ItemData.builder() + .definition(Registries.ITEMS.forVersion(protocolVersion).getStoredItems().upgradeTemplate().getBedrockDefinition()) + .count(1).build(); + } + /** * See {@link #findOrCreateItem(GeyserSession, String)}. This is for finding a specified {@link ItemStack}. * From 661a9b4741a2a8a274313dd63526cc7f86e8afe1 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Thu, 17 Aug 2023 23:07:55 -0400 Subject: [PATCH 055/344] Improvements to MessageTranslator (#3803) * Renames for clarity and refactor convertToJavaMessage * Bump adventure, velociy. Require CharacterAndFormat in MessageTranslator * Fix deprecations related to DummyLegacyHoverEventSerializer * Patch serialization of ScoreComponent until Adventure 1.15.0 --- .../geyser/inventory/AnvilContainer.java | 2 +- .../updater/AnvilInventoryUpdater.java | 2 +- .../text/DummyLegacyHoverEventSerializer.java | 6 +- .../CommandBlockBlockEntityTranslator.java | 2 +- .../translator/text/MessageTranslator.java | 94 +++++++++---------- .../chat/MessageTranslatorTest.java | 16 ++-- gradle/libs.versions.toml | 6 +- 7 files changed, 63 insertions(+), 65 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/inventory/AnvilContainer.java b/core/src/main/java/org/geysermc/geyser/inventory/AnvilContainer.java index 471aff8b2..5b0800e44 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/AnvilContainer.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/AnvilContainer.java @@ -75,7 +75,7 @@ public class AnvilContainer extends Container { String originalName = ItemUtils.getCustomName(getInput().getNbt()); - String plainOriginalName = MessageTranslator.convertToPlainText(originalName, session.locale()); + String plainOriginalName = MessageTranslator.convertToPlainTextLenient(originalName, session.locale()); String plainNewName = MessageTranslator.convertToPlainText(rename); if (!plainOriginalName.equals(plainNewName)) { // Strip out formatting since Java Edition does not allow it diff --git a/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java b/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java index c92724100..ea4ef674b 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java @@ -118,7 +118,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater { // Changing the item in the input slot resets the name field on Bedrock, but // does not result in a FilterTextPacket - String originalName = MessageTranslator.convertToPlainText(ItemUtils.getCustomName(input.getNbt()), session.locale()); + String originalName = MessageTranslator.convertToPlainTextLenient(ItemUtils.getCustomName(input.getNbt()), session.locale()); ServerboundRenameItemPacket renameItemPacket = new ServerboundRenameItemPacket(originalName); session.sendDownstreamPacket(renameItemPacket); diff --git a/core/src/main/java/org/geysermc/geyser/text/DummyLegacyHoverEventSerializer.java b/core/src/main/java/org/geysermc/geyser/text/DummyLegacyHoverEventSerializer.java index fdce1f879..e934fc124 100644 --- a/core/src/main/java/org/geysermc/geyser/text/DummyLegacyHoverEventSerializer.java +++ b/core/src/main/java/org/geysermc/geyser/text/DummyLegacyHoverEventSerializer.java @@ -28,7 +28,7 @@ package org.geysermc.geyser.text; import net.kyori.adventure.key.Key; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.event.HoverEvent; -import net.kyori.adventure.text.serializer.gson.LegacyHoverEventSerializer; +import net.kyori.adventure.text.serializer.json.LegacyHoverEventSerializer; import net.kyori.adventure.util.Codec; import org.jetbrains.annotations.NotNull; @@ -40,9 +40,9 @@ public final class DummyLegacyHoverEventSerializer implements LegacyHoverEventSe private final HoverEvent.ShowItem dummyShowItem; public DummyLegacyHoverEventSerializer() { - dummyShowEntity = HoverEvent.ShowEntity.of(Key.key("geysermc", "dummyshowitem"), + dummyShowEntity = HoverEvent.ShowEntity.showEntity(Key.key("geysermc", "dummyshowitem"), UUID.nameUUIDFromBytes("entitiesareprettyneat".getBytes(StandardCharsets.UTF_8))); - dummyShowItem = HoverEvent.ShowItem.of(Key.key("geysermc", "dummyshowentity"), 0); + dummyShowItem = HoverEvent.ShowItem.showItem(Key.key("geysermc", "dummyshowentity"), 0); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/CommandBlockBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/CommandBlockBlockEntityTranslator.java index 9e743667f..36345394b 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/CommandBlockBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/CommandBlockBlockEntityTranslator.java @@ -43,7 +43,7 @@ public class CommandBlockBlockEntityTranslator extends BlockEntityTranslator imp // Java and Bedrock values builder.put("conditionMet", ((ByteTag) tag.get("conditionMet")).getValue()); builder.put("auto", ((ByteTag) tag.get("auto")).getValue()); - builder.put("CustomName", MessageTranslator.convertMessage(((StringTag) tag.get("CustomName")).getValue())); + builder.put("CustomName", MessageTranslator.convertJsonMessage(((StringTag) tag.get("CustomName")).getValue())); builder.put("powered", ((ByteTag) tag.get("powered")).getValue()); builder.put("Command", ((StringTag) tag.get("Command")).getValue()); builder.put("SuccessCount", ((IntTag) tag.get("SuccessCount")).getValue()); diff --git a/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java index dd069c5f5..5f811ab49 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java @@ -28,7 +28,9 @@ package org.geysermc.geyser.translator.text; import com.github.steveice10.mc.protocol.data.DefaultComponentSerializer; import com.github.steveice10.mc.protocol.data.game.scoreboard.TeamColor; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.ScoreComponent; import net.kyori.adventure.text.TranslatableComponent; +import net.kyori.adventure.text.flattener.ComponentFlattener; import net.kyori.adventure.text.format.TextColor; import net.kyori.adventure.text.renderer.TranslatableComponentRenderer; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; @@ -50,8 +52,8 @@ public class MessageTranslator { // Possible TODO: replace the legacy hover event serializer with an empty one since we have no use for hover events private static final GsonComponentSerializer GSON_SERIALIZER; - private static final LegacyComponentSerializer LEGACY_SERIALIZER; - private static final String ALL_COLORS; + private static final LegacyComponentSerializer BEDROCK_SERIALIZER; + private static final String BEDROCK_COLORS; // Store team colors for player names private static final Map TEAM_COLORS = new EnumMap<>(TeamColor.class); @@ -99,47 +101,43 @@ public class MessageTranslator { // Tell MCProtocolLib to use this serializer, too. DefaultComponentSerializer.set(GSON_SERIALIZER); - LegacyComponentSerializer legacySerializer; - String allColors; - try { - Class.forName("net.kyori.adventure.text.serializer.legacy.CharacterAndFormat"); + // Customize the formatting characters of our legacy serializer for bedrock edition + List formats = new ArrayList<>(CharacterAndFormat.defaults()); + // The following two do not yet exist on Bedrock - https://bugs.mojang.com/browse/MCPE-41729 + formats.remove(CharacterAndFormat.STRIKETHROUGH); + formats.remove(CharacterAndFormat.UNDERLINED); - List formats = new ArrayList<>(CharacterAndFormat.defaults()); - // The following two do not yet exist on Bedrock - https://bugs.mojang.com/browse/MCPE-41729 - formats.remove(CharacterAndFormat.STRIKETHROUGH); - formats.remove(CharacterAndFormat.UNDERLINED); + formats.add(CharacterAndFormat.characterAndFormat('g', TextColor.color(221, 214, 5))); // Minecoin Gold + // Add the new characters implemented in 1.19.80 + formats.add(CharacterAndFormat.characterAndFormat('h', TextColor.color(227, 212, 209))); // Quartz + formats.add(CharacterAndFormat.characterAndFormat('i', TextColor.color(206, 202, 202))); // Iron + formats.add(CharacterAndFormat.characterAndFormat('j', TextColor.color(68, 58, 59))); // Netherite + formats.add(CharacterAndFormat.characterAndFormat('m', TextColor.color(151, 22, 7))); // Redstone + formats.add(CharacterAndFormat.characterAndFormat('n', TextColor.color(180, 104, 77))); // Copper + formats.add(CharacterAndFormat.characterAndFormat('p', TextColor.color(222, 177, 45))); // Gold + formats.add(CharacterAndFormat.characterAndFormat('q', TextColor.color(17, 160, 54))); // Emerald + formats.add(CharacterAndFormat.characterAndFormat('s', TextColor.color(44, 186, 168))); // Diamond + formats.add(CharacterAndFormat.characterAndFormat('t', TextColor.color(33, 73, 123))); // Lapis + formats.add(CharacterAndFormat.characterAndFormat('u', TextColor.color(154, 92, 198))); // Amethyst - formats.add(CharacterAndFormat.characterAndFormat('g', TextColor.color(221, 214, 5))); // Minecoin Gold - // Add the new characters implemented in 1.19.80 - formats.add(CharacterAndFormat.characterAndFormat('h', TextColor.color(227, 212, 209))); // Quartz - formats.add(CharacterAndFormat.characterAndFormat('i', TextColor.color(206, 202, 202))); // Iron - formats.add(CharacterAndFormat.characterAndFormat('j', TextColor.color(68, 58, 59))); // Netherite - formats.add(CharacterAndFormat.characterAndFormat('m', TextColor.color(151, 22, 7))); // Redstone - formats.add(CharacterAndFormat.characterAndFormat('n', TextColor.color(180, 104, 77))); // Copper - formats.add(CharacterAndFormat.characterAndFormat('p', TextColor.color(222, 177, 45))); // Gold - formats.add(CharacterAndFormat.characterAndFormat('q', TextColor.color(17, 160, 54))); // Emerald - formats.add(CharacterAndFormat.characterAndFormat('s', TextColor.color(44, 186, 168))); // Diamond - formats.add(CharacterAndFormat.characterAndFormat('t', TextColor.color(33, 73, 123))); // Lapis - formats.add(CharacterAndFormat.characterAndFormat('u', TextColor.color(154, 92, 198))); // Amethyst + // Can be removed once Adventure 1.15.0 is released (see https://github.com/KyoriPowered/adventure/pull/954) + ComponentFlattener flattener = ComponentFlattener.basic().toBuilder() + .mapper(ScoreComponent.class, component -> "") + .build(); - legacySerializer = LegacyComponentSerializer.legacySection().toBuilder() - .formats(formats) - .build(); + BEDROCK_SERIALIZER = LegacyComponentSerializer.legacySection().toBuilder() + .formats(formats) + .flattener(flattener) + .build(); - StringBuilder colorBuilder = new StringBuilder(); - for (CharacterAndFormat format : formats) { - if (format.format() instanceof TextColor) { - colorBuilder.append(format.character()); - } + // cache all the legacy character codes + StringBuilder colorBuilder = new StringBuilder(); + for (CharacterAndFormat format : formats) { + if (format.format() instanceof TextColor) { + colorBuilder.append(format.character()); } - allColors = colorBuilder.toString(); - } catch (ClassNotFoundException ignored) { - // Velocity doesn't have this yet. - legacySerializer = LegacyComponentSerializer.legacySection(); - allColors = "0123456789abcdef"; } - LEGACY_SERIALIZER = legacySerializer; - ALL_COLORS = allColors; + BEDROCK_COLORS = colorBuilder.toString(); } /** @@ -154,7 +152,7 @@ public class MessageTranslator { // Translate any components that require it message = RENDERER.render(message, locale); - String legacy = LEGACY_SERIALIZER.serialize(message); + String legacy = BEDROCK_SERIALIZER.serialize(message); StringBuilder finalLegacy = new StringBuilder(); char[] legacyChars = legacy.toCharArray(); @@ -170,7 +168,7 @@ public class MessageTranslator { } char next = legacyChars[++i]; - if (ALL_COLORS.indexOf(next) != -1) { + if (BEDROCK_COLORS.indexOf(next) != -1) { // Append this color code, as well as a necessary reset code if (!lastFormatReset) { finalLegacy.append(RESET); @@ -189,12 +187,12 @@ public class MessageTranslator { } } - public static String convertMessage(String message, String locale) { + public static String convertJsonMessage(String message, String locale) { return convertMessage(GSON_SERIALIZER.deserialize(message), locale); } - public static String convertMessage(String message) { - return convertMessage(message, GeyserLocale.getDefaultLocale()); + public static String convertJsonMessage(String message) { + return convertJsonMessage(message, GeyserLocale.getDefaultLocale()); } public static String convertMessage(Component message) { @@ -202,7 +200,7 @@ public class MessageTranslator { } /** - * Verifies the message is valid JSON in case it's plaintext. Works around GsonComponentSeraializer not using lenient mode. + * Verifies the message is valid JSON in case it's plaintext. Works around GsonComponentSerializer not using lenient mode. * See https://wiki.vg/Chat for messages sent in lenient mode, and for a description on leniency. * * @param message Potentially lenient JSON message @@ -218,9 +216,10 @@ public class MessageTranslator { } try { - return convertMessage(message, locale); + return convertJsonMessage(message, locale); } catch (Exception ignored) { - String convertedMessage = convertMessage(convertToJavaMessage(message), locale); + // Use the default legacy serializer since message is java-legacy + String convertedMessage = convertMessage(LegacyComponentSerializer.legacySection().deserialize(message), locale); // We have to do this since Adventure strips the starting reset character if (message.startsWith(RESET) && !convertedMessage.startsWith(RESET)) { @@ -242,11 +241,10 @@ public class MessageTranslator { * @return The formatted JSON string */ public static String convertToJavaMessage(String message) { - Component component = LegacyComponentSerializer.legacySection().deserialize(message); + Component component = BEDROCK_SERIALIZER.deserialize(message); return GSON_SERIALIZER.serialize(component); } - /** * Convert legacy format message to plain text * @@ -275,7 +273,7 @@ public class MessageTranslator { * @param locale Locale to use for translation strings * @return The plain text of the message */ - public static String convertToPlainText(String message, String locale) { + public static String convertToPlainTextLenient(String message, String locale) { if (message == null) { return ""; } diff --git a/core/src/test/java/org/geysermc/geyser/network/translators/chat/MessageTranslatorTest.java b/core/src/test/java/org/geysermc/geyser/network/translators/chat/MessageTranslatorTest.java index bce8fe0c8..5e5c3af7a 100644 --- a/core/src/test/java/org/geysermc/geyser/network/translators/chat/MessageTranslatorTest.java +++ b/core/src/test/java/org/geysermc/geyser/network/translators/chat/MessageTranslatorTest.java @@ -38,7 +38,7 @@ import java.util.Map; @TestInstance(TestInstance.Lifecycle.PER_CLASS) public class MessageTranslatorTest { - private Map messages = new HashMap<>(); + private final Map messages = new HashMap<>(); @BeforeAll public void setUp() throws Exception { @@ -70,7 +70,7 @@ public class MessageTranslatorTest { @Test public void convertMessage() { for (Map.Entry entry : messages.entrySet()) { - String bedrockMessage = MessageTranslator.convertMessage(entry.getKey(), "en_US"); + String bedrockMessage = MessageTranslator.convertJsonMessage(entry.getKey(), "en_US"); Assertions.assertEquals(entry.getValue(), bedrockMessage, "Translation of messages is incorrect"); } } @@ -85,13 +85,13 @@ public class MessageTranslatorTest { @Test public void convertToPlainText() { - Assertions.assertEquals("Many colors here", MessageTranslator.convertToPlainText("{\"extra\":[{\"color\":\"red\",\"text\":\"M\"},{\"color\":\"gold\",\"text\":\"a\"},{\"color\":\"yellow\",\"text\":\"n\"},{\"color\":\"green\",\"text\":\"y \"},{\"color\":\"aqua\",\"text\":\"c\"},{\"color\":\"dark_purple\",\"text\":\"o\"},{\"color\":\"red\",\"text\":\"l\"},{\"color\":\"gold\",\"text\":\"o\"},{\"color\":\"yellow\",\"text\":\"r\"},{\"color\":\"green\",\"text\":\"s \"},{\"color\":\"aqua\",\"text\":\"h\"},{\"color\":\"dark_purple\",\"text\":\"e\"},{\"color\":\"red\",\"text\":\"r\"},{\"color\":\"gold\",\"text\":\"e\"}],\"text\":\"\"}", "en_US"), "JSON message is not handled properly"); + Assertions.assertEquals("Many colors here", MessageTranslator.convertToPlainTextLenient("{\"extra\":[{\"color\":\"red\",\"text\":\"M\"},{\"color\":\"gold\",\"text\":\"a\"},{\"color\":\"yellow\",\"text\":\"n\"},{\"color\":\"green\",\"text\":\"y \"},{\"color\":\"aqua\",\"text\":\"c\"},{\"color\":\"dark_purple\",\"text\":\"o\"},{\"color\":\"red\",\"text\":\"l\"},{\"color\":\"gold\",\"text\":\"o\"},{\"color\":\"yellow\",\"text\":\"r\"},{\"color\":\"green\",\"text\":\"s \"},{\"color\":\"aqua\",\"text\":\"h\"},{\"color\":\"dark_purple\",\"text\":\"e\"},{\"color\":\"red\",\"text\":\"r\"},{\"color\":\"gold\",\"text\":\"e\"}],\"text\":\"\"}", "en_US"), "JSON message is not handled properly"); Assertions.assertEquals("Many colors here", MessageTranslator.convertToPlainText("§cM§6a§en§ay §bc§5o§cl§6o§er§as §bh§5e§cr§6e"), "Legacy formatted message is not handled properly (Colors)"); - Assertions.assertEquals("Many colors here", MessageTranslator.convertToPlainText("§cM§6a§en§ay §bc§5o§cl§6o§er§as §bh§5e§cr§6e", "en_US"), "Legacy formatted message is not handled properly (Colors)"); - Assertions.assertEquals("Obf Bold Strikethrough Underline Italic Reset", MessageTranslator.convertToPlainText("§kObf §lBold §mStrikethrough §nUnderline §oItalic §rReset", "en_US"), "Legacy formatted message is not handled properly (Style)"); - Assertions.assertEquals("Strange", MessageTranslator.convertToPlainText("§rStrange", "en_US"), "Valid lenient JSON is not handled properly"); - Assertions.assertEquals("", MessageTranslator.convertToPlainText("", "en_US"), "Empty message is not handled properly"); - Assertions.assertEquals(" ", MessageTranslator.convertToPlainText(" ", "en_US"), "Whitespace is not preserved"); + Assertions.assertEquals("Many colors here", MessageTranslator.convertToPlainTextLenient("§cM§6a§en§ay §bc§5o§cl§6o§er§as §bh§5e§cr§6e", "en_US"), "Legacy formatted message is not handled properly (Colors)"); + Assertions.assertEquals("Obf Bold Strikethrough Underline Italic Reset", MessageTranslator.convertToPlainTextLenient("§kObf §lBold §mStrikethrough §nUnderline §oItalic §rReset", "en_US"), "Legacy formatted message is not handled properly (Style)"); + Assertions.assertEquals("Strange", MessageTranslator.convertToPlainTextLenient("§rStrange", "en_US"), "Valid lenient JSON is not handled properly"); + Assertions.assertEquals("", MessageTranslator.convertToPlainTextLenient("", "en_US"), "Empty message is not handled properly"); + Assertions.assertEquals(" ", MessageTranslator.convertToPlainTextLenient(" ", "en_US"), "Whitespace is not preserved"); } @Test diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 74e623f38..cbceb3e7e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,8 +14,8 @@ protocol-connection = "3.0.0.Beta1-20230718.000033-101" raknet = "1.0.0.CR1-20230703.195238-9" mcauthlib = "d9d773e" mcprotocollib = "1.20-1-20230607.135651-6" # Temporary hack - needs to be updated to release once publishing is fixed -adventure = "4.14.0-20230424.215040-7" -adventure-platform = "4.1.2" +adventure = "4.14.0" +adventure-platform = "4.3.0" junit = "5.9.2" checkerframework = "3.19.0" log4j = "2.20.0" @@ -26,7 +26,7 @@ viaversion = "4.0.0" adapters = "1.9-SNAPSHOT" commodore = "2.2" bungeecord = "a7c6ede" -velocity = "3.0.0" +velocity = "3.1.1" sponge = "8.0.0" fabric-minecraft = "1.20" fabric-loader = "0.14.21" From 9ddfdf9374333737e94804b6f53cd95849b3471c Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Mon, 21 Aug 2023 16:04:08 -0700 Subject: [PATCH 056/344] Add support for custom blocks and skulls (#3505) * Super cursed custom skulls custom block * Rename some stuff * Attempt to clean up some code * Remove skull translation events and define custom blocks for custom skulls Clean up skull block translation a bit * Auto generate skull resource pack Change `davchoo` to `geyser` in geometry * Add config options for custom blocks and custom skull blocks * Fix formatting and names for player skulls * Use block states more efficiently for custom skulls 21 block states vs 48 block states * Clean up custom block api a bit * Apply some suggestions from Camotoy * Move custom skull config stuff to its own file Custom skulls can now be added by username, uuid, and textures Move skull nbt stuff from requestTexturesFromUsername to SkullBlockEntityTranslator Add requestTexturesFromUUID * Update custom block nbt for v534 * Disable collision box & selection box when box is empty Fix incorrect collision names used in CustomBlockComponentsBuilder * Add custom block stuff to provider registry loader * More API changes Convert CustomBlockPermutation into a record Change materialInstances in CustomBlockComponents Builder to materialInstance Reuse box components in CustomSkull * Convert skull floor geometries into a template Should be easier to modify in needed in the future. * Crop and reorder skull textures to eliminate unused space Should reduce memory & storage usage for Bedrock clients * Revert "Crop and reorder skull textures to eliminate unused space" This reverts commit 15fd5353e1c2b8bcffd6d5986095a3646a6e7bf9. * Use identifier from CustomBlockData in SkullResourcePackManager * Fix isIncorrectHeldItem check for custom skull blocks Add defaultBlockState to CustomBlockData * Fix adding duplicate block states for custom blocks with 0 properties Remove defaultBlockState CustomBlockState field from GeyserCustomBlockData since it creates a circular reference * Add basis for overriding Bedrock block states Fix missing providers when used in GeyserDefineCustomBlocksEvent * Fix custom blocks in 1.19.50 * Decouple mappings from items * Decouple mappings from items * Null check * Move to CustomBlockRegistryPopulator * Remove name_hash from blocksTag/vanillaBlockStates Fixes creative inventory contents with custom blocks registered * Limit Bedrock versions to 1.19.40+ Custom blocks were released in 1.19.40 * Un-revert Crop and reorder skull textures to eliminate unused space Should reduce memory & storage usage for Bedrock clients Bug with top face flipping + per-face uv's was fixed in 1.19.40+ https://bugs.mojang.com/browse/MCPE-160073 Geometry is still offset by 0.5 to prevent lighting bugs * Add validation custom block components and s/lightFilter/lightDampening/ Also validate custom block names * Add display name component and add toggle for client block placing The display name component allows blocks to use other locale keys. placeAir will prevent the client from placing the default block state. * Begin parsing block mappings (still much to do!) * CustomBlockMapping stores block w/ all states * Mappings almost :/ * Ok now they work at least * Read most mapping components * Block mappings mostly done * Translate block item * Add docs for custom blocks * Add tags * More docs * Accidentally added name comp. * Fix collide box and warn for >16 props * add registerBlockItemOverride event + refactor * Inventory overrides for multistate bedrock blocks * Implement all remaining block components * Minor cleanup and javadocs * Update custom skull config example * Address @Camotoy's review Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Fix light_emission and light_dampening components * Remove redundant populate method and remove BLOCKS_JSON after last use * Fix inventories with block state overrides not opening * API event for skull blocks & let register via URL Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Use skin hash instead of URL Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Address @davchoo's review Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Rework MappingsReader_v1 to avoid passing maps around * Treat all properties as string properties There isn't a real need to check for boolean and int properties * Fix block registry scan in MappingsReader * Skin hashes can have less than 64 characters? * Include entry when logging exceptions from block mappings * Submodule Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Fix block break speeds thanks to @Camotoy Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Temporarily fix build on eclipse so I may work... Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Custom tool breakspeed by server; Closes #3348 Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Account for if custom skulls are added on 1st run Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Initial framework for extended collision boxes Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Add some notes for the extended collision box impl Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * We have our extended collision registry Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Notes for me Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Extended collision boxes almost work Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Extended collision boxes actually work Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Consider all hitboxes in calculation Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * X is mirrored... Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Extended collision boxes are much improved Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Upstream fallout Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Address @Redned235's review Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Oops my bad that makes no sense :) Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Ext collision box chunk translation optimization Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Trunc skinhash to 32 chars due to 80 char limit Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Use new transformation cmpnt vs legacy rotation Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * keep arr null on get extcolstor Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Properly handle if extended collision box is below Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Less ugly (realized it can go here) Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Prevent 2x placement due to extended collision box Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Properly build on eclipse via indra Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Ensure enough bits in bedrockData for paletteIDs Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Fix not needed whitespace Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Update license headers to 2023 Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Use release indra over snapshot Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Revert "Update license headers to 2023" This reverts commit f750059e8ee01dfd4e9f9d13d3bdb85eb90e1f74. * Account for collisions in chunk section y0 layer Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Fix extended collision @ air section bottom Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Address @davchoo's review Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Address @rtm516's review Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * More @rtm516's review Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Address @Camotoy's review Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Update javadocs Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Address @davchoo's review Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Lock extended collision to section Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Clear ext col even when air Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Let override vanilla items in creative inventory Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Avoid creating 12 HashSets for every overrided block state * Super minor nitpicks + Custom Skull NBT fix * Check custom skull is within Bedrock bounds Fixes NPE with custom skulls above y=320 or below y=-64 * Add static builder methods to match CustomItemData API * Upstream Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Initial API setup for modded blocks (no impl yet) Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * More work on nonvanilla blocks (nonfunctional) Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Fix compile Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Update submodules Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Modded reg so far (not done) Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Add non-vanilla registration and fix a few bugs * Fixes for non-vanilla blocks * Remove import * CustomRegPop. go1st for now; must split for modded Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Address silent change to geo component for blocks Co-Authored-By: Unoqwy Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Seperate bedrock, vanilla, & nonvanilla block reg Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Single event Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Impl MaterialInstance as builder per @Redned235 Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Added creative category enum & added some missing overrides (#7) * Add material instance to provider registry Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * oops Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Fix case of correctBedrockIdentifier not found Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Fix docs Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Address @Camotoy's review Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Address review from @davchoo Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Set namespace of custom blocks vs ident direct Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Address review from @rtm516 Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * One more Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Remove rogue space * Geo component as builder Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * use super name Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Bump version Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --------- Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Signed-off-by: GitHub Co-authored-by: davchoo Co-authored-by: davchoo <4722249+davchoo@users.noreply.github.com> Co-authored-by: Unoqwy Co-authored-by: RednedEpic Co-authored-by: ImDaBigBoss <67973871+ImDaBigBoss@users.noreply.github.com> Co-authored-by: rtm516 --- .../api/block/custom/CustomBlockData.java | 143 ++++ .../block/custom/CustomBlockPermutation.java | 39 + .../api/block/custom/CustomBlockState.java | 75 ++ .../custom/NonVanillaCustomBlockData.java | 91 +++ .../block/custom/component/BoxComponent.java | 69 ++ .../component/CustomBlockComponents.java | 192 +++++ .../custom/component/GeometryComponent.java | 69 ++ .../custom/component/MaterialInstance.java | 84 +++ .../custom/component/PlacementConditions.java | 53 ++ .../component/TransformationComponent.java | 67 ++ .../custom/nonvanilla/JavaBlockItem.java | 7 + .../custom/nonvanilla/JavaBlockState.java | 111 +++ .../custom/nonvanilla/JavaBoundingBox.java | 6 + .../custom/property/CustomBlockProperty.java | 56 ++ .../block/custom/property/PropertyType.java | 79 ++ .../GeyserDefineCustomBlocksEvent.java | 76 ++ .../GeyserDefineCustomSkullsEvent.java | 28 + .../geyser/api/util/CreativeCategory.java | 66 ++ build-logic/build.gradle.kts | 2 +- .../kotlin/geyser.base-conventions.gradle.kts | 2 +- build.gradle.kts | 12 +- .../java/org/geysermc/geyser/Constants.java | 4 + .../GeyserCustomSkullConfiguration.java | 65 ++ .../holder/BlockInventoryHolder.java | 19 +- .../mappings/versions/MappingsReader_v1.java | 132 ---- .../geyser/item/type/PlayerHeadItem.java | 35 +- .../block/GeyserCustomBlockComponents.java | 305 ++++++++ .../level/block/GeyserCustomBlockData.java | 217 ++++++ .../block/GeyserCustomBlockProperty.java | 44 ++ .../level/block/GeyserCustomBlockState.java | 112 +++ .../level/block/GeyserGeometryComponent.java | 76 ++ .../level/block/GeyserJavaBlockState.java | 161 ++++ .../level/block/GeyserMaterialInstance.java | 102 +++ .../GeyserNonVanillaCustomBlockData.java | 118 +++ .../geyser/pack/SkullResourcePackManager.java | 306 ++++++++ .../geyser/registry/BlockRegistries.java | 60 +- .../geysermc/geyser/registry/Registries.java | 18 +- .../loader/CollisionRegistryLoader.java | 5 + .../loader/ProviderRegistryLoader.java | 20 + .../registry/loader/ResourcePackLoader.java | 7 + .../mappings/MappingsConfigReader.java | 76 +- .../util/CustomBlockComponentsMapping.java | 40 + .../mappings/util/CustomBlockMapping.java | 44 ++ .../util/CustomBlockStateBuilderMapping.java | 42 ++ .../util/CustomBlockStateMapping.java | 40 + .../mappings/versions/MappingsReader.java | 7 +- .../mappings/versions/MappingsReader_v1.java | 713 ++++++++++++++++++ .../populator/BlockRegistryPopulator.java | 242 +++++- .../CustomBlockRegistryPopulator.java | 480 ++++++++++++ .../CustomItemRegistryPopulator.java | 72 +- .../CustomSkullRegistryPopulator.java | 187 +++++ .../populator/ItemRegistryPopulator.java | 101 ++- .../geyser/registry/type/BlockMapping.java | 1 + .../geyser/registry/type/BlockMappings.java | 18 + .../geyser/registry/type/CustomSkull.java | 166 ++++ .../registry/type/GeyserMappingItem.java | 2 + .../geyser/registry/type/ItemMappings.java | 4 + .../geyser/session/GeyserSession.java | 17 + .../geyser/session/cache/SkullCache.java | 97 ++- .../org/geysermc/geyser/skin/SkinManager.java | 2 +- .../geysermc/geyser/skin/SkinProvider.java | 11 +- .../chest/DoubleChestInventoryTranslator.java | 44 +- .../inventory/item/ItemTranslator.java | 91 ++- .../level/block/entity/PistonBlockEntity.java | 6 +- .../entity/SkullBlockEntityTranslator.java | 53 +- ...BedrockInventoryTransactionTranslator.java | 36 +- .../player/BedrockActionTranslator.java | 50 +- .../java/JavaUpdateRecipesTranslator.java | 6 +- .../level/JavaBlockEntityDataTranslator.java | 19 +- .../JavaLevelChunkWithLightTranslator.java | 209 ++++- .../org/geysermc/geyser/util/BlockUtils.java | 4 +- .../org/geysermc/geyser/util/ChunkUtils.java | 44 +- .../org/geysermc/geyser/util/FileUtils.java | 9 + .../org/geysermc/geyser/util/MathUtils.java | 48 ++ .../animations/disable.animation.json | 14 + .../animations/player_skull.animation.json | 80 ++ .../attachables/template_attachable.json | 57 ++ .../bedrock/skull_resource_pack/manifest.json | 17 + .../models/blocks/player_skull.geo.json | 73 ++ .../models/blocks/player_skull_floor.geo.json | 53 ++ .../models/blocks/player_skull_hand.geo.json | 52 ++ .../models/blocks/player_skull_wall.geo.json | 52 ++ .../textures/terrain_texture.json | 8 + .../bedrock/skull_resource_pack_files.txt | 7 + core/src/main/resources/config.yml | 3 +- core/src/main/resources/custom-skulls.yml | 29 + .../src/main/resources/icon.png | Bin gradle.properties | 4 +- 88 files changed, 6235 insertions(+), 328 deletions(-) create mode 100644 api/src/main/java/org/geysermc/geyser/api/block/custom/CustomBlockData.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/block/custom/CustomBlockPermutation.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/block/custom/CustomBlockState.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/block/custom/NonVanillaCustomBlockData.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/block/custom/component/BoxComponent.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/block/custom/component/CustomBlockComponents.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/block/custom/component/GeometryComponent.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/block/custom/component/MaterialInstance.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/block/custom/component/PlacementConditions.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/block/custom/component/TransformationComponent.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/block/custom/nonvanilla/JavaBlockItem.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/block/custom/nonvanilla/JavaBlockState.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/block/custom/nonvanilla/JavaBoundingBox.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/block/custom/property/CustomBlockProperty.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/block/custom/property/PropertyType.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserDefineCustomBlocksEvent.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserDefineCustomSkullsEvent.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/util/CreativeCategory.java create mode 100644 core/src/main/java/org/geysermc/geyser/configuration/GeyserCustomSkullConfiguration.java delete mode 100644 core/src/main/java/org/geysermc/geyser/item/mappings/versions/MappingsReader_v1.java create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockComponents.java create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockData.java create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockProperty.java create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockState.java create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/GeyserGeometryComponent.java create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/GeyserJavaBlockState.java create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/GeyserMaterialInstance.java create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/GeyserNonVanillaCustomBlockData.java create mode 100644 core/src/main/java/org/geysermc/geyser/pack/SkullResourcePackManager.java rename core/src/main/java/org/geysermc/geyser/{item => registry}/mappings/MappingsConfigReader.java (58%) create mode 100644 core/src/main/java/org/geysermc/geyser/registry/mappings/util/CustomBlockComponentsMapping.java create mode 100644 core/src/main/java/org/geysermc/geyser/registry/mappings/util/CustomBlockMapping.java create mode 100644 core/src/main/java/org/geysermc/geyser/registry/mappings/util/CustomBlockStateBuilderMapping.java create mode 100644 core/src/main/java/org/geysermc/geyser/registry/mappings/util/CustomBlockStateMapping.java rename core/src/main/java/org/geysermc/geyser/{item => registry}/mappings/versions/MappingsReader.java (86%) create mode 100644 core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java create mode 100644 core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java create mode 100644 core/src/main/java/org/geysermc/geyser/registry/populator/CustomSkullRegistryPopulator.java create mode 100644 core/src/main/java/org/geysermc/geyser/registry/type/CustomSkull.java create mode 100644 core/src/main/resources/bedrock/skull_resource_pack/animations/disable.animation.json create mode 100644 core/src/main/resources/bedrock/skull_resource_pack/animations/player_skull.animation.json create mode 100644 core/src/main/resources/bedrock/skull_resource_pack/attachables/template_attachable.json create mode 100644 core/src/main/resources/bedrock/skull_resource_pack/manifest.json create mode 100644 core/src/main/resources/bedrock/skull_resource_pack/models/blocks/player_skull.geo.json create mode 100644 core/src/main/resources/bedrock/skull_resource_pack/models/blocks/player_skull_floor.geo.json create mode 100644 core/src/main/resources/bedrock/skull_resource_pack/models/blocks/player_skull_hand.geo.json create mode 100644 core/src/main/resources/bedrock/skull_resource_pack/models/blocks/player_skull_wall.geo.json create mode 100644 core/src/main/resources/bedrock/skull_resource_pack/textures/terrain_texture.json create mode 100644 core/src/main/resources/bedrock/skull_resource_pack_files.txt create mode 100644 core/src/main/resources/custom-skulls.yml rename {bootstrap/standalone => core}/src/main/resources/icon.png (100%) diff --git a/api/src/main/java/org/geysermc/geyser/api/block/custom/CustomBlockData.java b/api/src/main/java/org/geysermc/geyser/api/block/custom/CustomBlockData.java new file mode 100644 index 000000000..9f142faab --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/block/custom/CustomBlockData.java @@ -0,0 +1,143 @@ +/* + * 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.api.block.custom; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.geyser.api.GeyserApi; +import org.geysermc.geyser.api.block.custom.component.CustomBlockComponents; +import org.geysermc.geyser.api.block.custom.property.CustomBlockProperty; +import org.geysermc.geyser.api.util.CreativeCategory; + +import java.util.List; +import java.util.Map; + +/** + * This class is used to store data for a custom block. + */ +public interface CustomBlockData { + /** + * Gets the name of the custom block + * + * @return The name of the custom block. + */ + @NonNull String name(); + + /** + * Gets the identifier of the custom block + * + * @return The identifier of the custom block. + */ + @NonNull String identifier(); + + /** + * Gets if the custom block is included in the creative inventory + * + * @return If the custom block is included in the creative inventory. + */ + boolean includedInCreativeInventory(); + + /** + * Gets the item's creative category, or tab id. + * + * @return the item's creative category + */ + @Nullable CreativeCategory creativeCategory(); + + /** + * Gets the item's creative group. + * + * @return the item's creative group + */ + @Nullable String creativeGroup(); + + /** + * Gets the components of the custom block + * + * @return The components of the custom block. + */ + @Nullable CustomBlockComponents components(); + + /** + * Gets the custom block's map of block property names to CustomBlockProperty + * objects + * + * @return The custom block's map of block property names to CustomBlockProperty objects. + */ + @NonNull Map> properties(); + + /** + * Gets the list of the custom block's permutations + * + * @return The permutations of the custom block. + */ + @NonNull List permutations(); + + /** + * Gets the custom block's default block state + * + * @return The default block state of the custom block. + */ + @NonNull CustomBlockState defaultBlockState(); + + /** + * Gets a builder for a custom block state + * + * @return The builder for a custom block state. + */ + CustomBlockState.@NonNull Builder blockStateBuilder(); + + /** + * Create a Builder for CustomBlockData + * + * @return A CustomBlockData Builder + */ + static CustomBlockData.Builder builder() { + return GeyserApi.api().provider(CustomBlockData.Builder.class); + } + + interface Builder { + Builder name(@NonNull String name); + + Builder includedInCreativeInventory(boolean includedInCreativeInventory); + + Builder creativeCategory(@Nullable CreativeCategory creativeCategory); + + Builder creativeGroup(@Nullable String creativeGroup); + + Builder components(@NonNull CustomBlockComponents components); + + Builder booleanProperty(@NonNull String propertyName); + + Builder intProperty(@NonNull String propertyName, List values); + + Builder stringProperty(@NonNull String propertyName, List values); + + Builder permutations(@NonNull List permutations); + + CustomBlockData build(); + } +} diff --git a/api/src/main/java/org/geysermc/geyser/api/block/custom/CustomBlockPermutation.java b/api/src/main/java/org/geysermc/geyser/api/block/custom/CustomBlockPermutation.java new file mode 100644 index 000000000..fca39b533 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/block/custom/CustomBlockPermutation.java @@ -0,0 +1,39 @@ +/* + * 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.api.block.custom; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.api.block.custom.component.CustomBlockComponents; + +/** + * This class is used to store a custom block permutations, which contain custom + * block components mapped to a Molang query that should return true or false + * + * @param components The components of the block + * @param condition The Molang query that should return true or false + */ +public record CustomBlockPermutation(@NonNull CustomBlockComponents components, @NonNull String condition) { +} diff --git a/api/src/main/java/org/geysermc/geyser/api/block/custom/CustomBlockState.java b/api/src/main/java/org/geysermc/geyser/api/block/custom/CustomBlockState.java new file mode 100644 index 000000000..70b3c1e2d --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/block/custom/CustomBlockState.java @@ -0,0 +1,75 @@ +/* + * 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.api.block.custom; + +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.util.Map; + +/** + * This class is used to store a custom block state, which contains CustomBlockData + * tied to defined properties and values + */ +public interface CustomBlockState { + /** + * Gets the custom block data associated with the state + * + * @return The custom block data for the state. + */ + @NonNull CustomBlockData block(); + + /** + * Gets the name of the state + * + * @return The name of the state. + */ + @NonNull String name(); + + /** + * Gets the given property for the state + * + * @param propertyName the property name + * @return the boolean, int, or string property. + */ + @NonNull T property(@NonNull String propertyName); + + /** + * Gets a map of the properties for the state + * + * @return The properties for the state. + */ + @NonNull Map properties(); + + interface Builder { + Builder booleanProperty(@NonNull String propertyName, boolean value); + + Builder intProperty(@NonNull String propertyName, int value); + + Builder stringProperty(@NonNull String propertyName, @NonNull String value); + + CustomBlockState build(); + } +} diff --git a/api/src/main/java/org/geysermc/geyser/api/block/custom/NonVanillaCustomBlockData.java b/api/src/main/java/org/geysermc/geyser/api/block/custom/NonVanillaCustomBlockData.java new file mode 100644 index 000000000..4ab186ce6 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/block/custom/NonVanillaCustomBlockData.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2019-2023 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.api.block.custom; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.geyser.api.GeyserApi; +import org.geysermc.geyser.api.block.custom.component.CustomBlockComponents; +import org.geysermc.geyser.api.util.CreativeCategory; + +import java.util.List; + +/** + * Represents a completely custom block that is not based on an existing vanilla Minecraft block. + */ +public interface NonVanillaCustomBlockData extends CustomBlockData { + /** + * Gets the namespace of the custom block + * + * @return The namespace of the custom block. + */ + @NonNull String namespace(); + + + /** + * Create a Builder for NonVanillaCustomBlockData + * + * @return A NonVanillaCustomBlockData Builder + */ + static NonVanillaCustomBlockData.Builder builder() { + return GeyserApi.api().provider(NonVanillaCustomBlockData.Builder.class); + } + + interface Builder extends CustomBlockData.Builder { + + Builder namespace(@NonNull String namespace); + + @Override + Builder name(@NonNull String name); + + @Override + Builder includedInCreativeInventory(boolean includedInCreativeInventory); + + @Override + Builder creativeCategory(@Nullable CreativeCategory creativeCategory); + + @Override + Builder creativeGroup(@Nullable String creativeGroup); + + @Override + Builder components(@NonNull CustomBlockComponents components); + + @Override + Builder booleanProperty(@NonNull String propertyName); + + @Override + Builder intProperty(@NonNull String propertyName, List values); + + @Override + Builder stringProperty(@NonNull String propertyName, List values); + + @Override + Builder permutations(@NonNull List permutations); + + @Override + NonVanillaCustomBlockData build(); + } +} diff --git a/api/src/main/java/org/geysermc/geyser/api/block/custom/component/BoxComponent.java b/api/src/main/java/org/geysermc/geyser/api/block/custom/component/BoxComponent.java new file mode 100644 index 000000000..0b577742d --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/block/custom/component/BoxComponent.java @@ -0,0 +1,69 @@ +/* + * 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.api.block.custom.component; + +/** + * This class is used to store a box component for the selection and + * collision boxes of a custom block. + * + * @param originX The origin X of the box + * @param originY The origin Y of the box + * @param originZ The origin Z of the box + * @param sizeX The size X of the box + * @param sizeY The size Y of the box + * @param sizeZ The size Z of the box + */ +public record BoxComponent(float originX, float originY, float originZ, float sizeX, float sizeY, float sizeZ) { + private static final BoxComponent FULL_BOX = new BoxComponent(-8, 0, -8, 16, 16, 16); + private static final BoxComponent EMPTY_BOX = new BoxComponent(0, 0, 0, 0, 0, 0); + + /** + * Gets a full box component + * + * @return A full box component + */ + public static BoxComponent fullBox() { + return FULL_BOX; + } + + /** + * Gets an empty box component + * + * @return An empty box component + */ + public static BoxComponent emptyBox() { + return EMPTY_BOX; + } + + /** + * Gets if the box component is empty + * + * @return If the box component is empty. + */ + public boolean isEmpty() { + return sizeX == 0 && sizeY == 0 && sizeZ == 0; + } +} diff --git a/api/src/main/java/org/geysermc/geyser/api/block/custom/component/CustomBlockComponents.java b/api/src/main/java/org/geysermc/geyser/api/block/custom/component/CustomBlockComponents.java new file mode 100644 index 000000000..036723092 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/block/custom/component/CustomBlockComponents.java @@ -0,0 +1,192 @@ +/* + * 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.api.block.custom.component; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.geyser.api.GeyserApi; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * This class is used to store components for a custom block or custom block permutation. + */ +public interface CustomBlockComponents { + + /** + * Gets the selection box component + * Equivalent to "minecraft:selection_box" + * + * @return The selection box. + */ + @Nullable BoxComponent selectionBox(); + + /** + * Gets the collision box component + * Equivalent to "minecraft:collision_box" + * @return The collision box. + */ + @Nullable BoxComponent collisionBox(); + + /** + * Gets the display name component + * Equivalent to "minecraft:display_name" + * + * @return The display name. + */ + @Nullable String displayName(); + + /** + * Gets the geometry component + * Equivalent to "minecraft:geometry" + * + * @return The geometry. + */ + @Nullable GeometryComponent geometry(); + + /** + * Gets the material instances component + * Equivalent to "minecraft:material_instances" + * + * @return The material instances. + */ + @NonNull Map materialInstances(); + + /** + * Gets the placement filter component + * Equivalent to "minecraft:placement_filter" + * + * @return The placement filter. + */ + @Nullable List placementFilter(); + + /** + * Gets the destructible by mining component + * Equivalent to "minecraft:destructible_by_mining" + * + * @return The destructible by mining value. + */ + @Nullable Float destructibleByMining(); + + /** + * Gets the friction component + * Equivalent to "minecraft:friction" + * + * @return The friction value. + */ + @Nullable Float friction(); + + /** + * Gets the light emission component + * Equivalent to "minecraft:light_emission" + * + * @return The light emission value. + */ + @Nullable Integer lightEmission(); + + /** + * Gets the light dampening component + * Equivalent to "minecraft:light_dampening" + * + * @return The light dampening value. + */ + @Nullable Integer lightDampening(); + + /** + * Gets the transformation component + * Equivalent to "minecraft:transformation" + * + * @return The transformation. + */ + @Nullable TransformationComponent transformation(); + + /** + * Gets the unit cube component + * Equivalent to "minecraft:unit_cube" + * + * @return The rotation. + */ + boolean unitCube(); + + /** + * Gets if the block should place only air + * Equivalent to setting a dummy event to run on "minecraft:on_player_placing" + * + * @return If the block should place only air. + */ + boolean placeAir(); + + /** + * Gets the set of tags + * Equivalent to "tag:some_tag" + * + * @return The set of tags. + */ + @NonNull Set tags(); + + /** + * Create a Builder for CustomBlockComponents + * + * @return A CustomBlockComponents Builder + */ + static CustomBlockComponents.Builder builder() { + return GeyserApi.api().provider(CustomBlockComponents.Builder.class); + } + + interface Builder { + Builder selectionBox(BoxComponent selectionBox); + + Builder collisionBox(BoxComponent collisionBox); + + Builder displayName(String displayName); + + Builder geometry(GeometryComponent geometry); + + Builder materialInstance(@NonNull String name, @NonNull MaterialInstance materialInstance); + + Builder placementFilter(List placementConditions); + + Builder destructibleByMining(Float destructibleByMining); + + Builder friction(Float friction); + + Builder lightEmission(Integer lightEmission); + + Builder lightDampening(Integer lightDampening); + + Builder transformation(TransformationComponent transformation); + + Builder unitCube(boolean unitCube); + + Builder placeAir(boolean placeAir); + + Builder tags(Set tags); + + CustomBlockComponents build(); + } +} diff --git a/api/src/main/java/org/geysermc/geyser/api/block/custom/component/GeometryComponent.java b/api/src/main/java/org/geysermc/geyser/api/block/custom/component/GeometryComponent.java new file mode 100644 index 000000000..6d85989a7 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/block/custom/component/GeometryComponent.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2019-2023 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.api.block.custom.component; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.geyser.api.GeyserApi; + +import java.util.Map; + +/** + * This class is used to store data for a geometry component. + */ +public interface GeometryComponent { + + /** + * Gets the identifier of the geometry + * + * @return The identifier of the geometry. + */ + @NonNull String identifier(); + + /** + * Gets the bone visibility of the geometry + * + * @return The bone visibility of the geometry. + */ + @Nullable Map boneVisibility(); + + /** + * Creates a builder for GeometryComponent + * + * @return a builder for GeometryComponent. + */ + static GeometryComponent.Builder builder() { + return GeyserApi.api().provider(GeometryComponent.Builder.class); + } + + interface Builder { + Builder identifier(@NonNull String identifier); + + Builder boneVisibility(@Nullable Map boneVisibility); + + GeometryComponent build(); + } +} diff --git a/api/src/main/java/org/geysermc/geyser/api/block/custom/component/MaterialInstance.java b/api/src/main/java/org/geysermc/geyser/api/block/custom/component/MaterialInstance.java new file mode 100644 index 000000000..26edab2f6 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/block/custom/component/MaterialInstance.java @@ -0,0 +1,84 @@ +/* + * 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.api.block.custom.component; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.geyser.api.GeyserApi; + +/** + * This class is used to store data for a material instance. + */ +public interface MaterialInstance { + /** + * Gets the texture of the block + * + * @return The texture of the block. + */ + @NonNull String texture(); + + /** + * Gets the render method of the block + * + * @return The render method of the block. + */ + @Nullable String renderMethod(); + + /** + * Gets if the block should be dimmed on certain faces + * + * @return If the block should be dimmed on certain faces. + */ + @Nullable boolean faceDimming(); + + /** + * Gets if the block should have ambient occlusion + * + * @return If the block should have ambient occlusion. + */ + @Nullable boolean ambientOcclusion(); + + /** + * Creates a builder for MaterialInstance. + * + * @return a builder for MaterialInstance + */ + static MaterialInstance.Builder builder() { + return GeyserApi.api().provider(MaterialInstance.Builder.class); + } + + interface Builder { + Builder texture(@NonNull String texture); + + Builder renderMethod(@Nullable String renderMethod); + + Builder faceDimming(@Nullable boolean faceDimming); + + Builder ambientOcclusion(@Nullable boolean ambientOcclusion); + + MaterialInstance build(); + } +} diff --git a/api/src/main/java/org/geysermc/geyser/api/block/custom/component/PlacementConditions.java b/api/src/main/java/org/geysermc/geyser/api/block/custom/component/PlacementConditions.java new file mode 100644 index 000000000..d06d9a967 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/block/custom/component/PlacementConditions.java @@ -0,0 +1,53 @@ +/* + * 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.api.block.custom.component; + +import java.util.LinkedHashMap; +import java.util.Set; + +import org.checkerframework.checker.nullness.qual.NonNull; + +/** + * This class is used to store conditions for a placement filter for a custom block. + * + * @param allowedFaces The faces that the block can be placed on + * @param blockFilters The block filters that control what blocks the block can be placed on + */ +public record PlacementConditions(@NonNull Set allowedFaces, @NonNull LinkedHashMap blockFilters) { + public enum Face { + DOWN, + UP, + NORTH, + SOUTH, + WEST, + EAST; + } + + public enum BlockFilterType { + BLOCK, + TAG + } +} \ No newline at end of file diff --git a/api/src/main/java/org/geysermc/geyser/api/block/custom/component/TransformationComponent.java b/api/src/main/java/org/geysermc/geyser/api/block/custom/component/TransformationComponent.java new file mode 100644 index 000000000..d52565e22 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/block/custom/component/TransformationComponent.java @@ -0,0 +1,67 @@ +/* + * 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.api.block.custom.component; + +/** + * This class is used to store the transformation component of a block + * + * @param rx The rotation on the x axis + * @param ry The rotation on the y axis + * @param rz The rotation on the z axis + * @param sx The scale on the x axis + * @param sy The scale on the y axis + * @param sz The scale on the z axis + * @param tx The translation on the x axis + * @param ty The translation on the y axis + * @param tz The translation on the z axis + */ +public record TransformationComponent(int rx, int ry, int rz, float sx, float sy, float sz, float tx, float ty, float tz) { + + /** + * Constructs a new TransformationComponent with the rotation values and assumes default scale and translation + * + * @param rx The rotation on the x axis + * @param ry The rotation on the y axis + * @param rz The rotation on the z axis + */ + public TransformationComponent(int rx, int ry, int rz) { + this(rx, ry, rz, 1, 1, 1, 0, 0, 0); + } + + /** + * Constructs a new TransformationComponent with the rotation and scale values and assumes default translation + * + * @param rx The rotation on the x axis + * @param ry The rotation on the y axis + * @param rz The rotation on the z axis + * @param sx The scale on the x axis + * @param sy The scale on the y axis + * @param sz The scale on the z axis + */ + public TransformationComponent(int rx, int ry, int rz, float sx, float sy, float sz) { + this(rx, ry, rz, sx, sy, sz, 0, 0, 0); + } +} diff --git a/api/src/main/java/org/geysermc/geyser/api/block/custom/nonvanilla/JavaBlockItem.java b/api/src/main/java/org/geysermc/geyser/api/block/custom/nonvanilla/JavaBlockItem.java new file mode 100644 index 000000000..5143246d9 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/block/custom/nonvanilla/JavaBlockItem.java @@ -0,0 +1,7 @@ +package org.geysermc.geyser.api.block.custom.nonvanilla; + +import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.nullness.qual.NonNull; + +public record JavaBlockItem(@NonNull String identifier, @NonNegative int javaId, @NonNegative int stackSize) { +} diff --git a/api/src/main/java/org/geysermc/geyser/api/block/custom/nonvanilla/JavaBlockState.java b/api/src/main/java/org/geysermc/geyser/api/block/custom/nonvanilla/JavaBlockState.java new file mode 100644 index 000000000..6293506a8 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/block/custom/nonvanilla/JavaBlockState.java @@ -0,0 +1,111 @@ +package org.geysermc.geyser.api.block.custom.nonvanilla; + +import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.geyser.api.GeyserApi; + +public interface JavaBlockState { + /** + * Gets the identifier of the block state + * + * @return the identifier of the block state + */ + @NonNull String identifier(); + + /** + * Gets the Java ID of the block state + * + * @return the Java ID of the block state + */ + @NonNegative int javaId(); + + /** + * Gets the state group ID of the block state + * + * @return the state group ID of the block state + */ + @NonNegative int stateGroupId(); + + /** + * Gets the block hardness of the block state + * + * @return the block hardness of the block state + */ + @NonNegative float blockHardness(); + + /** + * Gets whether the block state is waterlogged + * + * @return whether the block state is waterlogged + */ + @NonNull boolean waterlogged(); + + /** + * Gets the collision of the block state + * + * @return the collision of the block state + */ + @NonNull JavaBoundingBox[] collision(); + + /** + * Gets whether the block state can be broken with hand + * + * @return whether the block state can be broken with hand + */ + @NonNull boolean canBreakWithHand(); + + /** + * Gets the pick item of the block state + * + * @return the pick item of the block state + */ + @Nullable String pickItem(); + + /** + * Gets the piston behavior of the block state + * + * @return the piston behavior of the block state + */ + @Nullable String pistonBehavior(); + + /** + * Gets whether the block state has block entity + * + * @return whether the block state has block entity + */ + @Nullable boolean hasBlockEntity(); + + /** + * Creates a new {@link JavaBlockState.Builder} instance + * + * @return a new {@link JavaBlockState.Builder} instance + */ + static JavaBlockState.Builder builder() { + return GeyserApi.api().provider(JavaBlockState.Builder.class); + } + + interface Builder { + Builder identifier(@NonNull String identifier); + + Builder javaId(@NonNegative int javaId); + + Builder stateGroupId(@NonNegative int stateGroupId); + + Builder blockHardness(@NonNegative float blockHardness); + + Builder waterlogged(@NonNull boolean waterlogged); + + Builder collision(@NonNull JavaBoundingBox[] collision); + + Builder canBreakWithHand(@NonNull boolean canBreakWithHand); + + Builder pickItem(@Nullable String pickItem); + + Builder pistonBehavior(@Nullable String pistonBehavior); + + Builder hasBlockEntity(@Nullable boolean hasBlockEntity); + + JavaBlockState build(); + } +} diff --git a/api/src/main/java/org/geysermc/geyser/api/block/custom/nonvanilla/JavaBoundingBox.java b/api/src/main/java/org/geysermc/geyser/api/block/custom/nonvanilla/JavaBoundingBox.java new file mode 100644 index 000000000..56a4ca3da --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/block/custom/nonvanilla/JavaBoundingBox.java @@ -0,0 +1,6 @@ +package org.geysermc.geyser.api.block.custom.nonvanilla; + +import org.checkerframework.checker.nullness.qual.NonNull; + +public record JavaBoundingBox(@NonNull double middleX, @NonNull double middleY, @NonNull double middleZ, @NonNull double sizeX, @NonNull double sizeY, @NonNull double sizeZ) { +} diff --git a/api/src/main/java/org/geysermc/geyser/api/block/custom/property/CustomBlockProperty.java b/api/src/main/java/org/geysermc/geyser/api/block/custom/property/CustomBlockProperty.java new file mode 100644 index 000000000..fc39c4663 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/block/custom/property/CustomBlockProperty.java @@ -0,0 +1,56 @@ +/* + * 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.api.block.custom.property; + +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.util.List; + +/** + * This class is used to store a property of a custom block of a generic type. + */ +public interface CustomBlockProperty { + /** + * Gets the name of the property + * + * @return The name of the property. + */ + @NonNull String name(); + + /** + * Gets the values of the property + * + * @return The values of the property. + */ + @NonNull List values(); + + /** + * Gets the type of the property + * + * @return The type of the property. + */ + @NonNull PropertyType type(); +} diff --git a/api/src/main/java/org/geysermc/geyser/api/block/custom/property/PropertyType.java b/api/src/main/java/org/geysermc/geyser/api/block/custom/property/PropertyType.java new file mode 100644 index 000000000..48f25c36c --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/block/custom/property/PropertyType.java @@ -0,0 +1,79 @@ +/* + * 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.api.block.custom.property; + +import org.checkerframework.checker.nullness.qual.NonNull; + +/** + * This class is used to define a custom block property's type. + */ +public class PropertyType { + private static final PropertyType BOOLEAN = new PropertyType(Boolean.class); + private static final PropertyType INTEGER = new PropertyType(Integer.class); + private static final PropertyType STRING = new PropertyType(String.class); + + /** + * Gets the property type for a boolean. + * + * @return The property type for a boolean. + */ + @NonNull public static PropertyType booleanProp() { + return BOOLEAN; + } + + /** + * Gets the property type for an integer. + * + * @return The property type for an integer. + */ + @NonNull public static PropertyType integerProp() { + return INTEGER; + } + + /** + * Gets the property type for a string. + * + * @return The property type for a string. + */ + @NonNull public static PropertyType stringProp() { + return STRING; + } + + private final Class typeClass; + + /** + * Gets the class of the property type + * + * @return The class of the property type. + */ + @NonNull public Class typeClass() { + return typeClass; + } + + private PropertyType(Class typeClass) { + this.typeClass = typeClass; + } +} diff --git a/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserDefineCustomBlocksEvent.java b/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserDefineCustomBlocksEvent.java new file mode 100644 index 000000000..b1a01d7e6 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserDefineCustomBlocksEvent.java @@ -0,0 +1,76 @@ +/* + * 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.api.event.lifecycle; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.api.block.custom.CustomBlockData; +import org.geysermc.geyser.api.block.custom.CustomBlockState; +import org.geysermc.geyser.api.block.custom.nonvanilla.JavaBlockItem; +import org.geysermc.geyser.api.block.custom.nonvanilla.JavaBlockState; +import org.geysermc.event.Event; + +/** + * Called on Geyser's startup when looking for custom blocks. Custom blocks must be registered through this event. + * + * This event will not be called if the "add-non-bedrock-items" setting is disabled in the Geyser config. + */ +public abstract class GeyserDefineCustomBlocksEvent implements Event { + /** + * Registers the given {@link CustomBlockData} as a custom block + * + * @param customBlockData the custom block to register + */ + public abstract void register(@NonNull CustomBlockData customBlockData); + + /** + * Registers the given {@link CustomBlockState} as an override for the + * given java state identifier + * Java state identifiers are listed in + * https://raw.githubusercontent.com/GeyserMC/mappings/master/blocks.json + * + * @param javaIdentifier the java state identifier to override + * @param customBlockState the custom block state with which to override java state identifier + */ + public abstract void registerOverride(@NonNull String javaIdentifier, @NonNull CustomBlockState customBlockState); + + /** + * Registers the given {@link CustomBlockData} as an override for the + * given java item identifier + * + * @param javaIdentifier the java item identifier to override + * @param customBlockData the custom block data with which to override java item identifier + */ + public abstract void registerItemOverride(@NonNull String javaIdentifier, @NonNull CustomBlockData customBlockData); + + /** + * Registers the given {@link CustomBlockState} as an override for the + * given {@link JavaBlockState} + * + * @param javaBlockState the java block state for the non-vanilla block + * @param customBlockState the custom block state with which to override java state identifier + */ + public abstract void registerOverride(@NonNull JavaBlockState javaBlockState, @NonNull CustomBlockState customBlockState); +} diff --git a/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserDefineCustomSkullsEvent.java b/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserDefineCustomSkullsEvent.java new file mode 100644 index 000000000..17f7b599a --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserDefineCustomSkullsEvent.java @@ -0,0 +1,28 @@ +package org.geysermc.geyser.api.event.lifecycle; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.event.Event; + +/** + * Called on Geyser's startup when looking for custom skulls. Custom skulls must be registered through this event. + * + * This event will not be called if the "add-non-bedrock-items" setting is disabled in the Geyser config. + */ +public abstract class GeyserDefineCustomSkullsEvent implements Event { + /** + * The type of texture provided + */ + public enum SkullTextureType { + USERNAME, + UUID, + PROFILE, + SKIN_HASH + } + + /** + * Registers the given username, UUID, base64 encoded profile, or skin hash as a custom skull blocks + * @param texture the username, UUID, base64 encoded profile, or skin hash + * @param type the type of texture provided + */ + public abstract void register(@NonNull String texture, @NonNull SkullTextureType type); +} diff --git a/api/src/main/java/org/geysermc/geyser/api/util/CreativeCategory.java b/api/src/main/java/org/geysermc/geyser/api/util/CreativeCategory.java new file mode 100644 index 000000000..7519ff157 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/util/CreativeCategory.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2019-2023 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.api.util; + +import org.checkerframework.checker.nullness.qual.NonNull; + +/** + * Represents the creative menu categories or tabs. + */ +public enum CreativeCategory { + COMMANDS("commands", 1), + CONSTRUCTION("construction", 2), + EQUIPMENT("equipment", 3), + ITEMS("items", 4), + NATURE("nature", 5), + NONE("none", 6); + + private final String internalName; + private final int id; + + CreativeCategory(String internalName, int id) { + this.internalName = internalName; + this.id = id; + } + + /** + * Gets the internal name of the category. + * + * @return the name of the category + */ + @NonNull public String internalName() { + return internalName; + } + + /** + * Gets the internal ID of the category. + * + * @return the ID of the category + */ + public int id() { + return id; + } +} diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts index 3d1fb47f7..c0c683920 100644 --- a/build-logic/build.gradle.kts +++ b/build-logic/build.gradle.kts @@ -8,7 +8,7 @@ repositories { } dependencies { - implementation("net.kyori", "indra-common", "3.0.1") + implementation("net.kyori", "indra-common", "3.1.1") implementation("com.github.johnrengelman", "shadow", "7.1.3-SNAPSHOT") // Within the gradle plugin classpath, there is a version conflict between loom and some other diff --git a/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts b/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts index 709867300..93d702939 100644 --- a/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts @@ -34,4 +34,4 @@ tasks { ) } } -} +} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 2eed8de91..4cb5b0223 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,9 +5,15 @@ plugins { } allprojects { - group = "org.geysermc.geyser" - version = "2.1.2-SNAPSHOT" - description = "Allows for players from Minecraft: Bedrock Edition to join Minecraft: Java Edition servers." + group = properties["group"] as String + "." + properties["id"] as String + version = properties["version"] as String + description = properties["description"] as String +} + +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(16)) + } } val platforms = setOf( diff --git a/core/src/main/java/org/geysermc/geyser/Constants.java b/core/src/main/java/org/geysermc/geyser/Constants.java index 12e8b0d8c..5de8e6e6b 100644 --- a/core/src/main/java/org/geysermc/geyser/Constants.java +++ b/core/src/main/java/org/geysermc/geyser/Constants.java @@ -41,6 +41,10 @@ public final class Constants { static final String SAVED_REFRESH_TOKEN_FILE = "saved-refresh-tokens.json"; + public static final String GEYSER_CUSTOM_NAMESPACE = "geyser_custom"; + + public static final String MINECRAFT_SKIN_SERVER_URL = "https://textures.minecraft.net/texture/"; + static { URI wsUri = null; try { diff --git a/core/src/main/java/org/geysermc/geyser/configuration/GeyserCustomSkullConfiguration.java b/core/src/main/java/org/geysermc/geyser/configuration/GeyserCustomSkullConfiguration.java new file mode 100644 index 000000000..1af3578a3 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/configuration/GeyserCustomSkullConfiguration.java @@ -0,0 +1,65 @@ +/* + * 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.configuration; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +@JsonIgnoreProperties(ignoreUnknown = true) +@SuppressWarnings("FieldMayBeFinal") // Jackson requires that the fields are not final +public class GeyserCustomSkullConfiguration { + @JsonProperty("player-usernames") + private List playerUsernames; + + @JsonProperty("player-uuids") + private List playerUUIDs; + + @JsonProperty("player-profiles") + private List playerProfiles; + + @JsonProperty("skin-hashes") + private List skinHashes; + + public List getPlayerUsernames() { + return Objects.requireNonNullElse(playerUsernames, Collections.emptyList()); + } + + public List getPlayerUUIDs() { + return Objects.requireNonNullElse(playerUUIDs, Collections.emptyList()); + } + + public List getPlayerProfiles() { + return Objects.requireNonNullElse(playerProfiles, Collections.emptyList()); + } + + public List getPlayerSkinHashes() { + return Objects.requireNonNullElse(skinHashes, Collections.emptyList()); + } +} 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 01365be34..c81fe6598 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 @@ -77,15 +77,18 @@ public class BlockInventoryHolder extends InventoryHolder { // (This could be a virtual inventory that the player is opening) if (checkInteractionPosition(session)) { // Then, check to see if the interacted block is valid for this inventory by ensuring the block state identifier is valid + // and the bedrock block is vanilla int javaBlockId = session.getGeyser().getWorldManager().getBlockAt(session, session.getLastInteractionBlockPosition()); - String[] javaBlockString = BlockRegistries.JAVA_BLOCKS.getOrDefault(javaBlockId, BlockMapping.AIR).getJavaIdentifier().split("\\["); - if (isValidBlock(javaBlockString)) { - // We can safely use this block - inventory.setHolderPosition(session.getLastInteractionBlockPosition()); - ((Container) inventory).setUsingRealBlock(true, javaBlockString[0]); - setCustomName(session, session.getLastInteractionBlockPosition(), inventory, javaBlockId); + if (!BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.get().containsKey(javaBlockId)) { + String[] javaBlockString = BlockRegistries.JAVA_BLOCKS.getOrDefault(javaBlockId, BlockMapping.AIR).getJavaIdentifier().split("\\["); + if (isValidBlock(javaBlockString)) { + // We can safely use this block + inventory.setHolderPosition(session.getLastInteractionBlockPosition()); + ((Container) inventory).setUsingRealBlock(true, javaBlockString[0]); + setCustomName(session, session.getLastInteractionBlockPosition(), inventory, javaBlockId); - return true; + return true; + } } } @@ -97,7 +100,7 @@ public class BlockInventoryHolder extends InventoryHolder { UpdateBlockPacket blockPacket = new UpdateBlockPacket(); blockPacket.setDataLayer(0); blockPacket.setBlockPosition(position); - blockPacket.setDefinition(session.getBlockMappings().getBedrockBlock(defaultJavaBlockState)); + blockPacket.setDefinition(session.getBlockMappings().getVanillaBedrockBlock(defaultJavaBlockState)); blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY); session.sendUpstreamPacket(blockPacket); inventory.setHolderPosition(position); diff --git a/core/src/main/java/org/geysermc/geyser/item/mappings/versions/MappingsReader_v1.java b/core/src/main/java/org/geysermc/geyser/item/mappings/versions/MappingsReader_v1.java deleted file mode 100644 index e08190aff..000000000 --- a/core/src/main/java/org/geysermc/geyser/item/mappings/versions/MappingsReader_v1.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * 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.item.mappings.versions; - -import com.fasterxml.jackson.databind.JsonNode; -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.item.exception.InvalidCustomMappingsFileException; - -import java.nio.file.Path; -import java.util.function.BiConsumer; - -public class MappingsReader_v1 extends MappingsReader { - @Override - public void readMappings(Path file, JsonNode mappingsRoot, BiConsumer consumer) { - this.readItemMappings(file, mappingsRoot, consumer); - } - - public void readItemMappings(Path file, JsonNode mappingsRoot, BiConsumer consumer) { - JsonNode itemsNode = mappingsRoot.get("items"); - - if (itemsNode != null && itemsNode.isObject()) { - itemsNode.fields().forEachRemaining(entry -> { - if (entry.getValue().isArray()) { - entry.getValue().forEach(data -> { - try { - CustomItemData customItemData = this.readItemMappingEntry(data); - consumer.accept(entry.getKey(), customItemData); - } catch (InvalidCustomMappingsFileException e) { - GeyserImpl.getInstance().getLogger().error("Error in custom mapping file: " + file.toString(), e); - } - }); - } - }); - } - } - - private CustomItemOptions readItemCustomItemOptions(JsonNode node) { - CustomItemOptions.Builder customItemOptions = CustomItemOptions.builder(); - - JsonNode customModelData = node.get("custom_model_data"); - if (customModelData != null && customModelData.isInt()) { - customItemOptions.customModelData(customModelData.asInt()); - } - - JsonNode damagePredicate = node.get("damage_predicate"); - if (damagePredicate != null && damagePredicate.isInt()) { - customItemOptions.damagePredicate(damagePredicate.asInt()); - } - - JsonNode unbreakable = node.get("unbreakable"); - if (unbreakable != null && unbreakable.isBoolean()) { - customItemOptions.unbreakable(unbreakable.asBoolean()); - } - - JsonNode defaultItem = node.get("default"); - if (defaultItem != null && defaultItem.isBoolean()) { - customItemOptions.defaultItem(defaultItem.asBoolean()); - } - - return customItemOptions.build(); - } - - @Override - public CustomItemData readItemMappingEntry(JsonNode node) throws InvalidCustomMappingsFileException { - if (node == null || !node.isObject()) { - throw new InvalidCustomMappingsFileException("Invalid item mappings entry"); - } - - JsonNode name = node.get("name"); - if (name == null || !name.isTextual() || name.asText().isEmpty()) { - throw new InvalidCustomMappingsFileException("An item entry has no name"); - } - - CustomItemData.Builder customItemData = CustomItemData.builder() - .name(name.asText()) - .customItemOptions(this.readItemCustomItemOptions(node)); - - //The next entries are optional - if (node.has("display_name")) { - customItemData.displayName(node.get("display_name").asText()); - } - - if (node.has("icon")) { - customItemData.icon(node.get("icon").asText()); - } - - if (node.has("allow_offhand")) { - customItemData.allowOffhand(node.get("allow_offhand").asBoolean()); - } - - if (node.has("display_handheld")) { - customItemData.displayHandheld(node.get("display_handheld").asBoolean()); - } - - if (node.has("texture_size")) { - customItemData.textureSize(node.get("texture_size").asInt()); - } - - if (node.has("render_offsets")) { - JsonNode tmpNode = node.get("render_offsets"); - - customItemData.renderOffsets(fromJsonNode(tmpNode)); - } - - return customItemData.build(); - } -} diff --git a/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java b/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java index 5c985c732..662448a52 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java @@ -32,6 +32,7 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.MinecraftLocale; +import org.geysermc.geyser.translator.text.MessageTranslator; public class PlayerHeadItem extends Item { public PlayerHeadItem(String javaIdentifier, Builder builder) { @@ -42,29 +43,35 @@ public class PlayerHeadItem extends Item { public void translateNbtToBedrock(@NonNull GeyserSession session, @NonNull CompoundTag tag) { super.translateNbtToBedrock(session, tag); - Tag display = tag.get("display"); - if (!(display instanceof CompoundTag) || !((CompoundTag) display).contains("Name")) { - Tag skullOwner = tag.get("SkullOwner"); - if (skullOwner != null) { + CompoundTag displayTag; + if (tag.get("display") instanceof CompoundTag existingDisplayTag) { + displayTag = existingDisplayTag; + } else { + displayTag = new CompoundTag("display"); + tag.put(displayTag); + } + + if (displayTag.get("Name") instanceof StringTag nameTag) { + // Custom names are always yellow and italic + displayTag.put(new StringTag("Name", ChatColor.YELLOW + ChatColor.ITALIC + MessageTranslator.convertMessageLenient(nameTag.getValue(), session.locale()))); + } else { + if (tag.contains("SkullOwner")) { StringTag name; - if (skullOwner instanceof StringTag) { - name = (StringTag) skullOwner; + Tag skullOwner = tag.get("SkullOwner"); + if (skullOwner instanceof StringTag skullName) { + name = skullName; } else { - StringTag skullName; - if (skullOwner instanceof CompoundTag && (skullName = ((CompoundTag) skullOwner).get("Name")) != null) { + if (skullOwner instanceof CompoundTag && ((CompoundTag) skullOwner).get("Name") instanceof StringTag skullName) { name = skullName; } else { - session.getGeyser().getLogger().debug("Not sure how to handle skull head item display. " + tag); + // No name found so default to "Player Head" + displayTag.put(new StringTag("Name", ChatColor.RESET + ChatColor.YELLOW + MinecraftLocale.getLocaleString("block.minecraft.player_head", session.locale()))); return; } } // Add correct name of player skull - // TODO: It's always yellow, even with a custom name. Handle? String displayName = ChatColor.RESET + ChatColor.YELLOW + MinecraftLocale.getLocaleString("block.minecraft.player_head.named", session.locale()).replace("%s", name.getValue()); - if (!(display instanceof CompoundTag)) { - tag.put(display = new CompoundTag("display")); - } - ((CompoundTag) display).put(new StringTag("Name", displayName)); + displayTag.put(new StringTag("Name", displayName)); } } } diff --git a/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockComponents.java b/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockComponents.java new file mode 100644 index 000000000..e43e168ee --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockComponents.java @@ -0,0 +1,305 @@ +/* + * 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.level.block; + +import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectMaps; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import lombok.Value; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.api.block.custom.component.BoxComponent; +import org.geysermc.geyser.api.block.custom.component.CustomBlockComponents; +import org.geysermc.geyser.api.block.custom.component.GeometryComponent; +import org.geysermc.geyser.api.block.custom.component.MaterialInstance; +import org.geysermc.geyser.api.block.custom.component.PlacementConditions; +import org.geysermc.geyser.api.block.custom.component.TransformationComponent; +import org.jetbrains.annotations.NotNull; + +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +@Value +public class GeyserCustomBlockComponents implements CustomBlockComponents { + BoxComponent selectionBox; + BoxComponent collisionBox; + String displayName; + GeometryComponent geometry; + Map materialInstances; + List placementFilter; + Float destructibleByMining; + Float friction; + Integer lightEmission; + Integer lightDampening; + TransformationComponent transformation; + boolean unitCube; + boolean placeAir; + Set tags; + + private GeyserCustomBlockComponents(CustomBlockComponentsBuilder builder) { + this.selectionBox = builder.selectionBox; + this.collisionBox = builder.collisionBox; + this.displayName = builder.displayName; + this.geometry = builder.geometry; + if (builder.materialInstances.isEmpty()) { + this.materialInstances = Object2ObjectMaps.emptyMap(); + } else { + this.materialInstances = Object2ObjectMaps.unmodifiable(new Object2ObjectArrayMap<>(builder.materialInstances)); + } + this.placementFilter = builder.placementFilter; + this.destructibleByMining = builder.destructibleByMining; + this.friction = builder.friction; + this.lightEmission = builder.lightEmission; + this.lightDampening = builder.lightDampening; + this.transformation = builder.transformation; + this.unitCube = builder.unitCube; + this.placeAir = builder.placeAir; + if (builder.tags.isEmpty()) { + this.tags = Set.of(); + } else { + this.tags = Set.copyOf(builder.tags); + } + } + + @Override + public BoxComponent selectionBox() { + return selectionBox; + } + + @Override + public BoxComponent collisionBox() { + return collisionBox; + } + + @Override + public String displayName() { + return displayName; + } + + @Override + public GeometryComponent geometry() { + return geometry; + } + + @Override + public @NonNull Map materialInstances() { + return materialInstances; + } + + @Override + public List placementFilter() { + return placementFilter; + } + + @Override + public Float destructibleByMining() { + return destructibleByMining; + } + + @Override + public Float friction() { + return friction; + } + + @Override + public Integer lightEmission() { + return lightEmission; + } + + @Override + public Integer lightDampening() { + return lightDampening; + } + + @Override + public TransformationComponent transformation() { + return transformation; + } + + @Override + public boolean unitCube() { + return unitCube; + } + + @Override + public boolean placeAir() { + return placeAir; + } + + @Override + public @NotNull Set tags() { + return tags; + } + + public static class CustomBlockComponentsBuilder implements Builder { + protected BoxComponent selectionBox; + protected BoxComponent collisionBox; + protected String displayName; + protected GeometryComponent geometry; + protected final Object2ObjectMap materialInstances = new Object2ObjectOpenHashMap<>(); + protected List placementFilter; + protected Float destructibleByMining; + protected Float friction; + protected Integer lightEmission; + protected Integer lightDampening; + protected TransformationComponent transformation; + protected boolean unitCube = false; + protected boolean placeAir = false; + protected final Set tags = new HashSet<>(); + + private void validateBox(BoxComponent box) { + if (box == null) { + return; + } + if (box.sizeX() < 0 || box.sizeY() < 0 || box.sizeZ() < 0) { + throw new IllegalArgumentException("Box size must be non-negative."); + } + float minX = box.originX() + 8; + float minY = box.originY(); + float minZ = box.originZ() + 8; + float maxX = minX + box.sizeX(); + float maxY = minY + box.sizeY(); + float maxZ = minZ + box.sizeZ(); + if (minX < 0 || minY < 0 || minZ < 0 || maxX > 16 || maxY > 16 || maxZ > 16) { + throw new IllegalArgumentException("Box bounds must be within (0, 0, 0) and (16, 16, 16). Recieved: (" + minX + ", " + minY + ", " + minZ + ") to (" + maxX + ", " + maxY + ", " + maxZ + ")"); + } + } + + @Override + public Builder selectionBox(BoxComponent selectionBox) { + validateBox(selectionBox); + this.selectionBox = selectionBox; + return this; + } + + @Override + public Builder collisionBox(BoxComponent collisionBox) { + validateBox(collisionBox); + this.collisionBox = collisionBox; + return this; + } + + @Override + public Builder displayName(String displayName) { + this.displayName = displayName; + return this; + } + + @Override + public Builder geometry(GeometryComponent geometry) { + this.geometry = geometry; + return this; + } + + @Override + public Builder materialInstance(@NotNull String name, @NotNull MaterialInstance materialInstance) { + this.materialInstances.put(name, materialInstance); + return this; + } + + @Override + public Builder placementFilter(List placementFilter) { + this.placementFilter = placementFilter; + return this; + } + + @Override + public Builder destructibleByMining(Float destructibleByMining) { + if (destructibleByMining != null && destructibleByMining < 0) { + throw new IllegalArgumentException("Destructible by mining must be non-negative"); + } + this.destructibleByMining = destructibleByMining; + return this; + } + + @Override + public Builder friction(Float friction) { + if (friction != null) { + if (friction < 0 || friction > 1) { + throw new IllegalArgumentException("Friction must be in the range 0-1"); + } + } + this.friction = friction; + return this; + } + + @Override + public Builder lightEmission(Integer lightEmission) { + if (lightEmission != null) { + if (lightEmission < 0 || lightEmission > 15) { + throw new IllegalArgumentException("Light emission must be in the range 0-15"); + } + } + this.lightEmission = lightEmission; + return this; + } + + @Override + public Builder lightDampening(Integer lightDampening) { + if (lightDampening != null) { + if (lightDampening < 0 || lightDampening > 15) { + throw new IllegalArgumentException("Light dampening must be in the range 0-15"); + } + } + this.lightDampening = lightDampening; + return this; + } + + @Override + public Builder transformation(TransformationComponent transformation) { + if (transformation.rx() % 90 != 0 || transformation.ry() % 90 != 0 || transformation.rz() % 90 != 0) { + throw new IllegalArgumentException("Rotation of transformation must be a multiple of 90 degrees."); + } + this.transformation = transformation; + return this; + } + + @Override + public Builder unitCube(boolean unitCube) { + this.unitCube = unitCube; + return this; + } + + @Override + public Builder placeAir(boolean placeAir) { + this.placeAir = placeAir; + return this; + } + + @Override + public Builder tags(Set tags) { + this.tags.addAll(tags); + return this; + } + + @Override + public CustomBlockComponents build() { + return new GeyserCustomBlockComponents(this); + } + } +} diff --git a/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockData.java b/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockData.java new file mode 100644 index 000000000..413a4d1ed --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockData.java @@ -0,0 +1,217 @@ +/* + * 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.level.block; + +import it.unimi.dsi.fastutil.objects.*; +import lombok.RequiredArgsConstructor; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.Constants; +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.block.custom.CustomBlockData; +import org.geysermc.geyser.api.block.custom.CustomBlockPermutation; +import org.geysermc.geyser.api.block.custom.CustomBlockState; +import org.geysermc.geyser.api.block.custom.component.CustomBlockComponents; +import org.geysermc.geyser.api.block.custom.property.CustomBlockProperty; +import org.geysermc.geyser.api.block.custom.property.PropertyType; +import org.geysermc.geyser.api.util.CreativeCategory; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.Nullable; + +import java.util.List; +import java.util.Map; + +@RequiredArgsConstructor +public class GeyserCustomBlockData implements CustomBlockData { + private final String name; + private final boolean includedInCreativeInventory; + private final CreativeCategory creativeCategory; + private final String creativeGroup; + private final CustomBlockComponents components; + private final Map> properties; + private final List permutations; + + private final Map defaultProperties; + + GeyserCustomBlockData(CustomBlockDataBuilder builder) { + this.name = builder.name; + if (name == null) { + throw new IllegalStateException("Name must be set"); + } + + this.includedInCreativeInventory = builder.includedInCreativeInventory; + this.creativeCategory = builder.creativeCategory; + this.creativeGroup = builder.creativeGroup; + + this.components = builder.components; + + if (!builder.properties.isEmpty()) { + this.properties = Object2ObjectMaps.unmodifiable(new Object2ObjectArrayMap<>(builder.properties)); + Object2ObjectMap defaultProperties = new Object2ObjectOpenHashMap<>(this.properties.size()); + for (CustomBlockProperty property : properties.values()) { + if (property.values().size() > 16) { + GeyserImpl.getInstance().getLogger().warning(property.name() + " contains more than 16 values, but BDS specifies it should not. This may break in future versions."); + } + if (property.values().stream().distinct().count() != property.values().size()) { + throw new IllegalStateException(property.name() + " has duplicate values."); + } + if (property.values().isEmpty()) { + throw new IllegalStateException(property.name() + " contains no values."); + } + defaultProperties.put(property.name(), property.values().get(0)); + } + this.defaultProperties = Object2ObjectMaps.unmodifiable(defaultProperties); + } else { + this.properties = Object2ObjectMaps.emptyMap(); + this.defaultProperties = Object2ObjectMaps.emptyMap(); + } + + if (!builder.permutations.isEmpty()) { + this.permutations = List.of(builder.permutations.toArray(new CustomBlockPermutation[0])); + } else { + this.permutations = ObjectLists.emptyList(); + } + } + + @Override + public @NonNull String name() { + return name; + } + + @Override + public @NonNull String identifier() { + return Constants.GEYSER_CUSTOM_NAMESPACE + ":" + name; + } + + @Override + public boolean includedInCreativeInventory() { + return includedInCreativeInventory; + } + + @Override + public @Nullable CreativeCategory creativeCategory() { + return creativeCategory; + } + + @Override + public @Nullable String creativeGroup() { + return creativeGroup; + } + + @Override + public CustomBlockComponents components() { + return components; + } + + @Override + public @NonNull Map> properties() { + return properties; + } + + @Override + public @NonNull List permutations() { + return permutations; + } + + @Override + public @NonNull CustomBlockState defaultBlockState() { + return new GeyserCustomBlockState(this, defaultProperties); + } + + @Override + public CustomBlockState.@NotNull Builder blockStateBuilder() { + return new GeyserCustomBlockState.CustomBlockStateBuilder(this); + } + + public static class CustomBlockDataBuilder implements Builder { + private String name; + private boolean includedInCreativeInventory; + private CreativeCategory creativeCategory; + private String creativeGroup; + private CustomBlockComponents components; + private final Object2ObjectMap> properties = new Object2ObjectOpenHashMap<>(); + private List permutations = ObjectLists.emptyList(); + + @Override + public Builder name(@NonNull String name) { + this.name = name; + return this; + } + + @Override + public Builder includedInCreativeInventory(boolean includedInCreativeInventory) { + this.includedInCreativeInventory = includedInCreativeInventory; + return this; + } + + @Override + public Builder creativeCategory(@Nullable CreativeCategory creativeCategory) { + this.creativeCategory = creativeCategory; + return this; + } + + @Override + public Builder creativeGroup(@Nullable String creativeGroup) { + this.creativeGroup = creativeGroup; + return this; + } + + @Override + public Builder components(@NonNull CustomBlockComponents components) { + this.components = components; + return this; + } + + @Override + public Builder booleanProperty(@NonNull String propertyName) { + this.properties.put(propertyName, new GeyserCustomBlockProperty<>(propertyName, List.of((byte) 0, (byte) 1), PropertyType.booleanProp())); + return this; + } + + @Override + public Builder intProperty(@NonNull String propertyName, List values) { + this.properties.put(propertyName, new GeyserCustomBlockProperty<>(propertyName, values, PropertyType.integerProp())); + return this; + } + + @Override + public Builder stringProperty(@NonNull String propertyName, List values) { + this.properties.put(propertyName, new GeyserCustomBlockProperty<>(propertyName, values, PropertyType.stringProp())); + return this; + } + + @Override + public Builder permutations(@NonNull List permutations) { + this.permutations = permutations; + return this; + } + + @Override + public CustomBlockData build() { + return new GeyserCustomBlockData(this); + } + } +} diff --git a/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockProperty.java b/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockProperty.java new file mode 100644 index 000000000..139df1fcd --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockProperty.java @@ -0,0 +1,44 @@ +/* + * 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.level.block; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.api.block.custom.property.CustomBlockProperty; +import org.geysermc.geyser.api.block.custom.property.PropertyType; + +import java.util.List; + +/** + * A custom block property that can be used to store custom data for a block. + * + * @param The type of the property + * @param name The name of the property + * @param values The values of the property + * @param type The type of the property + */ +public record GeyserCustomBlockProperty(@NonNull String name, @NonNull List values, + @NonNull PropertyType type) implements CustomBlockProperty { +} diff --git a/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockState.java b/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockState.java new file mode 100644 index 000000000..576bd9743 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockState.java @@ -0,0 +1,112 @@ +/* + * 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.level.block; + +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectMaps; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import lombok.RequiredArgsConstructor; +import lombok.Value; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.api.block.custom.CustomBlockData; +import org.geysermc.geyser.api.block.custom.CustomBlockState; +import org.geysermc.geyser.api.block.custom.property.CustomBlockProperty; + +import java.util.Map; + +@Value +public class GeyserCustomBlockState implements CustomBlockState { + CustomBlockData block; + Map properties; + + @Override + public @NonNull CustomBlockData block() { + return block; + } + + @Override + public @NonNull String name() { + return block.name(); + } + + @SuppressWarnings("unchecked") + @Override + public @NonNull T property(String propertyName) { + return (T) properties.get(propertyName); + } + + @Override + public @NonNull Map properties() { + return properties; + } + + @RequiredArgsConstructor + public static class CustomBlockStateBuilder implements CustomBlockState.Builder { + private final CustomBlockData blockData; + private final Object2ObjectMap properties = new Object2ObjectOpenHashMap<>(); + + @Override + public Builder booleanProperty(@NonNull String propertyName, boolean value) { + properties.put(propertyName, value ? (byte) 1 : (byte) 0); + return this; + } + + @Override + public Builder intProperty(@NonNull String propertyName, int value) { + properties.put(propertyName, value); + return this; + } + + @Override + public Builder stringProperty(@NonNull String propertyName, @NonNull String value) { + properties.put(propertyName, value); + return this; + } + + @Override + public CustomBlockState build() { + for (String propertyName : blockData.properties().keySet()) { + if (!properties.containsKey(propertyName)) { + throw new IllegalArgumentException("Missing property: " + propertyName); + } + } + + for (Map.Entry entry : properties.entrySet()) { + String propertyName = entry.getKey(); + Object propertyValue = entry.getValue(); + + CustomBlockProperty property = blockData.properties().get(propertyName); + if (property == null) { + throw new IllegalArgumentException("Unknown property: " + propertyName); + } else if (!property.values().contains(propertyValue)) { + throw new IllegalArgumentException("Invalid value: " + propertyValue + " for property: " + propertyName); + } + } + + return new GeyserCustomBlockState(blockData, Object2ObjectMaps.unmodifiable(properties)); + } + } +} diff --git a/core/src/main/java/org/geysermc/geyser/level/block/GeyserGeometryComponent.java b/core/src/main/java/org/geysermc/geyser/level/block/GeyserGeometryComponent.java new file mode 100644 index 000000000..c23fc87a2 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/GeyserGeometryComponent.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2019-2023 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.level.block; + +import lombok.RequiredArgsConstructor; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.geyser.api.block.custom.component.GeometryComponent; + +import java.util.Map; + +@RequiredArgsConstructor +public class GeyserGeometryComponent implements GeometryComponent { + private final String identifier; + private final Map boneVisibility; + + GeyserGeometryComponent(GeometryComponentBuilder builder) { + this.identifier = builder.identifier; + this.boneVisibility = builder.boneVisibility; + } + + @Override + public @NonNull String identifier() { + return identifier; + } + + @Override + public @Nullable Map boneVisibility() { + return boneVisibility; + } + + public static class GeometryComponentBuilder implements Builder { + private String identifier; + private Map boneVisibility; + + @Override + public GeometryComponent.Builder identifier(@NonNull String identifier) { + this.identifier = identifier; + return this; + } + + @Override + public GeometryComponent.Builder boneVisibility(@Nullable Map boneVisibility) { + this.boneVisibility = boneVisibility; + return this; + } + + @Override + public GeometryComponent build() { + return new GeyserGeometryComponent(this); + } + } +} diff --git a/core/src/main/java/org/geysermc/geyser/level/block/GeyserJavaBlockState.java b/core/src/main/java/org/geysermc/geyser/level/block/GeyserJavaBlockState.java new file mode 100644 index 000000000..725afe6df --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/GeyserJavaBlockState.java @@ -0,0 +1,161 @@ +package org.geysermc.geyser.level.block; + +import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.geyser.api.block.custom.nonvanilla.JavaBlockState; +import org.geysermc.geyser.api.block.custom.nonvanilla.JavaBoundingBox; + +public class GeyserJavaBlockState implements JavaBlockState { + String identifier; + int javaId; + int stateGroupId; + float blockHardness; + boolean waterlogged; + JavaBoundingBox[] collision; + boolean canBreakWithHand; + String pickItem; + String pistonBehavior; + boolean hasBlockEntity; + + private GeyserJavaBlockState(JavaBlockStateBuilder builder) { + this.identifier = builder.identifier; + this.javaId = builder.javaId; + this.stateGroupId = builder.stateGroupId; + this.blockHardness = builder.blockHardness; + this.waterlogged = builder.waterlogged; + this.collision = builder.collision; + this.canBreakWithHand = builder.canBreakWithHand; + this.pickItem = builder.pickItem; + this.pistonBehavior = builder.pistonBehavior; + this.hasBlockEntity = builder.hasBlockEntity; + } + + @Override + public @NonNull String identifier() { + return identifier; + } + + @Override + public @NonNegative int javaId() { + return javaId; + } + + @Override + public @NonNegative int stateGroupId() { + return stateGroupId; + } + + @Override + public @NonNegative float blockHardness() { + return blockHardness; + } + + @Override + public @NonNull boolean waterlogged() { + return waterlogged; + } + + @Override + public @NonNull JavaBoundingBox[] collision() { + return collision; + } + + @Override + public @NonNull boolean canBreakWithHand() { + return canBreakWithHand; + } + + @Override + public @Nullable String pickItem() { + return pickItem; + } + + @Override + public @Nullable String pistonBehavior() { + return pistonBehavior; + } + + @Override + public @Nullable boolean hasBlockEntity() { + return hasBlockEntity; + } + + public static class JavaBlockStateBuilder implements Builder { + private String identifier; + private int javaId; + private int stateGroupId; + private float blockHardness; + private boolean waterlogged; + private JavaBoundingBox[] collision; + private boolean canBreakWithHand; + private String pickItem; + private String pistonBehavior; + private boolean hasBlockEntity; + + @Override + public Builder identifier(@NonNull String identifier) { + this.identifier = identifier; + return this; + } + + @Override + public Builder javaId(@NonNegative int javaId) { + this.javaId = javaId; + return this; + } + + @Override + public Builder stateGroupId(@NonNegative int stateGroupId) { + this.stateGroupId = stateGroupId; + return this; + } + + @Override + public Builder blockHardness(@NonNegative float blockHardness) { + this.blockHardness = blockHardness; + return this; + } + + @Override + public Builder waterlogged(@NonNull boolean waterlogged) { + this.waterlogged = waterlogged; + return this; + } + + @Override + public Builder collision(@NonNull JavaBoundingBox[] collision) { + this.collision = collision; + return this; + } + + @Override + public Builder canBreakWithHand(@NonNull boolean canBreakWithHand) { + this.canBreakWithHand = canBreakWithHand; + return this; + } + + @Override + public Builder pickItem(@Nullable String pickItem) { + this.pickItem = pickItem; + return this; + } + + @Override + public Builder pistonBehavior(@Nullable String pistonBehavior) { + this.pistonBehavior = pistonBehavior; + return this; + } + + @Override + public Builder hasBlockEntity(@Nullable boolean hasBlockEntity) { + this.hasBlockEntity = hasBlockEntity; + return this; + } + + @Override + public JavaBlockState build() { + return new GeyserJavaBlockState(this); + } + } +} diff --git a/core/src/main/java/org/geysermc/geyser/level/block/GeyserMaterialInstance.java b/core/src/main/java/org/geysermc/geyser/level/block/GeyserMaterialInstance.java new file mode 100644 index 000000000..80a880152 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/GeyserMaterialInstance.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2019-2023 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.level.block; + +import lombok.RequiredArgsConstructor; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.geyser.api.block.custom.component.MaterialInstance; + +@RequiredArgsConstructor +public class GeyserMaterialInstance implements MaterialInstance { + private final String texture; + private final String renderMethod; + private final boolean faceDimming; + private final boolean ambientOcclusion; + + GeyserMaterialInstance(MaterialInstanceBuilder builder) { + this.texture = builder.texture; + this.renderMethod = builder.renderMethod; + this.faceDimming = builder.faceDimming; + this.ambientOcclusion = builder.ambientOcclusion; + } + + @Override + public @NonNull String texture() { + return texture; + } + + @Override + public @Nullable String renderMethod() { + return renderMethod; + } + + @Override + public @Nullable boolean faceDimming() { + return faceDimming; + } + + @Override + public @Nullable boolean ambientOcclusion() { + return ambientOcclusion; + } + + public static class MaterialInstanceBuilder implements Builder { + private String texture; + private String renderMethod; + private boolean faceDimming; + private boolean ambientOcclusion; + + @Override + public Builder texture(@NonNull String texture) { + this.texture = texture; + return this; + } + + @Override + public Builder renderMethod(@Nullable String renderMethod) { + this.renderMethod = renderMethod; + return this; + } + + @Override + public Builder faceDimming(@Nullable boolean faceDimming) { + this.faceDimming = faceDimming; + return this; + } + + @Override + public Builder ambientOcclusion(@Nullable boolean ambientOcclusion) { + this.ambientOcclusion = ambientOcclusion; + return this; + } + + @Override + public MaterialInstance build() { + return new GeyserMaterialInstance(this); + } + } +} diff --git a/core/src/main/java/org/geysermc/geyser/level/block/GeyserNonVanillaCustomBlockData.java b/core/src/main/java/org/geysermc/geyser/level/block/GeyserNonVanillaCustomBlockData.java new file mode 100644 index 000000000..8b5056a6f --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/GeyserNonVanillaCustomBlockData.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2019-2023 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.level.block; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.geyser.api.block.custom.CustomBlockPermutation; +import org.geysermc.geyser.api.block.custom.NonVanillaCustomBlockData; +import org.geysermc.geyser.api.block.custom.component.CustomBlockComponents; +import org.geysermc.geyser.api.util.CreativeCategory; + +import java.util.List; + +public class GeyserNonVanillaCustomBlockData extends GeyserCustomBlockData implements NonVanillaCustomBlockData { + private final String namespace; + + GeyserNonVanillaCustomBlockData(NonVanillaCustomBlockDataBuilder builder) { + super(builder); + + this.namespace = builder.namespace; + if (namespace == null) { + throw new IllegalStateException("Identifier must be set"); + } + } + + @Override + public @NonNull String identifier() { + return this.namespace + ":" + super.name(); + } + + @Override + public @NonNull String namespace() { + return this.namespace; + } + + public static class NonVanillaCustomBlockDataBuilder extends CustomBlockDataBuilder implements NonVanillaCustomBlockData.Builder { + private String namespace; + + @Override + public NonVanillaCustomBlockDataBuilder namespace(@NonNull String namespace) { + this.namespace = namespace; + return this; + } + + @Override + public NonVanillaCustomBlockDataBuilder name(@NonNull String name) { + return (NonVanillaCustomBlockDataBuilder) super.name(name); + } + + @Override + public NonVanillaCustomBlockDataBuilder includedInCreativeInventory(boolean includedInCreativeInventory) { + return (NonVanillaCustomBlockDataBuilder) super.includedInCreativeInventory(includedInCreativeInventory); + } + + @Override + public NonVanillaCustomBlockDataBuilder creativeCategory(@Nullable CreativeCategory creativeCategories) { + return (NonVanillaCustomBlockDataBuilder) super.creativeCategory(creativeCategories); + } + + @Override + public NonVanillaCustomBlockDataBuilder creativeGroup(@Nullable String creativeGroup) { + return (NonVanillaCustomBlockDataBuilder) super.creativeGroup(creativeGroup); + } + + @Override + public NonVanillaCustomBlockDataBuilder components(@NonNull CustomBlockComponents components) { + return (NonVanillaCustomBlockDataBuilder) super.components(components); + } + + @Override + public NonVanillaCustomBlockDataBuilder booleanProperty(@NonNull String propertyName) { + return (NonVanillaCustomBlockDataBuilder) super.booleanProperty(propertyName); + } + + @Override + public NonVanillaCustomBlockDataBuilder intProperty(@NonNull String propertyName, List values) { + return (NonVanillaCustomBlockDataBuilder) super.intProperty(propertyName, values); + } + + @Override + public NonVanillaCustomBlockDataBuilder stringProperty(@NonNull String propertyName, List values) { + return (NonVanillaCustomBlockDataBuilder) super.stringProperty(propertyName, values); + } + + @Override + public NonVanillaCustomBlockDataBuilder permutations(@NonNull List permutations) { + return (NonVanillaCustomBlockDataBuilder) super.permutations(permutations); + } + + @Override + public NonVanillaCustomBlockData build() { + return new GeyserNonVanillaCustomBlockData(this); + } + } +} diff --git a/core/src/main/java/org/geysermc/geyser/pack/SkullResourcePackManager.java b/core/src/main/java/org/geysermc/geyser/pack/SkullResourcePackManager.java new file mode 100644 index 000000000..d9f7a6327 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/pack/SkullResourcePackManager.java @@ -0,0 +1,306 @@ +/* + * 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.pack; + +import it.unimi.dsi.fastutil.Pair; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import org.geysermc.geyser.Constants; +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.pack.ResourcePackManifest; +import org.geysermc.geyser.registry.BlockRegistries; +import org.geysermc.geyser.registry.type.CustomSkull; +import org.geysermc.geyser.skin.SkinProvider; +import org.geysermc.geyser.util.FileUtils; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.*; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.List; +import java.util.*; +import java.util.function.UnaryOperator; +import java.util.stream.Stream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipOutputStream; + +public class SkullResourcePackManager { + + private static final long RESOURCE_PACK_VERSION = 8; + + private static final Path SKULL_SKIN_CACHE_PATH = GeyserImpl.getInstance().getBootstrap().getConfigFolder().resolve("cache").resolve("player_skulls"); + + public static final Map SKULL_SKINS = new Object2ObjectOpenHashMap<>(); + + @SuppressWarnings("ResultOfMethodCallIgnored") + public static Path createResourcePack() { + Path cachePath = GeyserImpl.getInstance().getBootstrap().getConfigFolder().resolve("cache"); + try { + Files.createDirectories(cachePath); + } catch (IOException e) { + GeyserImpl.getInstance().getLogger().severe("Unable to create directories for player skull resource pack!", e); + return null; + } + cleanSkullSkinCache(); + + Path packPath = cachePath.resolve("player_skulls.mcpack"); + File packFile = packPath.toFile(); + if (BlockRegistries.CUSTOM_SKULLS.get().isEmpty() || !GeyserImpl.getInstance().getConfig().isAddNonBedrockItems()) { + packFile.delete(); // No need to keep resource pack + return null; + } + if (packFile.exists() && canReusePack(packFile)) { + GeyserImpl.getInstance().getLogger().info("Reusing cached player skull resource pack."); + return packPath; + } + + // We need to create the resource pack from scratch + GeyserImpl.getInstance().getLogger().info("Creating skull resource pack."); + packFile.delete(); + try (ZipOutputStream zipOS = new ZipOutputStream(Files.newOutputStream(packPath, StandardOpenOption.WRITE, StandardOpenOption.CREATE))) { + addBaseResources(zipOS); + addSkinTextures(zipOS); + addAttachables(zipOS); + GeyserImpl.getInstance().getLogger().info("Finished creating skull resource pack."); + return packPath; + } catch (IOException e) { + GeyserImpl.getInstance().getLogger().severe("Unable to create player skull resource pack!", e); + GeyserImpl.getInstance().getLogger().severe("Bedrock players will see dirt blocks instead of custom skull blocks."); + packFile.delete(); + } + return null; + } + + public static void cacheSkullSkin(String skinHash) throws IOException { + String skinUrl = Constants.MINECRAFT_SKIN_SERVER_URL + skinHash; + Path skinPath = SKULL_SKINS.get(skinHash); + if (skinPath != null) { + return; + } + + Files.createDirectories(SKULL_SKIN_CACHE_PATH); + skinPath = SKULL_SKIN_CACHE_PATH.resolve(skinHash + ".png"); + if (Files.exists(skinPath)) { + SKULL_SKINS.put(skinHash, skinPath); + return; + } + + BufferedImage image = SkinProvider.requestImage(skinUrl, null); + // Resize skins to 48x16 to save on space and memory + BufferedImage skullTexture = new BufferedImage(48, 16, image.getType()); + // Reorder skin parts to fit into the space + // Right, Front, Left, Back, Top, Bottom - head + // Right, Front, Left, Back, Top, Bottom - hat + Graphics g = skullTexture.createGraphics(); + // Right, Front, Left, Back of the head + g.drawImage(image, 0, 0, 32, 8, 0, 8, 32, 16, null); + // Right, Front, Left, Back of the hat + g.drawImage(image, 0, 8, 32, 16, 32, 8, 64, 16, null); + // Top and bottom of the head + g.drawImage(image, 32, 0, 48, 8, 8, 0, 24, 8, null); + // Top and bottom of the hat + g.drawImage(image, 32, 8, 48, 16, 40, 0, 56, 8, null); + g.dispose(); + image.flush(); + + ImageIO.write(skullTexture, "png", skinPath.toFile()); + SKULL_SKINS.put(skinHash, skinPath); + GeyserImpl.getInstance().getLogger().debug("Cached player skull to " + skinPath + " for " + skinHash); + } + + public static void cleanSkullSkinCache() { + try (Stream stream = Files.list(SKULL_SKIN_CACHE_PATH)) { + int removeCount = 0; + for (Path path : stream.toList()) { + String skinHash = path.getFileName().toString(); + skinHash = skinHash.substring(0, skinHash.length() - ".png".length()); + if (!SKULL_SKINS.containsKey(skinHash) && path.toFile().delete()) { + removeCount++; + } + } + if (removeCount != 0) { + GeyserImpl.getInstance().getLogger().debug("Removed " + removeCount + " unnecessary skull skins."); + } + } catch (IOException e) { + GeyserImpl.getInstance().getLogger().debug("Unable to clean up skull skin cache."); + if (GeyserImpl.getInstance().getConfig().isDebugMode()) { + e.printStackTrace(); + } + } + } + + private static void addBaseResources(ZipOutputStream zipOS) throws IOException { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(GeyserImpl.getInstance().getBootstrap().getResource("bedrock/skull_resource_pack_files.txt")))) { + List lines = reader.lines().toList(); + for (String path : lines) { + ZipEntry entry = new ZipEntry(path); + + zipOS.putNextEntry(entry); + String resourcePath = "bedrock/" + path; + switch (path) { + case "skull_resource_pack/manifest.json" -> + fillTemplate(zipOS, resourcePath, SkullResourcePackManager::fillManifestJson); + case "skull_resource_pack/textures/terrain_texture.json" -> + fillTemplate(zipOS, resourcePath, SkullResourcePackManager::fillTerrainTextureJson); + default -> zipOS.write(FileUtils.readAllBytes(resourcePath)); + } + zipOS.closeEntry(); + } + + addFloorGeometries(zipOS); + + ZipEntry entry = new ZipEntry("skull_resource_pack/pack_icon.png"); + zipOS.putNextEntry(entry); + zipOS.write(FileUtils.readAllBytes("icon.png")); + zipOS.closeEntry(); + } + } + + private static void addFloorGeometries(ZipOutputStream zipOS) throws IOException { + String template = FileUtils.readToString("bedrock/skull_resource_pack/models/blocks/player_skull_floor.geo.json"); + String[] quadrants = {"a", "b", "c", "d"}; + for (int i = 0; i < quadrants.length; i++) { + String quadrant = quadrants[i]; + float yRotation = i * 22.5f; + String contents = template + .replace("${quadrant}", quadrant) + .replace("${y_rotation}", String.valueOf(yRotation)); + + ZipEntry entry = new ZipEntry("skull_resource_pack/models/blocks/player_skull_floor_" + quadrant + ".geo.json"); + zipOS.putNextEntry(entry); + zipOS.write(contents.getBytes(StandardCharsets.UTF_8)); + zipOS.closeEntry(); + } + } + + private static void addAttachables(ZipOutputStream zipOS) throws IOException { + String template = FileUtils.readToString("bedrock/skull_resource_pack/attachables/template_attachable.json"); + for (CustomSkull skull : BlockRegistries.CUSTOM_SKULLS.get().values()) { + ZipEntry entry = new ZipEntry("skull_resource_pack/attachables/" + truncateHash(skull.getSkinHash()) + ".json"); + zipOS.putNextEntry(entry); + zipOS.write(fillAttachableJson(template, skull).getBytes(StandardCharsets.UTF_8)); + zipOS.closeEntry(); + } + } + + private static void addSkinTextures(ZipOutputStream zipOS) throws IOException { + for (Path skinPath : SKULL_SKINS.values()) { + ZipEntry entry = new ZipEntry("skull_resource_pack/textures/blocks/" + truncateHash(skinPath.getFileName().toString()) + ".png"); + zipOS.putNextEntry(entry); + try (InputStream stream = Files.newInputStream(skinPath)) { + stream.transferTo(zipOS); + } + zipOS.closeEntry(); + } + } + + private static void fillTemplate(ZipOutputStream zipOS, String path, UnaryOperator filler) throws IOException { + String template = FileUtils.readToString(path); + String result = filler.apply(template); + zipOS.write(result.getBytes(StandardCharsets.UTF_8)); + } + + private static String fillAttachableJson(String template, CustomSkull skull) { + return template.replace("${identifier}", skull.getCustomBlockData().identifier()) + .replace("${texture}", truncateHash(skull.getSkinHash())); + } + + private static String fillManifestJson(String template) { + Pair uuids = generatePackUUIDs(); + return template.replace("${uuid1}", uuids.first().toString()) + .replace("${uuid2}", uuids.second().toString()); + } + + private static String fillTerrainTextureJson(String template) { + StringBuilder textures = new StringBuilder(); + for (String skinHash : SKULL_SKINS.keySet()) { + String texture = String.format("\"geyser.%s_player_skin\":{\"textures\":\"textures/blocks/%s\"},\n", skinHash, truncateHash(skinHash)); + textures.append(texture); + } + if (textures.length() != 0) { + // Remove trailing comma + textures.delete(textures.length() - 2, textures.length()); + } + return template.replace("${texture_data}", textures); + } + + private static Pair generatePackUUIDs() { + UUID uuid1 = UUID.randomUUID(); + UUID uuid2 = UUID.randomUUID(); + try { + MessageDigest md = MessageDigest.getInstance("SHA-256"); + for (int i = 0; i < 8; i++) { + md.update((byte) ((RESOURCE_PACK_VERSION >> (i * 8)) & 0xFF)); + } + SKULL_SKINS.keySet().stream() + .sorted() + .map(hash -> hash.getBytes(StandardCharsets.UTF_8)) + .forEach(md::update); + + ByteBuffer skinHashes = ByteBuffer.wrap(md.digest()); + uuid1 = new UUID(skinHashes.getLong(), skinHashes.getLong()); + uuid2 = new UUID(skinHashes.getLong(), skinHashes.getLong()); + } catch (NoSuchAlgorithmException e) { + GeyserImpl.getInstance().getLogger().severe("Unable to get SHA-256 Message Digest instance! Bedrock players will have to re-downloaded the player skull resource pack after each server restart.", e); + } + + return Pair.of(uuid1, uuid2); + } + + private static boolean canReusePack(File packFile) { + Pair uuids = generatePackUUIDs(); + try (ZipFile zipFile = new ZipFile(packFile)) { + Optional manifestEntry = zipFile.stream() + .filter(entry -> entry.getName().contains("manifest.json")) + .findFirst(); + if (manifestEntry.isPresent()) { + GeyserResourcePackManifest manifest = FileUtils.loadJson(zipFile.getInputStream(manifestEntry.get()), GeyserResourcePackManifest.class); + if (!uuids.first().equals(manifest.header().uuid())) { + return false; + } + Optional resourceUUID = manifest.modules().stream() + .filter(module -> "resources".equals(module.type())) + .findFirst() + .map(ResourcePackManifest.Module::uuid); + return resourceUUID.isPresent() && uuids.second().equals(resourceUUID.get()); + } + } catch (IOException e) { + GeyserImpl.getInstance().getLogger().debug("Cached player skull resource pack was invalid! The pack will be recreated."); + } + return false; + } + + private static String truncateHash(String hash) { + return hash.substring(0, Math.min(hash.length(), 32)); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java b/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java index 8b576a673..49fd90cf7 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java +++ b/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java @@ -25,17 +25,30 @@ package org.geysermc.geyser.registry; +import it.unimi.dsi.fastutil.Pair; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import org.geysermc.geyser.api.block.custom.CustomBlockData; +import org.geysermc.geyser.api.block.custom.CustomBlockState; +import org.geysermc.geyser.api.block.custom.nonvanilla.JavaBlockItem; +import org.geysermc.geyser.api.block.custom.nonvanilla.JavaBlockState; +import org.geysermc.geyser.registry.loader.CollisionRegistryLoader; import org.geysermc.geyser.registry.loader.RegistryLoaders; import org.geysermc.geyser.registry.populator.BlockRegistryPopulator; +import org.geysermc.geyser.registry.populator.CustomBlockRegistryPopulator; +import org.geysermc.geyser.registry.populator.CustomSkullRegistryPopulator; import org.geysermc.geyser.registry.type.BlockMapping; import org.geysermc.geyser.registry.type.BlockMappings; +import org.geysermc.geyser.registry.type.CustomSkull; +import org.geysermc.geyser.translator.collision.BlockCollision; import java.util.BitSet; +import java.util.Set; + /** * Holds all the block registries in Geyser. */ @@ -57,6 +70,11 @@ public class BlockRegistries { */ public static final ArrayRegistry JAVA_BLOCKS = ArrayRegistry.create(RegistryLoaders.uninitialized()); + /** + * A mapped registry containing which holds block IDs to its {@link BlockCollision}. + */ + public static final IntMappedRegistry COLLISIONS; + /** * A mapped registry containing the Java identifiers to IDs. */ @@ -83,11 +101,51 @@ public class BlockRegistries { */ public static final SimpleRegistry INTERACTIVE_MAY_BUILD = SimpleRegistry.create(RegistryLoaders.uninitialized()); + /** + * A registry containing all the custom blocks. + */ + public static final ArrayRegistry CUSTOM_BLOCKS = ArrayRegistry.create(RegistryLoaders.empty(() -> new CustomBlockData[] {})); + + /** + * A registry which stores Java Ids and the custom block state it should be replaced with. + */ + public static final MappedRegistry> CUSTOM_BLOCK_STATE_OVERRIDES = MappedRegistry.create(RegistryLoaders.empty(Int2ObjectOpenHashMap::new)); + + /** + * A registry which stores non vanilla java blockstates and the custom block state it should be replaced with. + */ + public static final SimpleMappedRegistry NON_VANILLA_BLOCK_STATE_OVERRIDES = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new)); + + /** + * A registry which stores clean Java Ids and the custom block it should be replaced with in the context of items. + */ + public static final SimpleMappedRegistry CUSTOM_BLOCK_ITEM_OVERRIDES = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new)); + + /** + * A registry which stores Custom Block Data for extended collision boxes and the Java IDs of blocks that will have said extended collision boxes placed above them. + */ + public static final SimpleMappedRegistry> EXTENDED_COLLISION_BOXES = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new)); + + /** + * A registry which stores skin texture hashes to custom skull blocks. + */ + public static final SimpleMappedRegistry CUSTOM_SKULLS = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new)); + static { - BlockRegistryPopulator.populate(); + CustomSkullRegistryPopulator.populate(); + BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.PRE_INIT); + CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.DEFINITION); + CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.NON_VANILLA_REGISTRATION); + BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.INIT_JAVA); + COLLISIONS = IntMappedRegistry.create(Pair.of("org.geysermc.geyser.translator.collision.CollisionRemapper", "mappings/collision.json"), CollisionRegistryLoader::new); + CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.VANILLA_REGISTRATION); + CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.CUSTOM_REGISTRATION); + BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.INIT_BEDROCK); + BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.POST_INIT); } public static void init() { // no-op } + } \ No newline at end of file diff --git a/core/src/main/java/org/geysermc/geyser/registry/Registries.java b/core/src/main/java/org/geysermc/geyser/registry/Registries.java index 73ae23e9e..9b5ed8ae6 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/Registries.java +++ b/core/src/main/java/org/geysermc/geyser/registry/Registries.java @@ -31,7 +31,6 @@ import com.github.steveice10.mc.protocol.data.game.level.event.LevelEvent; import com.github.steveice10.mc.protocol.data.game.level.particle.ParticleType; import com.github.steveice10.mc.protocol.data.game.recipe.RecipeType; import com.github.steveice10.packetlib.packet.Packet; -import it.unimi.dsi.fastutil.Pair; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2IntMap; @@ -56,7 +55,6 @@ import org.geysermc.geyser.registry.type.EnchantmentData; import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.registry.type.ParticleMapping; import org.geysermc.geyser.registry.type.SoundMapping; -import org.geysermc.geyser.translator.collision.BlockCollision; import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator; import org.geysermc.geyser.translator.level.event.LevelEventTranslator; import org.geysermc.geyser.translator.sound.SoundInteractionTranslator; @@ -68,6 +66,12 @@ import java.util.*; * Holds all the common registries in Geyser. */ public final class Registries { + /** + * A registry holding all the providers. + * This has to be initialized first to allow extensions to access providers during other registry events. + */ + public static final SimpleMappedRegistry, ProviderSupplier> PROVIDERS = SimpleMappedRegistry.create(new IdentityHashMap<>(), ProviderRegistryLoader::new); + /** * A registry holding a CompoundTag of the known entity identifiers. */ @@ -93,11 +97,6 @@ public final class Registries { */ public static final SimpleMappedRegistry BLOCK_ENTITIES = SimpleMappedRegistry.create("org.geysermc.geyser.translator.level.block.entity.BlockEntity", BlockEntityRegistryLoader::new); - /** - * A mapped registry containing which holds block IDs to its {@link BlockCollision}. - */ - public static final IntMappedRegistry COLLISIONS = IntMappedRegistry.create(Pair.of("org.geysermc.geyser.translator.collision.CollisionRemapper", "mappings/collision.json"), CollisionRegistryLoader::new); - /** * A versioned registry which holds a {@link RecipeType} to a corresponding list of {@link RecipeData}. */ @@ -144,11 +143,6 @@ public final class Registries { */ public static final VersionedRegistry> POTION_MIXES; - /** - * A registry holding all the - */ - public static final SimpleMappedRegistry, ProviderSupplier> PROVIDERS = SimpleMappedRegistry.create(new IdentityHashMap<>(), ProviderRegistryLoader::new); - /** * A versioned registry holding all the recipes, with the net ID being the key, and {@link GeyserRecipe} as the value. */ diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/CollisionRegistryLoader.java b/core/src/main/java/org/geysermc/geyser/registry/loader/CollisionRegistryLoader.java index 69ad16743..bf2d72b27 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/loader/CollisionRegistryLoader.java +++ b/core/src/main/java/org/geysermc/geyser/registry/loader/CollisionRegistryLoader.java @@ -79,6 +79,11 @@ public class CollisionRegistryLoader extends MultiResourceRegistryLoader collisionInstances = new Object2ObjectOpenHashMap<>(); for (int i = 0; i < blockMappings.length; i++) { BlockMapping blockMapping = blockMappings[i]; + if (blockMapping == null) { + GeyserImpl.getInstance().getLogger().warning("Missing block mapping for Java block " + i); + continue; + } + BlockCollision newCollision = instantiateCollision(blockMapping, annotationMap, collisionList); if (newCollision != null) { diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/ProviderRegistryLoader.java b/core/src/main/java/org/geysermc/geyser/registry/loader/ProviderRegistryLoader.java index d32b11cc0..13d7a4d77 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/loader/ProviderRegistryLoader.java +++ b/core/src/main/java/org/geysermc/geyser/registry/loader/ProviderRegistryLoader.java @@ -25,6 +25,12 @@ package org.geysermc.geyser.registry.loader; +import org.geysermc.geyser.api.block.custom.CustomBlockData; +import org.geysermc.geyser.api.block.custom.NonVanillaCustomBlockData; +import org.geysermc.geyser.api.block.custom.component.CustomBlockComponents; +import org.geysermc.geyser.api.block.custom.component.GeometryComponent; +import org.geysermc.geyser.api.block.custom.component.MaterialInstance; +import org.geysermc.geyser.api.block.custom.nonvanilla.JavaBlockState; import org.geysermc.geyser.api.command.Command; import org.geysermc.geyser.api.event.EventRegistrar; import org.geysermc.geyser.api.extension.Extension; @@ -37,6 +43,12 @@ import org.geysermc.geyser.event.GeyserEventRegistrar; import org.geysermc.geyser.item.GeyserCustomItemData; import org.geysermc.geyser.item.GeyserCustomItemOptions; import org.geysermc.geyser.item.GeyserNonVanillaCustomItemData; +import org.geysermc.geyser.level.block.GeyserCustomBlockComponents; +import org.geysermc.geyser.level.block.GeyserCustomBlockData; +import org.geysermc.geyser.level.block.GeyserGeometryComponent; +import org.geysermc.geyser.level.block.GeyserJavaBlockState; +import org.geysermc.geyser.level.block.GeyserMaterialInstance; +import org.geysermc.geyser.level.block.GeyserNonVanillaCustomBlockData; import org.geysermc.geyser.pack.path.GeyserPathPackCodec; import org.geysermc.geyser.registry.provider.ProviderSupplier; @@ -52,6 +64,14 @@ public class ProviderRegistryLoader implements RegistryLoader, Prov public Map, ProviderSupplier> load(Map, ProviderSupplier> providers) { // misc providers.put(Command.Builder.class, args -> new GeyserCommandManager.CommandBuilder<>((Extension) args[0])); + + providers.put(CustomBlockComponents.Builder.class, args -> new GeyserCustomBlockComponents.CustomBlockComponentsBuilder()); + providers.put(CustomBlockData.Builder.class, args -> new GeyserCustomBlockData.CustomBlockDataBuilder()); + providers.put(JavaBlockState.Builder.class, args -> new GeyserJavaBlockState.JavaBlockStateBuilder()); + providers.put(NonVanillaCustomBlockData.Builder.class, args -> new GeyserNonVanillaCustomBlockData.NonVanillaCustomBlockDataBuilder()); + providers.put(MaterialInstance.Builder.class, args -> new GeyserMaterialInstance.MaterialInstanceBuilder()); + providers.put(GeometryComponent.Builder.class, args -> new GeyserGeometryComponent.GeometryComponentBuilder()); + providers.put(EventRegistrar.class, args -> new GeyserEventRegistrar(args[0])); providers.put(PathPackCodec.class, args -> new GeyserPathPackCodec((Path) args[0])); diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/ResourcePackLoader.java b/core/src/main/java/org/geysermc/geyser/registry/loader/ResourcePackLoader.java index 452550d87..800a3d22c 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/loader/ResourcePackLoader.java +++ b/core/src/main/java/org/geysermc/geyser/registry/loader/ResourcePackLoader.java @@ -30,6 +30,7 @@ import org.geysermc.geyser.api.event.lifecycle.GeyserLoadResourcePacksEvent; import org.geysermc.geyser.api.pack.ResourcePack; import org.geysermc.geyser.pack.GeyserResourcePack; import org.geysermc.geyser.pack.GeyserResourcePackManifest; +import org.geysermc.geyser.pack.SkullResourcePackManager; import org.geysermc.geyser.pack.path.GeyserPathPackCodec; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.util.FileUtils; @@ -87,6 +88,12 @@ public class ResourcePackLoader implements RegistryLoader(); } + // Add custom skull pack + Path skullResourcePack = SkullResourcePackManager.createResourcePack(); + if (skullResourcePack != null) { + resourcePacks.add(skullResourcePack); + } + GeyserLoadResourcePacksEvent event = new GeyserLoadResourcePacksEvent(resourcePacks); GeyserImpl.getInstance().eventBus().fire(event); diff --git a/core/src/main/java/org/geysermc/geyser/item/mappings/MappingsConfigReader.java b/core/src/main/java/org/geysermc/geyser/registry/mappings/MappingsConfigReader.java similarity index 58% rename from core/src/main/java/org/geysermc/geyser/item/mappings/MappingsConfigReader.java rename to core/src/main/java/org/geysermc/geyser/registry/mappings/MappingsConfigReader.java index eaf07c382..039412957 100644 --- a/core/src/main/java/org/geysermc/geyser/item/mappings/MappingsConfigReader.java +++ b/core/src/main/java/org/geysermc/geyser/registry/mappings/MappingsConfigReader.java @@ -23,15 +23,16 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.geyser.item.mappings; +package org.geysermc.geyser.registry.mappings; import com.fasterxml.jackson.databind.JsonNode; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.item.custom.CustomItemData; -import org.geysermc.geyser.item.mappings.versions.MappingsReader; -import org.geysermc.geyser.item.mappings.versions.MappingsReader_v1; +import org.geysermc.geyser.registry.mappings.util.CustomBlockMapping; +import org.geysermc.geyser.registry.mappings.versions.MappingsReader; +import org.geysermc.geyser.registry.mappings.versions.MappingsReader_v1; import java.io.IOException; import java.nio.file.Files; @@ -56,43 +57,88 @@ public class MappingsConfigReader { } } - public void loadMappingsFromJson(BiConsumer consumer) { - Path customMappingsDirectory = this.customMappingsDirectory; - if (!Files.exists(customMappingsDirectory)) { + public boolean ensureMappingsDirectory(Path mappingsDirectory) { + if (!Files.exists(mappingsDirectory)) { try { - Files.createDirectories(customMappingsDirectory); + Files.createDirectories(mappingsDirectory); + return true; } catch (IOException e) { - GeyserImpl.getInstance().getLogger().error("Failed to create custom mappings directory", e); - return; + GeyserImpl.getInstance().getLogger().error("Failed to create mappings directory", e); + return false; } } + return true; + } + + public void loadItemMappingsFromJson(BiConsumer consumer) { + if (!ensureMappingsDirectory(this.customMappingsDirectory)) { + return; + } Path[] mappingsFiles = this.getCustomMappingsFiles(); for (Path mappingsFile : mappingsFiles) { - this.readMappingsFromJson(mappingsFile, consumer); + this.readItemMappingsFromJson(mappingsFile, consumer); } } - public void readMappingsFromJson(Path file, BiConsumer consumer) { + public void loadBlockMappingsFromJson(BiConsumer consumer) { + if (!ensureMappingsDirectory(this.customMappingsDirectory)) { + return; + } + + Path[] mappingsFiles = this.getCustomMappingsFiles(); + for (Path mappingsFile : mappingsFiles) { + this.readBlockMappingsFromJson(mappingsFile, consumer); + } + } + + public JsonNode getMappingsRoot(Path file) { JsonNode mappingsRoot; try { mappingsRoot = GeyserImpl.JSON_MAPPER.readTree(file.toFile()); } catch (IOException e) { GeyserImpl.getInstance().getLogger().error("Failed to read custom mapping file: " + file, e); - return; + return null; } if (!mappingsRoot.has("format_version")) { GeyserImpl.getInstance().getLogger().error("Mappings file " + file + " is missing the format version field!"); - return; + return null; } - int formatVersion = mappingsRoot.get("format_version").asInt(); + return mappingsRoot; + } + + public int getFormatVersion(JsonNode mappingsRoot, Path file) { + int formatVersion = mappingsRoot.get("format_version").asInt(); if (!this.mappingReaders.containsKey(formatVersion)) { GeyserImpl.getInstance().getLogger().error("Mappings file " + file + " has an unknown format version: " + formatVersion); + return -1; + } + return formatVersion; + } + + public void readItemMappingsFromJson(Path file, BiConsumer consumer) { + JsonNode mappingsRoot = getMappingsRoot(file); + + int formatVersion = getFormatVersion(mappingsRoot, file); + + if (formatVersion < 0 || mappingsRoot == null) { return; } - this.mappingReaders.get(formatVersion).readMappings(file, mappingsRoot, consumer); + this.mappingReaders.get(formatVersion).readItemMappings(file, mappingsRoot, consumer); + } + + public void readBlockMappingsFromJson(Path file, BiConsumer consumer) { + JsonNode mappingsRoot = getMappingsRoot(file); + + int formatVersion = getFormatVersion(mappingsRoot, file); + + if (formatVersion < 0 || mappingsRoot == null) { + return; + } + + this.mappingReaders.get(formatVersion).readBlockMappings(file, mappingsRoot, consumer); } } diff --git a/core/src/main/java/org/geysermc/geyser/registry/mappings/util/CustomBlockComponentsMapping.java b/core/src/main/java/org/geysermc/geyser/registry/mappings/util/CustomBlockComponentsMapping.java new file mode 100644 index 000000000..3e5d934ab --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/mappings/util/CustomBlockComponentsMapping.java @@ -0,0 +1,40 @@ +/* + * 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.mappings.util; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.api.block.custom.component.BoxComponent; +import org.geysermc.geyser.api.block.custom.component.CustomBlockComponents; + +/** + * This class is used to store a custom block components mapping, which contains custom + * block components and a potenially null extended collision box + * + * @param components The components of the block + * @param extendedCollisionBox The extended collision box of the block + */ +public record CustomBlockComponentsMapping(@NonNull CustomBlockComponents components, BoxComponent extendedCollisionBox) { +} diff --git a/core/src/main/java/org/geysermc/geyser/registry/mappings/util/CustomBlockMapping.java b/core/src/main/java/org/geysermc/geyser/registry/mappings/util/CustomBlockMapping.java new file mode 100644 index 000000000..3dbb7908e --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/mappings/util/CustomBlockMapping.java @@ -0,0 +1,44 @@ +/* + * 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.mappings.util; + +import java.util.Map; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.api.block.custom.CustomBlockData; + +/** + * This class is used to store a custom block mappings, which contain all of the + * data required to register a custom block that overrides a group of java block + * states. + * + * @param data The custom block data + * @param states The custom block state mappings + * @param javaIdentifier The java identifier of the block + * @param overrideItem Whether or not the custom block should override the java item + */ +public record CustomBlockMapping(@NonNull CustomBlockData data, @NonNull Map states, @NonNull String javaIdentifier, boolean overrideItem) { +} diff --git a/core/src/main/java/org/geysermc/geyser/registry/mappings/util/CustomBlockStateBuilderMapping.java b/core/src/main/java/org/geysermc/geyser/registry/mappings/util/CustomBlockStateBuilderMapping.java new file mode 100644 index 000000000..e627c04a6 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/mappings/util/CustomBlockStateBuilderMapping.java @@ -0,0 +1,42 @@ +/* + * 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.mappings.util; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.api.block.custom.CustomBlockState; +import org.geysermc.geyser.api.block.custom.component.BoxComponent; + +import java.util.function.Function; + +/** + * This class is used to store a custom block state builder mapping, which contains custom + * block state builders and a potenially null extended collision box + * + * @param builder The builder of the block + * @param extendedCollisionBox The extended collision box of the block + */ +public record CustomBlockStateBuilderMapping(@NonNull Function builder, BoxComponent extendedCollisionBox) { +} diff --git a/core/src/main/java/org/geysermc/geyser/registry/mappings/util/CustomBlockStateMapping.java b/core/src/main/java/org/geysermc/geyser/registry/mappings/util/CustomBlockStateMapping.java new file mode 100644 index 000000000..4c04bd657 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/mappings/util/CustomBlockStateMapping.java @@ -0,0 +1,40 @@ +/* + * 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.mappings.util; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.api.block.custom.CustomBlockState; +import org.geysermc.geyser.api.block.custom.component.BoxComponent; + +/** + * This class is used to store a custom block state mapping, which contains custom + * block states and a potenially null extended collision box + * + * @param state The state of the block + * @param extendedCollisionBox The extended collision box of the block + */ +public record CustomBlockStateMapping(@NonNull CustomBlockState state, BoxComponent extendedCollisionBox) { +} diff --git a/core/src/main/java/org/geysermc/geyser/item/mappings/versions/MappingsReader.java b/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader.java similarity index 86% rename from core/src/main/java/org/geysermc/geyser/item/mappings/versions/MappingsReader.java rename to core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader.java index ef553f488..e76df2834 100644 --- a/core/src/main/java/org/geysermc/geyser/item/mappings/versions/MappingsReader.java +++ b/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader.java @@ -23,20 +23,23 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.geyser.item.mappings.versions; +package org.geysermc.geyser.registry.mappings.versions; import com.fasterxml.jackson.databind.JsonNode; import org.geysermc.geyser.api.item.custom.CustomItemData; import org.geysermc.geyser.api.item.custom.CustomRenderOffsets; import org.geysermc.geyser.item.exception.InvalidCustomMappingsFileException; +import org.geysermc.geyser.registry.mappings.util.CustomBlockMapping; import java.nio.file.Path; import java.util.function.BiConsumer; public abstract class MappingsReader { - public abstract void readMappings(Path file, JsonNode mappingsRoot, BiConsumer consumer); + public abstract void readItemMappings(Path file, JsonNode mappingsRoot, BiConsumer consumer); + public abstract void readBlockMappings(Path file, JsonNode mappingsRoot, BiConsumer consumer); public abstract CustomItemData readItemMappingEntry(JsonNode node) throws InvalidCustomMappingsFileException; + public abstract CustomBlockMapping readBlockMappingEntry(String identifier, JsonNode node) throws InvalidCustomMappingsFileException; protected CustomRenderOffsets fromJsonNode(JsonNode node) { if (node == null || !node.isObject()) { diff --git a/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java b/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java new file mode 100644 index 000000000..51c2220cb --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java @@ -0,0 +1,713 @@ +/* + * 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.mappings.versions; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.github.steveice10.mc.protocol.data.game.Identifier; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.block.custom.CustomBlockData; +import org.geysermc.geyser.api.block.custom.CustomBlockPermutation; +import org.geysermc.geyser.api.block.custom.CustomBlockState; +import org.geysermc.geyser.api.block.custom.component.*; +import org.geysermc.geyser.api.block.custom.component.PlacementConditions.BlockFilterType; +import org.geysermc.geyser.api.block.custom.component.PlacementConditions.Face; +import org.geysermc.geyser.api.item.custom.CustomItemData; +import org.geysermc.geyser.api.item.custom.CustomItemOptions; +import org.geysermc.geyser.api.util.CreativeCategory; +import org.geysermc.geyser.item.exception.InvalidCustomMappingsFileException; +import org.geysermc.geyser.level.block.GeyserCustomBlockComponents.CustomBlockComponentsBuilder; +import org.geysermc.geyser.level.block.GeyserCustomBlockData.CustomBlockDataBuilder; +import org.geysermc.geyser.level.block.GeyserGeometryComponent.GeometryComponentBuilder; +import org.geysermc.geyser.level.block.GeyserMaterialInstance.MaterialInstanceBuilder; +import org.geysermc.geyser.level.physics.BoundingBox; +import org.geysermc.geyser.registry.BlockRegistries; +import org.geysermc.geyser.registry.mappings.util.CustomBlockComponentsMapping; +import org.geysermc.geyser.registry.mappings.util.CustomBlockMapping; +import org.geysermc.geyser.registry.mappings.util.CustomBlockStateBuilderMapping; +import org.geysermc.geyser.registry.mappings.util.CustomBlockStateMapping; +import org.geysermc.geyser.translator.collision.BlockCollision; +import org.geysermc.geyser.util.BlockUtils; +import org.geysermc.geyser.util.MathUtils; + +import java.nio.file.Path; +import java.util.*; +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +/** + * A class responsible for reading custom item and block mappings from a JSON file + */ +public class MappingsReader_v1 extends MappingsReader { + @Override + public void readItemMappings(Path file, JsonNode mappingsRoot, BiConsumer consumer) { + this.readItemMappingsV1(file, mappingsRoot, consumer); + } + + /** + * Read item block from a JSON node + * + * @param file The path to the file + * @param mappingsRoot The {@link JsonNode} containing the mappings + * @param consumer The consumer to accept the mappings + * @see #readBlockMappingsV1(Path, JsonNode, BiConsumer) + */ + @Override + public void readBlockMappings(Path file, JsonNode mappingsRoot, BiConsumer consumer) { + this.readBlockMappingsV1(file, mappingsRoot, consumer); + } + + public void readItemMappingsV1(Path file, JsonNode mappingsRoot, BiConsumer consumer) { + JsonNode itemsNode = mappingsRoot.get("items"); + + if (itemsNode != null && itemsNode.isObject()) { + itemsNode.fields().forEachRemaining(entry -> { + if (entry.getValue().isArray()) { + entry.getValue().forEach(data -> { + try { + CustomItemData customItemData = this.readItemMappingEntry(data); + consumer.accept(entry.getKey(), customItemData); + } catch (InvalidCustomMappingsFileException e) { + GeyserImpl.getInstance().getLogger().error("Error in registering items for custom mapping file: " + file.toString(), e); + } + }); + } + }); + } + } + + /** + * Read block mappings from a JSON node + * + * @param file The path to the file + * @param mappingsRoot The {@link JsonNode} containing the mappings + * @param consumer The consumer to accept the mappings + * @see #readBlockMappings(Path, JsonNode, BiConsumer) + */ + public void readBlockMappingsV1(Path file, JsonNode mappingsRoot, BiConsumer consumer) { + JsonNode blocksNode = mappingsRoot.get("blocks"); + + if (blocksNode != null && blocksNode.isObject()) { + blocksNode.fields().forEachRemaining(entry -> { + if (entry.getValue().isObject()) { + try { + String identifier = Identifier.formalize(entry.getKey()); + CustomBlockMapping customBlockMapping = this.readBlockMappingEntry(identifier, entry.getValue()); + consumer.accept(identifier, customBlockMapping); + } catch (Exception e) { + GeyserImpl.getInstance().getLogger().error("Error in registering blocks for custom mapping file: " + file.toString()); + GeyserImpl.getInstance().getLogger().error("due to entry: " + entry, e); + } + } + }); + } + } + + private CustomItemOptions readItemCustomItemOptions(JsonNode node) { + CustomItemOptions.Builder customItemOptions = CustomItemOptions.builder(); + + JsonNode customModelData = node.get("custom_model_data"); + if (customModelData != null && customModelData.isInt()) { + customItemOptions.customModelData(customModelData.asInt()); + } + + JsonNode damagePredicate = node.get("damage_predicate"); + if (damagePredicate != null && damagePredicate.isInt()) { + customItemOptions.damagePredicate(damagePredicate.asInt()); + } + + JsonNode unbreakable = node.get("unbreakable"); + if (unbreakable != null && unbreakable.isBoolean()) { + customItemOptions.unbreakable(unbreakable.asBoolean()); + } + + JsonNode defaultItem = node.get("default"); + if (defaultItem != null && defaultItem.isBoolean()) { + customItemOptions.defaultItem(defaultItem.asBoolean()); + } + + return customItemOptions.build(); + } + + @Override + public CustomItemData readItemMappingEntry(JsonNode node) throws InvalidCustomMappingsFileException { + if (node == null || !node.isObject()) { + throw new InvalidCustomMappingsFileException("Invalid item mappings entry"); + } + + JsonNode name = node.get("name"); + if (name == null || !name.isTextual() || name.asText().isEmpty()) { + throw new InvalidCustomMappingsFileException("An item entry has no name"); + } + + CustomItemData.Builder customItemData = CustomItemData.builder() + .name(name.asText()) + .customItemOptions(this.readItemCustomItemOptions(node)); + + //The next entries are optional + if (node.has("display_name")) { + customItemData.displayName(node.get("display_name").asText()); + } + + if (node.has("icon")) { + customItemData.icon(node.get("icon").asText()); + } + + if (node.has("allow_offhand")) { + customItemData.allowOffhand(node.get("allow_offhand").asBoolean()); + } + + if (node.has("display_handheld")) { + customItemData.displayHandheld(node.get("display_handheld").asBoolean()); + } + + if (node.has("texture_size")) { + customItemData.textureSize(node.get("texture_size").asInt()); + } + + if (node.has("render_offsets")) { + JsonNode tmpNode = node.get("render_offsets"); + + customItemData.renderOffsets(fromJsonNode(tmpNode)); + } + + return customItemData.build(); + } + + /** + * Read a block mapping entry from a JSON node and Java identifier + * + * @param identifier The Java identifier of the block + * @param node The {@link JsonNode} containing the block mapping entry + * @return The {@link CustomBlockMapping} record to be read by {@link org.geysermc.geyser.registry.populator.CustomBlockRegistryPopulator} + * @throws InvalidCustomMappingsFileException If the JSON node is invalid + */ + @Override + public CustomBlockMapping readBlockMappingEntry(String identifier, JsonNode node) throws InvalidCustomMappingsFileException { + if (node == null || !node.isObject()) { + throw new InvalidCustomMappingsFileException("Invalid block mappings entry:" + node); + } + + String name = node.get("name").asText(); + if (name == null || name.isEmpty()) { + throw new InvalidCustomMappingsFileException("A block entry has no name"); + } + + boolean includedInCreativeInventory = node.has("included_in_creative_inventory") && node.get("included_in_creative_inventory").asBoolean(); + + CreativeCategory creativeCategory = CreativeCategory.NONE; + if (node.has("creative_category")) { + String categoryName = node.get("creative_category").asText(); + try { + creativeCategory = CreativeCategory.valueOf(categoryName.toUpperCase()); + } catch (IllegalArgumentException e) { + throw new InvalidCustomMappingsFileException("Invalid creative category \"" + categoryName + "\" for block \"" + name + "\""); + } + } + + String creativeGroup = ""; + if (node.has("creative_group")) { + creativeGroup = node.get("creative_group").asText(); + } + + // If this is true, we will only register the states the user has specified rather than all the possible block states + boolean onlyOverrideStates = node.has("only_override_states") && node.get("only_override_states").asBoolean(); + + // Create the data for the overall block + CustomBlockData.Builder customBlockDataBuilder = new CustomBlockDataBuilder() + .name(name) + .includedInCreativeInventory(includedInCreativeInventory) + .creativeCategory(creativeCategory) + .creativeGroup(creativeGroup); + + if (BlockRegistries.JAVA_IDENTIFIER_TO_ID.get().containsKey(identifier)) { + // There is only one Java block state to override + CustomBlockComponentsMapping componentsMapping = createCustomBlockComponentsMapping(node, identifier, name); + CustomBlockData blockData = customBlockDataBuilder + .components(componentsMapping.components()) + .build(); + return new CustomBlockMapping(blockData, Map.of(identifier, new CustomBlockStateMapping(blockData.defaultBlockState(), componentsMapping.extendedCollisionBox())), identifier, !onlyOverrideStates); + } + + Map componentsMap = new LinkedHashMap<>(); + + JsonNode stateOverrides = node.get("state_overrides"); + if (stateOverrides != null && stateOverrides.isObject()) { + // Load components for specific Java block states + Iterator> fields = stateOverrides.fields(); + while (fields.hasNext()) { + Map.Entry overrideEntry = fields.next(); + String state = identifier + "[" + overrideEntry.getKey() + "]"; + if (!BlockRegistries.JAVA_IDENTIFIER_TO_ID.get().containsKey(state)) { + throw new InvalidCustomMappingsFileException("Unknown Java block state: " + state + " for state_overrides."); + } + componentsMap.put(state, createCustomBlockComponentsMapping(overrideEntry.getValue(), state, name)); + } + } + if (componentsMap.isEmpty() && onlyOverrideStates) { + throw new InvalidCustomMappingsFileException("Block entry for " + identifier + " has only_override_states set to true, but has no state_overrides."); + } + + if (!onlyOverrideStates) { + // Create components for any remaining Java block states + BlockRegistries.JAVA_IDENTIFIER_TO_ID.get().keySet() + .stream() + .filter(s -> s.startsWith(identifier + "[")) + .filter(Predicate.not(componentsMap::containsKey)) + .forEach(state -> componentsMap.put(state, createCustomBlockComponentsMapping(null, state, name))); + } + + if (componentsMap.isEmpty()) { + throw new InvalidCustomMappingsFileException("Unknown Java block: " + identifier); + } + + // We pass in the first state and just use the hitbox from that as the default + // Each state will have its own so this is fine + String firstState = componentsMap.keySet().iterator().next(); + CustomBlockComponentsMapping firstComponentsMapping = createCustomBlockComponentsMapping(node, firstState, name); + customBlockDataBuilder.components(firstComponentsMapping.components()); + + return createCustomBlockMapping(customBlockDataBuilder, componentsMap, identifier, !onlyOverrideStates); + } + + private CustomBlockMapping createCustomBlockMapping(CustomBlockData.Builder customBlockDataBuilder, Map componentsMap, String identifier, boolean overrideItem) { + Map> valuesMap = new Object2ObjectOpenHashMap<>(); + + List permutations = new ArrayList<>(); + Map blockStateBuilders = new Object2ObjectOpenHashMap<>(); + + // For each Java block state, extract the property values, create a CustomBlockPermutation, + // and a CustomBlockState builder + for (Map.Entry entry : componentsMap.entrySet()) { + String state = entry.getKey(); + String[] pairs = splitStateString(state); + + String[] conditions = new String[pairs.length]; + Function blockStateBuilder = Function.identity(); + + for (int i = 0; i < pairs.length; i++) { + String[] parts = pairs[i].split("="); + String property = parts[0]; + String value = parts[1]; + + valuesMap.computeIfAbsent(property, k -> new LinkedHashSet<>()) + .add(value); + + conditions[i] = String.format("q.block_property('%s') == '%s'", property, value); + blockStateBuilder = blockStateBuilder.andThen(builder -> builder.stringProperty(property, value)); + } + + permutations.add(new CustomBlockPermutation(entry.getValue().components(), String.join(" && ", conditions))); + blockStateBuilders.put(state, new CustomBlockStateBuilderMapping(blockStateBuilder.andThen(CustomBlockState.Builder::build), entry.getValue().extendedCollisionBox())); + } + + valuesMap.forEach((key, value) -> customBlockDataBuilder.stringProperty(key, new ArrayList<>(value))); + + CustomBlockData customBlockData = customBlockDataBuilder + .permutations(permutations) + .build(); + // Build CustomBlockStates for each Java block state we wish to override + Map states = blockStateBuilders.entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getKey, e -> new CustomBlockStateMapping(e.getValue().builder().apply(customBlockData.blockStateBuilder()), e.getValue().extendedCollisionBox()))); + + return new CustomBlockMapping(customBlockData, states, identifier, overrideItem); + } + + /** + * Creates a {@link CustomBlockComponents} object for the passed state override or base block node, Java block state identifier, and custom block name + * + * @param node the state override or base block {@link JsonNode} + * @param stateKey the Java block state identifier + * @param name the name of the custom block + * @return the {@link CustomBlockComponents} object + */ + private CustomBlockComponentsMapping createCustomBlockComponentsMapping(JsonNode node, String stateKey, String name) { + // This is needed to find the correct selection box for the given block + int id = BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(stateKey, -1); + BoxComponent boxComponent = createBoxComponent(id); + BoxComponent extendedBoxComponent = createExtendedBoxComponent(id); + CustomBlockComponents.Builder builder = new CustomBlockComponentsBuilder() + .collisionBox(boxComponent) + .selectionBox(boxComponent); + + if (node == null) { + // No other components were defined + return new CustomBlockComponentsMapping(builder.build(), extendedBoxComponent); + } + + BoxComponent selectionBox = createBoxComponent(node.get("selection_box")); + if (selectionBox != null) { + builder.selectionBox(selectionBox); + } + BoxComponent collisionBox = createBoxComponent(node.get("collision_box")); + if (collisionBox != null) { + builder.collisionBox(collisionBox); + } + BoxComponent extendedCollisionBox = createBoxComponent(node.get("extended_collision_box")); + if (extendedCollisionBox != null) { + extendedBoxComponent = extendedCollisionBox; + } + + + // We set this to max value by default so that we may dictate the correct destroy time ourselves + float destructibleByMining = Float.MAX_VALUE; + if (node.has("destructible_by_mining")) { + destructibleByMining = node.get("destructible_by_mining").floatValue(); + } + builder.destructibleByMining(destructibleByMining); + + if (node.has("geometry")) { + if (node.get("geometry").isTextual()) { + builder.geometry(new GeometryComponentBuilder() + .identifier(node.get("geometry").asText()) + .build()); + } else { + JsonNode geometry = node.get("geometry"); + GeometryComponentBuilder geometryBuilder = new GeometryComponentBuilder(); + if (geometry.has("identifier")) { + geometryBuilder.identifier(geometry.get("identifier").asText()); + } + if (geometry.has("bone_visibility")) { + JsonNode boneVisibility = geometry.get("bone_visibility"); + if (boneVisibility.isObject()) { + Map boneVisibilityMap = new Object2ObjectOpenHashMap<>(); + boneVisibility.fields().forEachRemaining(entry -> { + boneVisibilityMap.put(entry.getKey(), entry.getValue().isBoolean() ? (entry.getValue().asBoolean() ? "1" : "0") : entry.getValue().asText()); + }); + geometryBuilder.boneVisibility(boneVisibilityMap); + } + } + builder.geometry(geometryBuilder.build()); + } + } + + String displayName = name; + if (node.has("display_name")) { + displayName = node.get("display_name").asText(); + } + builder.displayName(displayName); + + if (node.has("friction")) { + builder.friction(node.get("friction").floatValue()); + } + + if (node.has("light_emission")) { + builder.lightEmission(node.get("light_emission").asInt()); + } + + if (node.has("light_dampening")) { + builder.lightDampening(node.get("light_dampening").asInt()); + } + + boolean placeAir = true; + if (node.has("place_air")) { + placeAir = node.get("place_air").asBoolean(); + } + builder.placeAir(placeAir); + + if (node.has("transformation")) { + JsonNode transformation = node.get("transformation"); + + int rotationX = 0; + int rotationY = 0; + int rotationZ = 0; + float scaleX = 1; + float scaleY = 1; + float scaleZ = 1; + float transformX = 0; + float transformY = 0; + float transformZ = 0; + + if (transformation.has("rotation")) { + JsonNode rotation = transformation.get("rotation"); + rotationX = rotation.get(0).asInt(); + rotationY = rotation.get(1).asInt(); + rotationZ = rotation.get(2).asInt(); + } + if (transformation.has("scale")) { + JsonNode scale = transformation.get("scale"); + scaleX = scale.get(0).floatValue(); + scaleY = scale.get(1).floatValue(); + scaleZ = scale.get(2).floatValue(); + } + if (transformation.has("translation")) { + JsonNode translation = transformation.get("translation"); + transformX = translation.get(0).floatValue(); + transformY = translation.get(1).floatValue(); + transformZ = translation.get(2).floatValue(); + } + builder.transformation(new TransformationComponent(rotationX, rotationY, rotationZ, scaleX, scaleY, scaleZ, transformX, transformY, transformZ)); + } + + if (node.has("unit_cube")) { + builder.unitCube(node.get("unit_cube").asBoolean()); + } + + if (node.has("material_instances")) { + JsonNode materialInstances = node.get("material_instances"); + if (materialInstances.isObject()) { + materialInstances.fields().forEachRemaining(entry -> { + String key = entry.getKey(); + JsonNode value = entry.getValue(); + if (value.isObject()) { + MaterialInstance materialInstance = createMaterialInstanceComponent(value, name); + builder.materialInstance(key, materialInstance); + } + }); + } + } + + if (node.has("placement_filter")) { + JsonNode placementFilter = node.get("placement_filter"); + if (placementFilter.isObject()) { + if (placementFilter.has("conditions")) { + JsonNode conditions = placementFilter.get("conditions"); + if (conditions.isArray()) { + List filter = createPlacementFilterComponent(conditions); + builder.placementFilter(filter); + } + } + } + } + + // Tags can be applied so that blocks will match return true when queried for the tag + // Potentially useful for resource pack creators + // Ideally we could programmatically extract the tags here https://wiki.bedrock.dev/blocks/block-tags.html + // This would let us automatically apply the correct vanilla tags to blocks + // However, its worth noting that vanilla tools do not currently honor these tags anyway + if (node.get("tags") instanceof ArrayNode tags) { + Set tagsSet = new ObjectOpenHashSet<>(); + tags.forEach(tag -> tagsSet.add(tag.asText())); + builder.tags(tagsSet); + } + + return new CustomBlockComponentsMapping(builder.build(), extendedBoxComponent); + } + + /** + * Creates a {@link BoxComponent} based on a Java block's collision with provided bounds and offsets + * + * @param javaId the block's Java ID + * @param heightTranslation the height translation of the box + * @return the {@link BoxComponent} + */ + private BoxComponent createBoxComponent(int javaId, float heightTranslation) { + // Some blocks (e.g. plants) have no collision box + BlockCollision blockCollision = BlockUtils.getCollision(javaId); + if (blockCollision == null || blockCollision.getBoundingBoxes().length == 0) { + return BoxComponent.emptyBox(); + } + + float minX = 5; + float minY = 5; + float minZ = 5; + float maxX = -5; + float maxY = -5; + float maxZ = -5; + for (BoundingBox boundingBox : blockCollision.getBoundingBoxes()) { + double offsetX = boundingBox.getSizeX() * 0.5; + double offsetY = boundingBox.getSizeY() * 0.5; + double offsetZ = boundingBox.getSizeZ() * 0.5; + + minX = Math.min(minX, (float) (boundingBox.getMiddleX() - offsetX)); + minY = Math.min(minY, (float) (boundingBox.getMiddleY() - offsetY)); + minZ = Math.min(minZ, (float) (boundingBox.getMiddleZ() - offsetZ)); + + maxX = Math.max(maxX, (float) (boundingBox.getMiddleX() + offsetX)); + maxY = Math.max(maxY, (float) (boundingBox.getMiddleY() + offsetY)); + maxZ = Math.max(maxZ, (float) (boundingBox.getMiddleZ() + offsetZ)); + } + minX = MathUtils.clamp(minX, 0, 1); + minY = MathUtils.clamp(minY + heightTranslation, 0, 1); + minZ = MathUtils.clamp(minZ, 0, 1); + maxX = MathUtils.clamp(maxX, 0, 1); + maxY = MathUtils.clamp(maxY + heightTranslation, 0, 1); + maxZ = MathUtils.clamp(maxZ, 0, 1); + + return new BoxComponent( + 16 * (1 - maxX) - 8, // For some odd reason X is mirrored on Bedrock + 16 * minY, + 16 * minZ - 8, + 16 * (maxX - minX), + 16 * (maxY - minY), + 16 * (maxZ - minZ) + ); + } + + /** + * Creates a {@link BoxComponent} based on a Java block's collision + * + * @param javaId the block's Java ID + * @return the {@link BoxComponent} + */ + private BoxComponent createBoxComponent(int javaId) { + return createBoxComponent(javaId, 0); + } + + /** + * Creates the {@link BoxComponent} for an extended collision box based on a Java block's collision + * + * @param javaId the block's Java ID + * @return the {@link BoxComponent} or null if the block's collision box would not exceed 16 y units + */ + private BoxComponent createExtendedBoxComponent(int javaId) { + BlockCollision blockCollision = BlockUtils.getCollision(javaId); + if (blockCollision == null) { + return null; + } + for (BoundingBox box : blockCollision.getBoundingBoxes()) { + double maxY = 0.5 * box.getSizeY() + box.getMiddleY(); + if (maxY > 1) { + return createBoxComponent(javaId, -1); + } + } + return null; + } + + /** + * Creates a {@link BoxComponent} from a JSON Node + * + * @param node the JSON node + * @return the {@link BoxComponent} + */ + private BoxComponent createBoxComponent(JsonNode node) { + if (node != null && node.isObject()) { + if (node.has("origin") && node.has("size")) { + JsonNode origin = node.get("origin"); + float originX = origin.get(0).floatValue(); + float originY = origin.get(1).floatValue(); + float originZ = origin.get(2).floatValue(); + + JsonNode size = node.get("size"); + float sizeX = size.get(0).floatValue(); + float sizeY = size.get(1).floatValue(); + float sizeZ = size.get(2).floatValue(); + + return new BoxComponent(originX, originY, originZ, sizeX, sizeY, sizeZ); + } + } + return null; + } + + /** + * Creates the {@link MaterialInstance} for the passed material instance node and custom block name + * The name is used as a fallback if no texture is provided by the node + * + * @param node the material instance node + * @param name the custom block name + * @return the {@link MaterialInstance} + */ + private MaterialInstance createMaterialInstanceComponent(JsonNode node, String name) { + // Set default values, and use what the user provides if they have provided something + String texture = name; + if (node.has("texture")) { + texture = node.get("texture").asText(); + } + + String renderMethod = "opaque"; + if (node.has("render_method")) { + renderMethod = node.get("render_method").asText(); + } + + boolean faceDimming = true; + if (node.has("face_dimming")) { + faceDimming = node.get("face_dimming").asBoolean(); + } + + boolean ambientOcclusion = true; + if (node.has("ambient_occlusion")) { + ambientOcclusion = node.get("ambient_occlusion").asBoolean(); + } + + return new MaterialInstanceBuilder() + .texture(texture) + .renderMethod(renderMethod) + .faceDimming(faceDimming) + .ambientOcclusion(ambientOcclusion) + .build(); + } + + /** + * Creates the list of {@link PlacementConditions} for the passed conditions node + * + * @param node the conditions node + * @return the list of {@link PlacementConditions} + */ + private List createPlacementFilterComponent(JsonNode node) { + List conditions = new ArrayList<>(); + + // The structure of the placement filter component is the most complex of the current components + // Each condition effectively separated into two arrays: one of allowed faces, and one of blocks/block Molang queries + node.forEach(condition -> { + Set faces = EnumSet.noneOf(Face.class); + if (condition.has("allowed_faces")) { + JsonNode allowedFaces = condition.get("allowed_faces"); + if (allowedFaces.isArray()) { + allowedFaces.forEach(face -> faces.add(Face.valueOf(face.asText().toUpperCase()))); + } + } + + LinkedHashMap blockFilters = new LinkedHashMap<>(); + if (condition.has("block_filter")) { + JsonNode blockFilter = condition.get("block_filter"); + if (blockFilter.isArray()) { + blockFilter.forEach(filter -> { + if (filter.isObject()) { + if (filter.has("tags")) { + JsonNode tags = filter.get("tags"); + blockFilters.put(tags.asText(), BlockFilterType.TAG); + } + } else if (filter.isTextual()) { + blockFilters.put(filter.asText(), BlockFilterType.BLOCK); + } + }); + } + } + + conditions.add(new PlacementConditions(faces, blockFilters)); + }); + + return conditions; + } + + /** + * Splits the given java state identifier into an array of property=value pairs + * + * @param state the java state identifier + * @return the array of property=value pairs + */ + private String[] splitStateString(String state) { + int openBracketIndex = state.indexOf("["); + + String states = state.substring(openBracketIndex + 1, state.length() - 1); + return states.split(","); + } + +} 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 8e30143e8..ce6cec075 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 @@ -30,13 +30,19 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Interner; import com.google.common.collect.Interners; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.*; import org.cloudburstmc.nbt.*; import org.cloudburstmc.protocol.bedrock.codec.v582.Bedrock_v582; +import org.cloudburstmc.protocol.bedrock.data.BlockPropertyData; import org.cloudburstmc.protocol.bedrock.codec.v589.Bedrock_v589; import org.cloudburstmc.protocol.bedrock.codec.v594.Bedrock_v594; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.block.custom.CustomBlockData; +import org.geysermc.geyser.api.block.custom.CustomBlockState; +import org.geysermc.geyser.api.block.custom.nonvanilla.JavaBlockState; import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.physics.PistonBehavior; import org.geysermc.geyser.registry.BlockRegistries; @@ -47,6 +53,7 @@ import org.geysermc.geyser.util.BlockUtils; import java.io.DataInputStream; import java.io.InputStream; +import java.nio.charset.StandardCharsets; import java.util.*; import java.util.function.BiFunction; import java.util.zip.GZIPInputStream; @@ -55,15 +62,35 @@ import java.util.zip.GZIPInputStream; * Populates the block registries. */ public final class BlockRegistryPopulator { + /** + * The stage of population + */ + public enum Stage { + PRE_INIT, + INIT_JAVA, + INIT_BEDROCK, + POST_INIT; + } + + public static void populate(Stage stage) { + switch (stage) { + case PRE_INIT -> { nullifyBlocksNode(); } + case INIT_JAVA -> { registerJavaBlocks(); } + case INIT_BEDROCK -> { registerBedrockBlocks(); } + case POST_INIT -> { nullifyBlocksNode(); } + default -> { throw new IllegalArgumentException("Unknown stage: " + stage); } + } + } + /** * Stores the raw blocks JSON until it is no longer needed. */ private static JsonNode BLOCKS_JSON; + private static int minCustomRuntimeID = -1; + private static int maxCustomRuntimeID = -1; + private static int javaBlocksSize = -1; - public static void populate() { - registerJavaBlocks(); - registerBedrockBlocks(); - + private static void nullifyBlocksNode() { BLOCKS_JSON = null; } @@ -154,36 +181,83 @@ public final class BlockRegistryPopulator { Interner statesInterner = Interners.newStrongInterner(); for (Map.Entry, BiFunction> palette : blockMappers.entrySet()) { - NbtList blocksTag; + int protocolVersion = palette.getKey().valueInt(); + List vanillaBlockStates; + List blockStates; try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResource(String.format("bedrock/block_palette.%s.nbt", palette.getKey().key())); - NBTInputStream nbtInputStream = new NBTInputStream(new DataInputStream(new GZIPInputStream(stream)), true, true)) { + NBTInputStream nbtInputStream = new NBTInputStream(new DataInputStream(new GZIPInputStream(stream)), true, true)) { NbtMap blockPalette = (NbtMap) nbtInputStream.readTag(); - blocksTag = (NbtList) blockPalette.getList("blocks", NbtType.COMPOUND); + + vanillaBlockStates = new ArrayList<>(blockPalette.getList("blocks", NbtType.COMPOUND)); + for (int i = 0; i < vanillaBlockStates.size(); i++) { + NbtMapBuilder builder = vanillaBlockStates.get(i).toBuilder(); + builder.remove("name_hash"); // Quick workaround - was added in 1.19.20 + builder.remove("network_id"); // Added in 1.19.80 - ???? + builder.putCompound("states", statesInterner.intern((NbtMap) builder.remove("states"))); + vanillaBlockStates.set(i, builder.build()); + } + + blockStates = new ArrayList<>(vanillaBlockStates); } catch (Exception e) { throw new AssertionError("Unable to get blocks from runtime block states", e); } + int stateVersion = vanillaBlockStates.get(0).getInt("version"); + + List customBlockProperties = new ArrayList<>(); + List customBlockStates = new ArrayList<>(); + List customExtBlockStates = new ArrayList<>(); + int[] remappedVanillaIds = new int[0]; + if (BlockRegistries.CUSTOM_BLOCKS.get().length != 0) { + for (CustomBlockData customBlock : BlockRegistries.CUSTOM_BLOCKS.get()) { + customBlockProperties.add(CustomBlockRegistryPopulator.generateBlockPropertyData(customBlock, protocolVersion)); + CustomBlockRegistryPopulator.generateCustomBlockStates(customBlock, customBlockStates, customExtBlockStates, stateVersion); + } + blockStates.addAll(customBlockStates); + GeyserImpl.getInstance().getLogger().debug("Added " + customBlockStates.size() + " custom block states to v" + protocolVersion + " palette."); + + // The palette is sorted by the FNV1 64-bit hash of the name + blockStates.sort((a, b) -> Long.compareUnsigned(fnv164(a.getString("name")), fnv164(b.getString("name")))); + } + // 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 - Object2ObjectMap blockStateOrderedMap = new Object2ObjectOpenHashMap<>(blocksTag.size()); - GeyserBedrockBlock[] bedrockRuntimeMap = new GeyserBedrockBlock[blocksTag.size()]; - - int stateVersion = -1; - for (int i = 0; i < blocksTag.size(); i++) { - NbtMapBuilder builder = blocksTag.get(i).toBuilder(); - builder.remove("name_hash"); // Quick workaround - was added in 1.19.20 - builder.remove("network_id"); // Added in 1.19.80 - ???? - builder.putCompound("states", statesInterner.intern((NbtMap) builder.remove("states"))); - NbtMap tag = builder.build(); + Object2ObjectMap blockStateOrderedMap = new Object2ObjectOpenHashMap<>(blockStates.size()); + GeyserBedrockBlock[] bedrockRuntimeMap = new GeyserBedrockBlock[blockStates.size()]; + for (int i = 0; i < blockStates.size(); i++) { + NbtMap tag = blockStates.get(i); if (blockStateOrderedMap.containsKey(tag)) { throw new AssertionError("Duplicate block states in Bedrock palette: " + tag); } GeyserBedrockBlock block = new GeyserBedrockBlock(i, tag); blockStateOrderedMap.put(tag, block); bedrockRuntimeMap[i] = block; - if (stateVersion == -1) { - stateVersion = tag.getInt("version"); + } + + Object2ObjectMap customBlockStateDefinitions = Object2ObjectMaps.emptyMap(); + Int2ObjectMap extendedCollisionBoxes = new Int2ObjectOpenHashMap<>(); + if (BlockRegistries.CUSTOM_BLOCKS.get().length != 0) { + customBlockStateDefinitions = new Object2ObjectOpenHashMap<>(customExtBlockStates.size()); + for (int i = 0; i < customExtBlockStates.size(); i++) { + NbtMap tag = customBlockStates.get(i); + CustomBlockState blockState = customExtBlockStates.get(i); + GeyserBedrockBlock bedrockBlock = blockStateOrderedMap.get(tag); + customBlockStateDefinitions.put(blockState, bedrockBlock); + + Set extendedCollisionjavaIds = BlockRegistries.EXTENDED_COLLISION_BOXES.getOrDefault(blockState.block(), null); + if (extendedCollisionjavaIds != null) { + for (int javaId : extendedCollisionjavaIds) { + extendedCollisionBoxes.put(javaId, bedrockBlock); + } + } + } + + remappedVanillaIds = new int[vanillaBlockStates.size()]; + for (int i = 0; i < vanillaBlockStates.size(); i++) { + GeyserBedrockBlock bedrockBlock = blockStateOrderedMap.get(vanillaBlockStates.get(i)); + remappedVanillaIds[i] = bedrockBlock != null ? bedrockBlock.getRuntimeId() : -1; } } + int javaRuntimeId = -1; GeyserBedrockBlock airDefinition = null; @@ -194,7 +268,8 @@ public final class BlockRegistryPopulator { BiFunction stateMapper = blockMappers.getOrDefault(palette.getKey(), emptyMapper); - GeyserBedrockBlock[] javaToBedrockBlocks = new GeyserBedrockBlock[BLOCKS_JSON.size()]; + GeyserBedrockBlock[] javaToBedrockBlocks = new GeyserBedrockBlock[javaBlocksSize]; + GeyserBedrockBlock[] javaToVanillaBedrockBlocks = new GeyserBedrockBlock[javaBlocksSize]; Map flowerPotBlocks = new Object2ObjectOpenHashMap<>(); Map itemFrames = new Object2ObjectOpenHashMap<>(); @@ -206,11 +281,22 @@ public final class BlockRegistryPopulator { javaRuntimeId++; Map.Entry entry = blocksIterator.next(); String javaId = entry.getKey(); + GeyserBedrockBlock vanillaBedrockDefinition = blockStateOrderedMap.get(buildBedrockState(entry.getValue(), stateVersion, stateMapper)); - GeyserBedrockBlock bedrockDefinition = blockStateOrderedMap.get(buildBedrockState(entry.getValue(), stateVersion, stateMapper)); - if (bedrockDefinition == null) { - throw new RuntimeException("Unable to find " + javaId + " Bedrock BlockDefinition on version " - + palette.getKey().key() + "! Built NBT tag: \n" + buildBedrockState(entry.getValue(), stateVersion, stateMapper)); + GeyserBedrockBlock bedrockDefinition; + CustomBlockState blockStateOverride = BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.get(javaRuntimeId); + if (blockStateOverride == null) { + bedrockDefinition = vanillaBedrockDefinition; + if (bedrockDefinition == null) { + throw new RuntimeException("Unable to find " + javaId + " Bedrock runtime ID! Built NBT tag: \n" + + palette.getKey().key() + buildBedrockState(entry.getValue(), stateVersion, stateMapper)); + } + } else { + bedrockDefinition = customBlockStateDefinitions.get(blockStateOverride); + if (bedrockDefinition == null) { + throw new RuntimeException("Unable to find " + javaId + " Bedrock runtime ID! Custom block override: \n" + + blockStateOverride); + } } switch (javaId) { @@ -236,9 +322,10 @@ public final class BlockRegistryPopulator { // Get the tag needed for non-empty flower pots if (entry.getValue().get("pottable") != null) { - flowerPotBlocks.put(cleanJavaIdentifier.intern(), blocksTag.get(bedrockDefinition.getRuntimeId())); + flowerPotBlocks.put(cleanJavaIdentifier.intern(), blockStates.get(bedrockDefinition.getRuntimeId())); } + javaToVanillaBedrockBlocks[javaRuntimeId] = vanillaBedrockDefinition; javaToBedrockBlocks[javaRuntimeId] = bedrockDefinition; } @@ -263,6 +350,33 @@ public final class BlockRegistryPopulator { } builder.bedrockMovingBlock(movingBlockDefinition); + Map nonVanillaStateOverrides = BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get(); + if (nonVanillaStateOverrides.size() > 0) { + // First ensure all non vanilla runtime IDs at minimum are air in case they aren't consecutive + Arrays.fill(javaToVanillaBedrockBlocks, minCustomRuntimeID, javaToVanillaBedrockBlocks.length, airDefinition); + Arrays.fill(javaToBedrockBlocks, minCustomRuntimeID, javaToBedrockBlocks.length, airDefinition); + + for (Map.Entry entry : nonVanillaStateOverrides.entrySet()) { + GeyserBedrockBlock bedrockDefinition = customBlockStateDefinitions.get(entry.getValue()); + if (bedrockDefinition == null) { + GeyserImpl.getInstance().getLogger().warning("Unable to find custom block for " + entry.getValue()); + continue; + } + + JavaBlockState javaState = entry.getKey(); + int stateRuntimeId = javaState.javaId(); + + boolean waterlogged = javaState.waterlogged(); + + if (waterlogged) { + BlockRegistries.WATERLOGGED.register(set -> set.set(stateRuntimeId)); + } + + javaToVanillaBedrockBlocks[stateRuntimeId] = bedrockDefinition; // TODO: Check this? + javaToBedrockBlocks[stateRuntimeId] = bedrockDefinition; + } + } + // Loop around again to find all item frame runtime IDs Object2ObjectMaps.fastForEach(blockStateOrderedMap, entry -> { String name = entry.getKey().getString("name"); @@ -274,10 +388,15 @@ public final class BlockRegistryPopulator { BlockRegistries.BLOCKS.register(palette.getKey().valueInt(), builder.blockStateVersion(stateVersion) .bedrockRuntimeMap(bedrockRuntimeMap) .javaToBedrockBlocks(javaToBedrockBlocks) + .javaToVanillaBedrockBlocks(javaToVanillaBedrockBlocks) .stateDefinitionMap(blockStateOrderedMap) .itemFrames(itemFrames) .flowerPotBlocks(flowerPotBlocks) .jigsawStates(jigsawDefinitions) + .remappedVanillaIds(remappedVanillaIds) + .blockProperties(customBlockProperties) + .customBlockStateDefinitions(customBlockStateDefinitions) + .extendedCollisionBoxes(extendedCollisionBoxes) .build()); } } @@ -290,7 +409,20 @@ public final class BlockRegistryPopulator { throw new AssertionError("Unable to load Java block mappings", e); } - BlockRegistries.JAVA_BLOCKS.set(new BlockMapping[blocksJson.size()]); // Set array size to number of blockstates + javaBlocksSize = blocksJson.size(); + + if (BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().size() > 0) { + minCustomRuntimeID = BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().keySet().stream().min(Comparator.comparing(JavaBlockState::javaId)).get().javaId(); + maxCustomRuntimeID = BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().keySet().stream().max(Comparator.comparing(JavaBlockState::javaId)).get().javaId(); + + if (minCustomRuntimeID < blocksJson.size()) { + throw new RuntimeException("Non vanilla custom block state overrides runtime ID must start after the last vanilla block state (" + javaBlocksSize + ")"); + } + + javaBlocksSize = maxCustomRuntimeID + 1; // Runtime ids start at 0, so we need to add 1 + } + + BlockRegistries.JAVA_BLOCKS.set(new BlockMapping[javaBlocksSize]); // Set array size to number of blockstates Deque cleanIdentifiers = new ArrayDeque<>(); @@ -428,6 +560,46 @@ public final class BlockRegistryPopulator { } BlockStateValues.JAVA_WATER_ID = waterRuntimeId; + if (BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().size() > 0) { + Set usedNonVanillaRuntimeIDs = new HashSet<>(); + + for (JavaBlockState javaBlockState : BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().keySet()) { + if (!usedNonVanillaRuntimeIDs.add(javaBlockState.javaId())) { + throw new RuntimeException("Duplicate runtime ID " + javaBlockState.javaId() + " for non vanilla Java block state " + javaBlockState.identifier()); + } + + CustomBlockState customBlockState = BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().get(javaBlockState); + + String javaId = javaBlockState.identifier(); + int stateRuntimeId = javaBlockState.javaId(); + BlockMapping blockMapping = BlockMapping.builder() + .canBreakWithHand(javaBlockState.canBreakWithHand()) + .pickItem(javaBlockState.pickItem()) + .isNonVanilla(true) + .javaIdentifier(javaId) + .javaBlockId(javaBlockState.stateGroupId()) + .hardness(javaBlockState.blockHardness()) + .pistonBehavior(javaBlockState.pistonBehavior() == null ? PistonBehavior.NORMAL : PistonBehavior.getByName(javaBlockState.pistonBehavior())) + .isBlockEntity(javaBlockState.hasBlockEntity()) + .build(); + + String cleanJavaIdentifier = BlockUtils.getCleanIdentifier(javaBlockState.identifier()); + String bedrockIdentifier = customBlockState.block().identifier(); + + if (!cleanJavaIdentifier.equals(cleanIdentifiers.peekLast())) { + uniqueJavaId++; + cleanIdentifiers.add(cleanJavaIdentifier.intern()); + } + + BlockRegistries.JAVA_IDENTIFIER_TO_ID.register(javaId, stateRuntimeId); + BlockRegistries.JAVA_BLOCKS.register(stateRuntimeId, blockMapping); + + // Keeping this here since this is currently unchanged between versions + // It's possible to only have this store differences in names, but the key set of all Java names is used in sending command suggestions + BlockRegistries.JAVA_TO_BEDROCK_IDENTIFIERS.register(cleanJavaIdentifier.intern(), bedrockIdentifier.intern()); + } + } + BlockRegistries.CLEAN_JAVA_IDENTIFIERS.set(cleanIdentifiers.toArray(new String[0])); BLOCKS_JSON = blocksJson; @@ -481,4 +653,22 @@ public final class BlockRegistryPopulator { tagBuilder.put("states", statesBuilder.build()); return tagBuilder.build(); } + + private static final long FNV1_64_OFFSET_BASIS = 0xcbf29ce484222325L; + private static final long FNV1_64_PRIME = 1099511628211L; + + /** + * Hashes a string using the FNV-1a 64-bit algorithm. + * + * @param str The string to hash + * @return The hashed string + */ + private static long fnv164(String str) { + long hash = FNV1_64_OFFSET_BASIS; + for (byte b : str.getBytes(StandardCharsets.UTF_8)) { + hash *= FNV1_64_PRIME; + hash ^= b; + } + return hash; + } } diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java new file mode 100644 index 000000000..5d453582c --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java @@ -0,0 +1,480 @@ +package org.geysermc.geyser.registry.populator; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtMapBuilder; +import org.cloudburstmc.nbt.NbtType; +import org.cloudburstmc.protocol.bedrock.codec.v594.Bedrock_v594; +import org.cloudburstmc.protocol.bedrock.data.BlockPropertyData; +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.block.custom.CustomBlockData; +import org.geysermc.geyser.api.block.custom.CustomBlockPermutation; +import org.geysermc.geyser.api.block.custom.CustomBlockState; +import org.geysermc.geyser.api.block.custom.component.BoxComponent; +import org.geysermc.geyser.api.block.custom.component.CustomBlockComponents; +import org.geysermc.geyser.api.block.custom.component.MaterialInstance; +import org.geysermc.geyser.api.block.custom.component.PlacementConditions; +import org.geysermc.geyser.api.block.custom.component.PlacementConditions.Face; +import org.geysermc.geyser.api.block.custom.nonvanilla.JavaBlockState; +import org.geysermc.geyser.api.block.custom.property.CustomBlockProperty; +import org.geysermc.geyser.api.block.custom.property.PropertyType; +import org.geysermc.geyser.api.event.lifecycle.GeyserDefineCustomBlocksEvent; +import org.geysermc.geyser.api.util.CreativeCategory; +import org.geysermc.geyser.level.block.GeyserCustomBlockState; +import org.geysermc.geyser.level.block.GeyserCustomBlockComponents.CustomBlockComponentsBuilder; +import org.geysermc.geyser.level.block.GeyserCustomBlockData.CustomBlockDataBuilder; +import org.geysermc.geyser.level.block.GeyserGeometryComponent.GeometryComponentBuilder; +import org.geysermc.geyser.level.block.GeyserMaterialInstance.MaterialInstanceBuilder; +import org.geysermc.geyser.registry.BlockRegistries; +import org.geysermc.geyser.registry.mappings.MappingsConfigReader; +import org.geysermc.geyser.registry.type.CustomSkull; +import org.geysermc.geyser.util.MathUtils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class CustomBlockRegistryPopulator { + /** + * The stage of population + */ + public enum Stage { + DEFINITION, + VANILLA_REGISTRATION, + NON_VANILLA_REGISTRATION, + CUSTOM_REGISTRATION; + } + + /** + * Populates the custom block registries by stage + * + * @param stage the stage to populate + */ + public static void populate(Stage stage) { + if (!GeyserImpl.getInstance().getConfig().isAddNonBedrockItems()) { + return; + } + + switch (stage) { + case DEFINITION -> { populateBedrock(); } + case VANILLA_REGISTRATION -> { populateVanilla(); } + case NON_VANILLA_REGISTRATION -> { populateNonVanilla(); } + case CUSTOM_REGISTRATION -> { registration(); } + default -> { throw new IllegalArgumentException("Unknown stage: " + stage); } + } + } + + private static Set customBlocks; + private static Set customBlockNames; + private static Int2ObjectMap blockStateOverrides; + private static Map customBlockItemOverrides; + private static Map nonVanillaBlockStateOverrides; + + /** + * Initializes custom blocks defined by API + */ + private static void populateBedrock() { + customBlocks = new ObjectOpenHashSet<>(); + customBlockNames = new ObjectOpenHashSet<>(); + blockStateOverrides = new Int2ObjectOpenHashMap<>(); + customBlockItemOverrides = new HashMap<>(); + nonVanillaBlockStateOverrides = new HashMap<>(); + + GeyserImpl.getInstance().getEventBus().fire(new GeyserDefineCustomBlocksEvent() { + @Override + public void register(@NonNull CustomBlockData customBlockData) { + if (customBlockData.name().length() == 0) { + throw new IllegalArgumentException("Custom block name must have at least 1 character."); + } + if (!customBlockNames.add(customBlockData.name())) { + throw new IllegalArgumentException("Another custom block was already registered under the name: " + customBlockData.name()); + } + if (Character.isDigit(customBlockData.name().charAt(0))) { + throw new IllegalArgumentException("Custom block can not start with a digit. Name: " + customBlockData.name()); + } + customBlocks.add(customBlockData); + } + + @Override + public void registerOverride(@NonNull String javaIdentifier, @NonNull CustomBlockState customBlockState) { + int id = BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(javaIdentifier, -1); + if (id == -1) { + throw new IllegalArgumentException("Unknown Java block state. Identifier: " + javaIdentifier); + } + if (!customBlocks.contains(customBlockState.block())) { + throw new IllegalArgumentException("Custom block is unregistered. Name: " + customBlockState.name()); + } + CustomBlockState oldBlockState = blockStateOverrides.put(id, customBlockState); + if (oldBlockState != null) { + GeyserImpl.getInstance().getLogger().debug("Duplicate block state override for Java Identifier: " + + javaIdentifier + " Old override: " + oldBlockState.name() + " New override: " + customBlockState.name()); + } + } + + @Override + public void registerItemOverride(@NonNull String javaIdentifier, @NonNull CustomBlockData customBlockData) { + if (!customBlocks.contains(customBlockData)) { + throw new IllegalArgumentException("Custom block is unregistered. Name: " + customBlockData.name()); + } + customBlockItemOverrides.put(javaIdentifier, customBlockData); + } + + @Override + public void registerOverride(@NonNull JavaBlockState javaBlockState, @NonNull CustomBlockState customBlockState) { + if (!customBlocks.contains(customBlockState.block())) { + throw new IllegalArgumentException("Custom block is unregistered. Name: " + customBlockState.name()); + } + nonVanillaBlockStateOverrides.put(javaBlockState, customBlockState); + } + }); + } + + /** + * Registers all vanilla custom blocks and skulls defined by API and mappings + */ + private static void populateVanilla() { + for (CustomSkull customSkull : BlockRegistries.CUSTOM_SKULLS.get().values()) { + customBlocks.add(customSkull.getCustomBlockData()); + } + + Map> extendedCollisionBoxes = new HashMap<>(); + Map extendedCollisionBoxSet = new HashMap<>(); + MappingsConfigReader mappingsConfigReader = new MappingsConfigReader(); + mappingsConfigReader.loadBlockMappingsFromJson((key, block) -> { + customBlocks.add(block.data()); + if (block.overrideItem()) { + customBlockItemOverrides.put(block.javaIdentifier(), block.data()); + } + block.states().forEach((javaIdentifier, customBlockState) -> { + int id = BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(javaIdentifier, -1); + blockStateOverrides.put(id, customBlockState.state()); + BoxComponent extendedCollisionBox = customBlockState.extendedCollisionBox(); + if (extendedCollisionBox != null) { + CustomBlockData extendedCollisionBlock = extendedCollisionBoxSet.computeIfAbsent(extendedCollisionBox, box -> { + CustomBlockData collisionBlock = createExtendedCollisionBlock(box, extendedCollisionBoxSet.size()); + customBlocks.add(collisionBlock); + return collisionBlock; + }); + extendedCollisionBoxes.computeIfAbsent(extendedCollisionBlock, k -> new HashSet<>()) + .add(id); + } + }); + }); + + BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.set(blockStateOverrides); + GeyserImpl.getInstance().getLogger().info("Registered " + blockStateOverrides.size() + " custom block overrides."); + + BlockRegistries.CUSTOM_BLOCK_ITEM_OVERRIDES.set(customBlockItemOverrides); + GeyserImpl.getInstance().getLogger().info("Registered " + customBlockItemOverrides.size() + " custom block item overrides."); + + BlockRegistries.EXTENDED_COLLISION_BOXES.set(extendedCollisionBoxes); + GeyserImpl.getInstance().getLogger().info("Registered " + extendedCollisionBoxes.size() + " custom block extended collision boxes."); + } + + /** + * Registers all non-vanilla custom blocks defined by API + */ + private static void populateNonVanilla() { + BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.set(nonVanillaBlockStateOverrides); + GeyserImpl.getInstance().getLogger().info("Registered " + nonVanillaBlockStateOverrides.size() + " non-vanilla block overrides."); + } + + /** + * Registers all bedrock custom blocks defined in previous stages + */ + private static void registration() { + BlockRegistries.CUSTOM_BLOCKS.set(customBlocks.toArray(new CustomBlockData[0])); + GeyserImpl.getInstance().getLogger().info("Registered " + customBlocks.size() + " custom blocks."); + } + + /** + * Generates and appends all custom block states to the provided list of custom block states + * Appends the custom block states to the provided list of NBT maps + * + * @param customBlock the custom block data to generate states for + * @param blockStates the list of NBT maps to append the custom block states to + * @param customExtBlockStates the list of custom block states to append the custom block states to + * @param stateVersion the state version to use for the custom block states + */ + static void generateCustomBlockStates(CustomBlockData customBlock, List blockStates, List customExtBlockStates, int stateVersion) { + int totalPermutations = 1; + for (CustomBlockProperty property : customBlock.properties().values()) { + totalPermutations *= property.values().size(); + } + + for (int i = 0; i < totalPermutations; i++) { + NbtMapBuilder statesBuilder = NbtMap.builder(); + int permIndex = i; + for (CustomBlockProperty property : customBlock.properties().values()) { + statesBuilder.put(property.name(), property.values().get(permIndex % property.values().size())); + permIndex /= property.values().size(); + } + NbtMap states = statesBuilder.build(); + + blockStates.add(NbtMap.builder() + .putString("name", customBlock.identifier()) + .putInt("version", stateVersion) + .putCompound("states", states) + .build()); + customExtBlockStates.add(new GeyserCustomBlockState(customBlock, states)); + } + } + + /** + * Generates and returns the block property data for the provided custom block + * + * @param customBlock the custom block to generate block property data for + * @param protocolVersion the protocol version to use for the block property data + * @return the block property data for the provided custom block + */ + @SuppressWarnings("unchecked") + static BlockPropertyData generateBlockPropertyData(CustomBlockData customBlock, int protocolVersion) { + List permutations = new ArrayList<>(); + for (CustomBlockPermutation permutation : customBlock.permutations()) { + permutations.add(NbtMap.builder() + .putCompound("components", CustomBlockRegistryPopulator.convertComponents(permutation.components(), protocolVersion)) + .putString("condition", permutation.condition()) + .build()); + } + + // The order that properties are defined influences the order that block states are generated + List properties = new ArrayList<>(); + for (CustomBlockProperty property : customBlock.properties().values()) { + NbtMapBuilder propertyBuilder = NbtMap.builder() + .putString("name", property.name()); + if (property.type() == PropertyType.booleanProp()) { + propertyBuilder.putList("enum", NbtType.BYTE, List.of((byte) 0, (byte) 1)); + } else if (property.type() == PropertyType.integerProp()) { + propertyBuilder.putList("enum", NbtType.INT, (List) property.values()); + } else if (property.type() == PropertyType.stringProp()) { + propertyBuilder.putList("enum", NbtType.STRING, (List) property.values()); + } + properties.add(propertyBuilder.build()); + } + + CreativeCategory creativeCategory = customBlock.creativeCategory() != null ? customBlock.creativeCategory() : CreativeCategory.NONE; + String creativeGroup = customBlock.creativeGroup() != null ? customBlock.creativeGroup() : ""; + NbtMap propertyTag = NbtMap.builder() + .putCompound("components", CustomBlockRegistryPopulator.convertComponents(customBlock.components(), protocolVersion)) + // this is required or the client will crash + // in the future, this can be used to replace items in the creative inventory + // this would require us to map https://wiki.bedrock.dev/documentation/creative-categories.html#for-blocks programatically + .putCompound("menu_category", NbtMap.builder() + .putString("category", creativeCategory.internalName()) + .putString("group", creativeGroup) + .putBoolean("is_hidden_in_commands", false) + .build()) + // meaning of this version is unknown, but it's required for tags to work and should probably be checked periodically + .putInt("molangVersion", 1) + .putList("permutations", NbtType.COMPOUND, permutations) + .putList("properties", NbtType.COMPOUND, properties) + .build(); + return new BlockPropertyData(customBlock.identifier(), propertyTag); + } + + /** + * Converts the provided custom block components to an {@link NbtMap} to be sent to the client in the StartGame packet + * + * @param components the custom block components to convert + * @param protocolVersion the protocol version to use for the conversion + * @return the NBT representation of the provided custom block components + */ + private static NbtMap convertComponents(CustomBlockComponents components, int protocolVersion) { + if (components == null) { + return NbtMap.EMPTY; + } + + NbtMapBuilder builder = NbtMap.builder(); + if (components.displayName() != null) { + builder.putCompound("minecraft:display_name", NbtMap.builder() + .putString("value", components.displayName()) + .build()); + } + + if (components.selectionBox() != null) { + builder.putCompound("minecraft:selection_box", convertBox(components.selectionBox())); + } + + if (components.collisionBox() != null) { + builder.putCompound("minecraft:collision_box", convertBox(components.collisionBox())); + } + + if (components.geometry() != null) { + NbtMapBuilder geometryBuilder = NbtMap.builder(); + if (protocolVersion >= Bedrock_v594.CODEC.getProtocolVersion()) { + geometryBuilder.putString("identifier", components.geometry().identifier()); + if (components.geometry().boneVisibility() != null) { + NbtMapBuilder boneVisibilityBuilder = NbtMap.builder(); + components.geometry().boneVisibility().entrySet().forEach( + entry -> boneVisibilityBuilder.putString(entry.getKey(), entry.getValue())); + geometryBuilder.putCompound("bone_visibility", boneVisibilityBuilder.build()); + } + } else { + geometryBuilder.putString("value", components.geometry().identifier()); + } + builder.putCompound("minecraft:geometry", geometryBuilder.build()); + } + + if (!components.materialInstances().isEmpty()) { + NbtMapBuilder materialsBuilder = NbtMap.builder(); + for (Map.Entry entry : components.materialInstances().entrySet()) { + MaterialInstance materialInstance = entry.getValue(); + materialsBuilder.putCompound(entry.getKey(), NbtMap.builder() + .putString("texture", materialInstance.texture()) + .putString("render_method", materialInstance.renderMethod()) + .putBoolean("face_dimming", materialInstance.faceDimming()) + .putBoolean("ambient_occlusion", materialInstance.faceDimming()) + .build()); + } + + builder.putCompound("minecraft:material_instances", NbtMap.builder() + // we could read these, but there is no functional reason to use them at the moment + // they only allow you to make aliases for material instances + // but you could already just define the same instance twice if this was really needed + .putCompound("mappings", NbtMap.EMPTY) + .putCompound("materials", materialsBuilder.build()) + .build()); + } + + if (components.placementFilter() != null) { + builder.putCompound("minecraft:placement_filter", NbtMap.builder() + .putList("conditions", NbtType.COMPOUND, convertPlacementFilter(components.placementFilter())) + .build()); + } + + if (components.destructibleByMining() != null) { + builder.putCompound("minecraft:destructible_by_mining", NbtMap.builder() + .putFloat("value", components.destructibleByMining()) + .build()); + } + + if (components.friction() != null) { + builder.putCompound("minecraft:friction", NbtMap.builder() + .putFloat("value", components.friction()) + .build()); + } + + if (components.lightEmission() != null) { + builder.putCompound("minecraft:light_emission", NbtMap.builder() + .putByte("emission", components.lightEmission().byteValue()) + .build()); + } + + if (components.lightDampening() != null) { + builder.putCompound("minecraft:light_dampening", NbtMap.builder() + .putByte("lightLevel", components.lightDampening().byteValue()) + .build()); + } + + if (components.transformation() != null) { + builder.putCompound("minecraft:transformation", NbtMap.builder() + .putInt("RX", MathUtils.unwrapDegreesToInt(components.transformation().rx()) / 90) + .putInt("RY", MathUtils.unwrapDegreesToInt(components.transformation().ry()) / 90) + .putInt("RZ", MathUtils.unwrapDegreesToInt(components.transformation().rz()) / 90) + .putFloat("SX", components.transformation().sx()) + .putFloat("SY", components.transformation().sy()) + .putFloat("SZ", components.transformation().sz()) + .putFloat("TX", components.transformation().tx()) + .putFloat("TY", components.transformation().ty()) + .putFloat("TZ", components.transformation().tz()) + .build()); + } + + if (components.unitCube()) { + builder.putCompound("minecraft:unit_cube", NbtMap.EMPTY); + } + + // place_air is not an actual component + // We just apply a dummy event to prevent the client from trying to place a block + // This mitigates the issue with the client sometimes double placing blocks + if (components.placeAir()) { + builder.putCompound("minecraft:on_player_placing", NbtMap.builder() + .putString("triggerType", "geyser:place_event") + .build()); + } + + if (!components.tags().isEmpty()) { + components.tags().forEach(tag -> builder.putCompound("tag:" + tag, NbtMap.EMPTY)); + } + + return builder.build(); + } + + /** + * Converts the provided box component to an {@link NbtMap} + * + * @param boxComponent the box component to convert + * @return the NBT representation of the provided box component + */ + private static NbtMap convertBox(BoxComponent boxComponent) { + return NbtMap.builder() + .putBoolean("enabled", !boxComponent.isEmpty()) + .putList("origin", NbtType.FLOAT, boxComponent.originX(), boxComponent.originY(), boxComponent.originZ()) + .putList("size", NbtType.FLOAT, boxComponent.sizeX(), boxComponent.sizeY(), boxComponent.sizeZ()) + .build(); + } + + /** + * Converts the provided placement filter to a list of {@link NbtMap} + * + * @param placementFilter the placement filter to convert + * @return the NBT representation of the provided placement filter + */ + private static List convertPlacementFilter(List placementFilter) { + List conditions = new ArrayList<>(); + placementFilter.forEach((condition) -> { + NbtMapBuilder conditionBuilder = NbtMap.builder(); + + // allowed_faces on the network is represented by 6 bits for the 6 possible faces + // the enum has the proper values for that face only, so we just bitwise OR them together + byte allowedFaces = 0; + for (Face face : condition.allowedFaces()) { allowedFaces |= (1 << face.ordinal()); } + conditionBuilder.putByte("allowed_faces", allowedFaces); + + // block_filters is a list of either blocks or queries for block tags + // if these match the block the player is trying to place on, the placement is allowed by the client + List blockFilters = new ArrayList<>(); + condition.blockFilters().forEach((value, type) -> { + NbtMapBuilder blockFilterBuilder = NbtMap.builder(); + switch (type) { + case BLOCK -> blockFilterBuilder.putString("name", value); + // meaning of this version is unknown, but it's required for tags to work and should probably be checked periodically + case TAG -> blockFilterBuilder.putString("tags", value).putInt("tags_version", 6); + } + blockFilters.add(blockFilterBuilder.build()); + }); + conditionBuilder.putList("block_filters", NbtType.COMPOUND, blockFilters); + conditions.add(conditionBuilder.build()); + }); + + return conditions; + } + + private static CustomBlockData createExtendedCollisionBlock(BoxComponent boxComponent, int extendedCollisionBlock) { + CustomBlockData customBlockData = new CustomBlockDataBuilder() + .name("extended_collision_" + extendedCollisionBlock) + .components( + new CustomBlockComponentsBuilder() + .collisionBox(boxComponent) + .selectionBox(BoxComponent.emptyBox()) + .materialInstance("*", new MaterialInstanceBuilder() + .texture("glass") + .renderMethod("alpha_test") + .faceDimming(false) + .ambientOcclusion(false) + .build()) + .lightDampening(0) + .geometry(new GeometryComponentBuilder() + .identifier("geometry.invisible") + .build()) + .build()) + .build(); + return customBlockData; + } +} 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 629fc17c5..3f3f5a4ba 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 @@ -41,10 +41,9 @@ 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.Items; -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.item.type.Item; +import org.geysermc.geyser.registry.mappings.MappingsConfigReader; import org.geysermc.geyser.registry.type.GeyserMappingItem; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.NonVanillaItemRegistration; @@ -56,7 +55,7 @@ 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) -> { + mappingsConfigReader.loadItemMappingsFromJson((key, item) -> { if (CustomItemRegistryPopulator.initialCheck(key, item, items)) { customItems.get(key).add(item); } @@ -294,34 +293,45 @@ public class CustomItemRegistryPopulator { boolean canDestroyInCreative = true; float miningSpeed = 1.0f; - if (toolType.equals("shears")) { - componentBuilder.putCompound("minecraft:digger", ToolBreakSpeedsUtils.getShearsDigger(15)); - } else { - int toolSpeed = ToolBreakSpeedsUtils.toolTierToSpeed(toolTier); - switch (toolType) { - case "sword" -> { - miningSpeed = 1.5f; - canDestroyInCreative = false; - componentBuilder.putCompound("minecraft:digger", ToolBreakSpeedsUtils.getSwordDigger(toolSpeed)); - componentBuilder.putCompound("minecraft:weapon", NbtMap.EMPTY); - } - case "pickaxe" -> { - componentBuilder.putCompound("minecraft:digger", ToolBreakSpeedsUtils.getPickaxeDigger(toolSpeed, toolTier)); - setItemTag(componentBuilder, "pickaxe"); - } - case "axe" -> { - componentBuilder.putCompound("minecraft:digger", ToolBreakSpeedsUtils.getAxeDigger(toolSpeed)); - setItemTag(componentBuilder, "axe"); - } - case "shovel" -> { - componentBuilder.putCompound("minecraft:digger", ToolBreakSpeedsUtils.getShovelDigger(toolSpeed)); - setItemTag(componentBuilder, "shovel"); - } - case "hoe" -> { - componentBuilder.putCompound("minecraft:digger", ToolBreakSpeedsUtils.getHoeDigger(toolSpeed)); - setItemTag(componentBuilder, "hoe"); - } - } + // This means client side the tool can never destroy a block + // This works because the molang '1' for tags will be true for all blocks and the speed will be 0 + // We want this since we calculate break speed server side in BedrockActionTranslator + List speed = new ArrayList<>(List.of( + NbtMap.builder() + .putCompound("block", NbtMap.builder() + .putString("tags", "1") + .build()) + .putCompound("on_dig", NbtMap.builder() + .putCompound("condition", NbtMap.builder() + .putString("expression", "") + .putInt("version", -1) + .build()) + .putString("event", "tool_durability") + .putString("target", "self") + .build()) + .putInt("speed", 0) + .build() + )); + + componentBuilder.putCompound("minecraft:digger", + NbtMap.builder() + .putList("destroy_speeds", NbtType.COMPOUND, speed) + .putCompound("on_dig", NbtMap.builder() + .putCompound("condition", NbtMap.builder() + .putString("expression", "") + .putInt("version", -1) + .build()) + .putString("event", "tool_durability") + .putString("target", "self") + .build()) + .putBoolean("use_efficiency", true) + .build() + ); + + if (toolType.equals("sword")) { + miningSpeed = 1.5f; + canDestroyInCreative = false; + componentBuilder.putCompound("minecraft:weapon", NbtMap.EMPTY); } itemProperties.putBoolean("hand_equipped", true); diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomSkullRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomSkullRegistryPopulator.java new file mode 100644 index 000000000..9c17ca952 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomSkullRegistryPopulator.java @@ -0,0 +1,187 @@ +/* + * 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 it.unimi.dsi.fastutil.objects.Object2ObjectMaps; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import lombok.NonNull; +import org.geysermc.geyser.GeyserBootstrap; +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.event.lifecycle.GeyserDefineCustomSkullsEvent; +import org.geysermc.geyser.configuration.GeyserCustomSkullConfiguration; +import org.geysermc.geyser.pack.SkullResourcePackManager; +import org.geysermc.geyser.registry.BlockRegistries; +import org.geysermc.geyser.registry.type.CustomSkull; +import org.geysermc.geyser.skin.SkinManager; +import org.geysermc.geyser.skin.SkinProvider; +import org.geysermc.geyser.text.GeyserLocale; +import org.geysermc.geyser.util.FileUtils; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.function.Function; + +public class CustomSkullRegistryPopulator { + + public static void populate() { + SkullResourcePackManager.SKULL_SKINS.clear(); // Remove skins after reloading + BlockRegistries.CUSTOM_SKULLS.set(Object2ObjectMaps.emptyMap()); + + if (!GeyserImpl.getInstance().getConfig().isAddNonBedrockItems()) { + return; + } + + GeyserCustomSkullConfiguration skullConfig; + try { + GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap(); + Path skullConfigPath = bootstrap.getConfigFolder().resolve("custom-skulls.yml"); + File skullConfigFile = FileUtils.fileOrCopiedFromResource(skullConfigPath.toFile(), "custom-skulls.yml", Function.identity(), bootstrap); + skullConfig = FileUtils.loadConfig(skullConfigFile, GeyserCustomSkullConfiguration.class); + } catch (IOException e) { + GeyserImpl.getInstance().getLogger().severe(GeyserLocale.getLocaleStringLog("geyser.config.failed"), e); + return; + } + + BlockRegistries.CUSTOM_SKULLS.set(new Object2ObjectOpenHashMap<>()); + + List profiles = new ArrayList<>(skullConfig.getPlayerProfiles()); + List usernames = new ArrayList<>(skullConfig.getPlayerUsernames()); + List uuids = new ArrayList<>(skullConfig.getPlayerUUIDs()); + List skinHashes = new ArrayList<>(skullConfig.getPlayerSkinHashes()); + + GeyserImpl.getInstance().getEventBus().fire(new GeyserDefineCustomSkullsEvent() { + @Override + public void register(@NonNull String texture, @NonNull SkullTextureType type) { + switch (type) { + case USERNAME -> usernames.add(texture); + case UUID -> uuids.add(texture); + case PROFILE -> profiles.add(texture); + case SKIN_HASH -> skinHashes.add(texture); + } + } + }); + + usernames.forEach((username) -> { + String profile = getProfileFromUsername(username); + if (profile != null) { + String skinHash = getSkinHash(profile); + if (skinHash != null) { + skinHashes.add(skinHash); + } + } + }); + + uuids.forEach((uuid) -> { + String profile = getProfileFromUuid(uuid); + if (profile != null) { + String skinHash = getSkinHash(profile); + if (skinHash != null) { + skinHashes.add(skinHash); + } + } + }); + + profiles.forEach((profile) -> { + String skinHash = getSkinHash(profile); + if (skinHash != null) { + skinHashes.add(skinHash); + } + }); + + skinHashes.forEach((skinHash) -> { + if (!skinHash.matches("^[a-fA-F0-9]+$")) { + GeyserImpl.getInstance().getLogger().error("Skin hash " + skinHash + " does not match required format ^[a-fA-F0-9]{64}$ and will not be added as a custom block."); + return; + } + + try { + SkullResourcePackManager.cacheSkullSkin(skinHash); + BlockRegistries.CUSTOM_SKULLS.register(skinHash, new CustomSkull(skinHash)); + } catch (IOException e) { + GeyserImpl.getInstance().getLogger().error("Failed to cache skin for skull texture " + skinHash + " This skull will not be added as a custom block.", e); + } + }); + + GeyserImpl.getInstance().getLogger().info("Registered " + BlockRegistries.CUSTOM_SKULLS.get().size() + " custom skulls as custom blocks."); + } + + /** + * Gets the skin hash from a base64 encoded profile + * @param profile the base64 encoded profile + * @return the skin hash or null if the profile is invalid + */ + private static String getSkinHash(String profile) { + try { + SkinManager.GameProfileData profileData = SkinManager.GameProfileData.loadFromJson(profile); + if (profileData == null) { + GeyserImpl.getInstance().getLogger().warning("Skull texture " + profile + " contained no skins and will not be added as a custom block."); + return null; + } + String skinUrl = profileData.skinUrl(); + return skinUrl.substring(skinUrl.lastIndexOf("/") + 1); + } catch (IOException e) { + GeyserImpl.getInstance().getLogger().error("Skull texture " + profile + " is invalid and will not be added as a custom block.", e); + return null; + } + } + + /** + * Gets the base64 encoded profile from a player's username + * @param username the player username + * @return the base64 encoded profile or null if the request failed + */ + private static String getProfileFromUsername(String username) { + try { + return SkinProvider.requestTexturesFromUsername(username).get(); + } catch (InterruptedException | ExecutionException e) { + GeyserImpl.getInstance().getLogger().error("Unable to request skull textures for " + username + " This skull will not be added as a custom block.", e); + return null; + } + } + + /** + * Gets the base64 encoded profile from a player's UUID + * @param uuid the player UUID + * @return the base64 encoded profile or null if the request failed + */ + private static String getProfileFromUuid(String uuid) { + try { + String uuidDigits = uuid.replace("-", ""); + if (uuidDigits.length() != 32) { + GeyserImpl.getInstance().getLogger().error("Invalid skull uuid " + uuid + " This skull will not be added as a custom block."); + return null; + } + return SkinProvider.requestTexturesFromUUID(uuid).get(); + } catch (InterruptedException | ExecutionException e) { + GeyserImpl.getInstance().getLogger().error("Unable to request skull textures for " + uuid + " This skull will not be added as a custom block.", e); + return null; + } + } +} 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 b0d88c3e7..f243d358a 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 @@ -34,6 +34,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; import it.unimi.dsi.fastutil.objects.*; +import org.geysermc.geyser.Constants; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; @@ -49,15 +50,18 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.block.custom.CustomBlockData; +import org.geysermc.geyser.api.block.custom.CustomBlockState; +import org.geysermc.geyser.api.block.custom.NonVanillaCustomBlockData; 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.inventory.item.StoredItemMappings; import org.geysermc.geyser.item.GeyserCustomMappingData; -import org.geysermc.geyser.item.Items; -import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.Registries; +import org.geysermc.geyser.item.Items; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.registry.type.*; import java.io.InputStream; @@ -176,6 +180,8 @@ public class ItemRegistryPopulator { Object2ObjectMap bedrockBlockIdOverrides = new Object2ObjectOpenHashMap<>(); Object2IntMap blacklistedIdentifiers = new Object2IntOpenHashMap<>(); + Object2ObjectMap customBlockItemDefinitions = new Object2ObjectOpenHashMap<>(); + List buckets = new ObjectArrayList<>(); List carpets = new ObjectArrayList<>(); @@ -249,15 +255,29 @@ public class ItemRegistryPopulator { BlockDefinition bedrockBlock = null; Integer firstBlockRuntimeId = entry.getValue().getFirstBlockRuntimeId(); + BlockDefinition customBlockItemOverride = null; if (firstBlockRuntimeId != null) { BlockDefinition blockOverride = bedrockBlockIdOverrides.get(bedrockIdentifier); - if (blockOverride != null) { + + // We'll do this here for custom blocks we want in the creative inventory so we can piggyback off the existing logic to find these + // blocks in creativeItems + CustomBlockData customBlockData = BlockRegistries.CUSTOM_BLOCK_ITEM_OVERRIDES.getOrDefault(javaItem.javaIdentifier(), null); + if (customBlockData != null) { + // this block has a custom item override and thus we should use its runtime ID for the ItemMapping + if (customBlockData.includedInCreativeInventory()) { + CustomBlockState customBlockState = customBlockData.defaultBlockState(); + customBlockItemOverride = blockMappings.getCustomBlockStateDefinitions().getOrDefault(customBlockState, null); + } + } + + // If it' s a custom block we can't do this because we need to make sure we find the creative item + if (blockOverride != null && customBlockItemOverride == null) { // Straight from BDS is our best chance of getting an item that doesn't run into issues bedrockBlock = blockOverride; } else { // Try to get an example block runtime ID from the creative contents packet, for Bedrock identifier obtaining - int aValidBedrockBlockId = blacklistedIdentifiers.getOrDefault(bedrockIdentifier, -1); - if (aValidBedrockBlockId == -1) { + int aValidBedrockBlockId = blacklistedIdentifiers.getOrDefault(bedrockIdentifier, customBlockItemOverride != null ? customBlockItemOverride.getRuntimeId() : -1); + if (aValidBedrockBlockId == -1 && customBlockItemOverride == null) { // Fallback bedrockBlock = blockMappings.getBedrockBlock(firstBlockRuntimeId); } else { @@ -273,7 +293,7 @@ public class ItemRegistryPopulator { // and the last, if relevant. We then iterate over all those values and get their Bedrock equivalents Integer lastBlockRuntimeId = entry.getValue().getLastBlockRuntimeId() == null ? firstBlockRuntimeId : entry.getValue().getLastBlockRuntimeId(); for (int i = firstBlockRuntimeId; i <= lastBlockRuntimeId; i++) { - GeyserBedrockBlock bedrockBlockRuntimeId = blockMappings.getBedrockBlock(i); + GeyserBedrockBlock bedrockBlockRuntimeId = blockMappings.getVanillaBedrockBlock(i); NbtMap blockTag = bedrockBlockRuntimeId.getState(); String bedrockName = blockTag.getString("name"); if (!bedrockName.equals(correctBedrockIdentifier)) { @@ -339,6 +359,12 @@ public class ItemRegistryPopulator { // Because we have replaced the Bedrock block ID, we also need to replace the creative contents block runtime ID // That way, creative items work correctly for these blocks + + // Set our custom block override now if there is one + if (customBlockItemOverride != null) { + bedrockBlock = customBlockItemOverride; + } + for (int j = 0; j < creativeItems.size(); j++) { ItemData itemData = creativeItems.get(j); if (itemData.getDefinition().equals(definition)) { @@ -347,16 +373,35 @@ public class ItemRegistryPopulator { } NbtMap states = ((GeyserBedrockBlock) itemData.getBlockDefinition()).getState().getCompound("states"); + boolean valid = true; for (Map.Entry nbtEntry : requiredBlockStates.entrySet()) { - if (!states.get(nbtEntry.getKey()).equals(nbtEntry.getValue())) { + if (states.getOrDefault(nbtEntry.getKey(), null) == null || !states.get(nbtEntry.getKey()).equals(nbtEntry.getValue())) { // A required block state doesn't match - this one is not valid valid = false; break; } } if (valid) { - creativeItems.set(j, itemData.toBuilder().blockDefinition(bedrockBlock).build()); + if (customBlockItemOverride != null && customBlockData != null) { + // Assuming this is a valid custom block override we'll just register it now while we have the creative item + int customProtocolId = nextFreeBedrockId++; + mappingItem.setBedrockData(customProtocolId); + bedrockIdentifier = customBlockData.identifier(); + definition = new SimpleItemDefinition(bedrockIdentifier, customProtocolId, true); + registry.put(customProtocolId, definition); + customBlockItemDefinitions.put(customBlockData, definition); + customIdMappings.put(customProtocolId, bedrockIdentifier); + + creativeItems.set(j, itemData.toBuilder() + .definition(definition) + .blockDefinition(bedrockBlock) + .netId(itemData.getNetId()) + .count(1) + .build()); + } else { + creativeItems.set(j, itemData.toBuilder().blockDefinition(bedrockBlock).build()); + } break; } } @@ -397,10 +442,10 @@ public class ItemRegistryPopulator { for (CustomItemData customItem : customItemsToLoad) { int customProtocolId = nextFreeBedrockId++; - String customItemName = "geyser_custom:" + customItem.name(); + String customItemName = customItem instanceof NonVanillaCustomItemData nonVanillaItem ? nonVanillaItem.identifier() : Constants.GEYSER_CUSTOM_NAMESPACE + ":" + customItem.name(); if (!registeredItemNames.add(customItemName)) { if (firstMappingsPass) { - GeyserImpl.getInstance().getLogger().error("Custom item name '" + customItem.name() + "' already exists and was registered again! Skipping..."); + GeyserImpl.getInstance().getLogger().error("Custom item name '" + customItemName + "' already exists and was registered again! Skipping..."); } continue; } @@ -516,6 +561,41 @@ public class ItemRegistryPopulator { } } + // Register the item forms of custom blocks + if (BlockRegistries.CUSTOM_BLOCKS.get().length != 0) { + for (CustomBlockData customBlock : BlockRegistries.CUSTOM_BLOCKS.get()) { + // We might've registered it already with the vanilla blocks so check first + if (customBlockItemDefinitions.containsKey(customBlock)) { + continue; + } + + // Non-vanilla custom blocks will be handled in the item + // registry, so we don't need to do anything here. + if (customBlock instanceof NonVanillaCustomBlockData) { + continue; + } + + int customProtocolId = nextFreeBedrockId++; + String identifier = customBlock.identifier(); + + final ItemDefinition definition = new SimpleItemDefinition(identifier, customProtocolId, true); + registry.put(customProtocolId, definition); + customBlockItemDefinitions.put(customBlock, definition); + customIdMappings.put(customProtocolId, identifier); + + GeyserBedrockBlock bedrockBlock = blockMappings.getCustomBlockStateDefinitions().getOrDefault(customBlock.defaultBlockState(), null); + + if (bedrockBlock != null && customBlock.includedInCreativeInventory()) { + creativeItems.add(ItemData.builder() + .definition(definition) + .blockDefinition(bedrockBlock) + .netId(creativeNetId.incrementAndGet()) + .count(1) + .build()); + } + } + } + ItemMappings itemMappings = ItemMappings.builder() .items(mappings.toArray(new ItemMapping[0])) .creativeItems(creativeItems.toArray(new ItemData[0])) @@ -527,6 +607,7 @@ public class ItemRegistryPopulator { .componentItemData(componentItemData) .lodestoneCompass(lodestoneEntry) .customIdMappings(customIdMappings) + .customBlockItemDefinitions(customBlockItemDefinitions) .build(); Registries.ITEMS.register(palette.protocolVersion(), itemMappings); diff --git a/core/src/main/java/org/geysermc/geyser/registry/type/BlockMapping.java b/core/src/main/java/org/geysermc/geyser/registry/type/BlockMapping.java index 34cde0acf..528999158 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/type/BlockMapping.java +++ b/core/src/main/java/org/geysermc/geyser/registry/type/BlockMapping.java @@ -56,6 +56,7 @@ public class BlockMapping { @Nonnull PistonBehavior pistonBehavior; boolean isBlockEntity; + boolean isNonVanilla; /** * @return the identifier without the additional block states 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 992ae324a..3c33ea097 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 @@ -25,12 +25,17 @@ package org.geysermc.geyser.registry.type; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import lombok.Builder; import lombok.Value; import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.protocol.bedrock.data.BlockPropertyData; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.common.DefinitionRegistry; +import org.geysermc.geyser.api.block.custom.CustomBlockState; +import java.util.List; import java.util.Map; import java.util.Set; @@ -44,9 +49,11 @@ public class BlockMappings implements DefinitionRegistry { int blockStateVersion; GeyserBedrockBlock[] javaToBedrockBlocks; + GeyserBedrockBlock[] javaToVanillaBedrockBlocks; Map stateDefinitionMap; GeyserBedrockBlock[] bedrockRuntimeMap; + int[] remappedVanillaIds; BlockDefinition commandBlock; @@ -55,6 +62,10 @@ public class BlockMappings implements DefinitionRegistry { Set jigsawStates; + List blockProperties; + Object2ObjectMap customBlockStateDefinitions; + Int2ObjectMap extendedCollisionBoxes; + public int getBedrockBlockId(int javaState) { return getBedrockBlock(javaState).getRuntimeId(); } @@ -66,6 +77,13 @@ public class BlockMappings implements DefinitionRegistry { return this.javaToBedrockBlocks[javaState]; } + public GeyserBedrockBlock getVanillaBedrockBlock(int javaState) { + if (javaState < 0 || javaState >= this.javaToVanillaBedrockBlocks.length) { + return bedrockAir; + } + return this.javaToVanillaBedrockBlocks[javaState]; + } + public BlockDefinition getItemFrame(NbtMap tag) { return this.itemFrames.get(tag); } diff --git a/core/src/main/java/org/geysermc/geyser/registry/type/CustomSkull.java b/core/src/main/java/org/geysermc/geyser/registry/type/CustomSkull.java new file mode 100644 index 000000000..5fe8a0edf --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/type/CustomSkull.java @@ -0,0 +1,166 @@ +/* + * 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.type; + +import lombok.Data; +import org.geysermc.geyser.api.block.custom.CustomBlockData; +import org.geysermc.geyser.api.block.custom.CustomBlockPermutation; +import org.geysermc.geyser.api.block.custom.CustomBlockState; +import org.geysermc.geyser.api.block.custom.component.BoxComponent; +import org.geysermc.geyser.api.block.custom.component.CustomBlockComponents; +import org.geysermc.geyser.api.block.custom.component.TransformationComponent; +import org.geysermc.geyser.level.block.GeyserCustomBlockComponents; +import org.geysermc.geyser.level.block.GeyserCustomBlockData; +import org.geysermc.geyser.level.block.GeyserGeometryComponent.GeometryComponentBuilder; +import org.geysermc.geyser.level.block.GeyserMaterialInstance.MaterialInstanceBuilder; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.IntStream; + +@Data +public class CustomSkull { + private final String skinHash; + + private CustomBlockData customBlockData; + + private static final String BITS_A_PROPERTY = "geyser_skull:bits_a"; + private static final String BITS_B_PROPERTY = "geyser_skull:bits_b"; + + private static final int[] ROTATIONS = {0, -90, 180, 90}; + + private static final BoxComponent FLOOR_BOX = new BoxComponent( + -4, 0, -4, + 8, 8, 8 + ); + + private static final BoxComponent WALL_BOX = new BoxComponent( + -4, 4, 0, + 8, 8, 8 + ); + + public CustomSkull(String skinHash) { + this.skinHash = skinHash; + + CustomBlockComponents components = new GeyserCustomBlockComponents.CustomBlockComponentsBuilder() + .destructibleByMining(1.5f) + .materialInstance("*", new MaterialInstanceBuilder() + .texture("geyser." + skinHash + "_player_skin") + .renderMethod("alpha_test") + .faceDimming(true) + .ambientOcclusion(true) + .build()) + .lightDampening(0) + .placeAir(true) + .build(); + + List permutations = new ArrayList<>(); + addDefaultPermutation(permutations); + addFloorPermutations(permutations); + addWallPermutations(permutations); + + customBlockData = new GeyserCustomBlockData.CustomBlockDataBuilder() + .name("player_skull_" + skinHash) + .components(components) + .intProperty(BITS_A_PROPERTY, IntStream.rangeClosed(0, 6).boxed().toList()) // This gives us exactly 21 block states + .intProperty(BITS_B_PROPERTY, IntStream.rangeClosed(0, 2).boxed().toList()) + .permutations(permutations) + .build(); + } + + public CustomBlockState getWallBlockState(int wallDirection) { + wallDirection = switch (wallDirection) { + case 0 -> 2; // South + case 90 -> 3; // West + case 180 -> 0; // North + case 270 -> 1; // East + default -> throw new IllegalArgumentException("Unknown skull wall direction: " + wallDirection); + }; + + return customBlockData.blockStateBuilder() + .intProperty(BITS_A_PROPERTY, wallDirection + 1) + .intProperty(BITS_B_PROPERTY, 0) + .build(); + } + + public CustomBlockState getFloorBlockState(int floorRotation) { + return customBlockData.blockStateBuilder() + .intProperty(BITS_A_PROPERTY, (5 + floorRotation) % 7) + .intProperty(BITS_B_PROPERTY, (5 + floorRotation) / 7) + .build(); + } + + private void addDefaultPermutation(List permutations) { + CustomBlockComponents components = new GeyserCustomBlockComponents.CustomBlockComponentsBuilder() + .geometry(new GeometryComponentBuilder() + .identifier("geometry.geyser.player_skull_hand") + .build()) + .transformation(new TransformationComponent(0, 180, 0)) + .build(); + + String condition = String.format("query.block_property('%s') == 0 && query.block_property('%s') == 0", BITS_A_PROPERTY, BITS_B_PROPERTY); + permutations.add(new CustomBlockPermutation(components, condition)); + } + + private void addFloorPermutations(List permutations) { + String[] quadrantNames = {"a", "b", "c", "d"}; + + for (int quadrant = 0; quadrant < 4; quadrant++) { + for (int i = 0; i < 4; i++) { + int floorRotation = 4 * quadrant + i; + CustomBlockComponents components = new GeyserCustomBlockComponents.CustomBlockComponentsBuilder() + .selectionBox(FLOOR_BOX) + .collisionBox(FLOOR_BOX) + .geometry(new GeometryComponentBuilder() + .identifier("geometry.geyser.player_skull_floor_" + quadrantNames[i]) + .build()) + .transformation(new TransformationComponent(0, ROTATIONS[quadrant], 0)) + .build(); + + int bitsA = (5 + floorRotation) % 7; + int bitsB = (5 + floorRotation) / 7; + String condition = String.format("query.block_property('%s') == %d && query.block_property('%s') == %d", BITS_A_PROPERTY, bitsA, BITS_B_PROPERTY, bitsB); + permutations.add(new CustomBlockPermutation(components, condition)); + } + } + } + + private void addWallPermutations(List permutations) { + for (int i = 0; i < 4; i++) { + CustomBlockComponents components = new GeyserCustomBlockComponents.CustomBlockComponentsBuilder() + .selectionBox(WALL_BOX) + .collisionBox(WALL_BOX) + .geometry(new GeometryComponentBuilder() + .identifier("geometry.geyser.player_skull_wall") + .build()) + .transformation(new TransformationComponent(0, ROTATIONS[i], 0)) + .build(); + + String condition = String.format("query.block_property('%s') == %d && query.block_property('%s') == %d", BITS_A_PROPERTY, i + 1, BITS_B_PROPERTY, 0); + permutations.add(new CustomBlockPermutation(components, condition)); + } + } +} diff --git a/core/src/main/java/org/geysermc/geyser/registry/type/GeyserMappingItem.java b/core/src/main/java/org/geysermc/geyser/registry/type/GeyserMappingItem.java index ab8c52bf6..c1ef09b87 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/type/GeyserMappingItem.java +++ b/core/src/main/java/org/geysermc/geyser/registry/type/GeyserMappingItem.java @@ -30,6 +30,7 @@ import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; import lombok.ToString; import lombok.With; @@ -39,6 +40,7 @@ import lombok.With; @ToString @EqualsAndHashCode @Getter +@Setter @With @NoArgsConstructor @AllArgsConstructor 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 65cc28420..704d5c211 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 @@ -27,6 +27,7 @@ package org.geysermc.geyser.registry.type; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import lombok.Builder; import lombok.Value; import org.checkerframework.checker.nullness.qual.NonNull; @@ -36,6 +37,7 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.common.DefinitionRegistry; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.block.custom.CustomBlockData; import org.geysermc.geyser.inventory.item.StoredItemMappings; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.Item; @@ -72,6 +74,8 @@ public class ItemMappings implements DefinitionRegistry { List componentItemData; Int2ObjectMap customIdMappings; + Object2ObjectMap customBlockItemDefinitions; + /** * Gets an {@link ItemMapping} from the given {@link ItemStack}. * diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index e09cff9e4..7197a4fc4 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -464,6 +464,12 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { @Setter private long lastInteractionTime; + /** + * Stores when the player started to break a block. Used to allow correct break time for custom blocks. + */ + @Setter + private long blockBreakStartTime; + /** * Stores whether the player intended to place a bucket. */ @@ -1563,6 +1569,17 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { startGamePacket.setItemDefinitions(this.itemMappings.getItemDefinitions().values().stream().toList()); // TODO // startGamePacket.setBlockPalette(this.blockMappings.getBedrockBlockPalette()); + // Needed for custom block mappings and custom skulls system + startGamePacket.getBlockProperties().addAll(this.blockMappings.getBlockProperties()); + + // See https://learn.microsoft.com/en-us/minecraft/creator/documents/experimentalfeaturestoggle for info on each experiment + // data_driven_items (Holiday Creator Features) is needed for blocks and items + startGamePacket.getExperiments().add(new ExperimentData("data_driven_items", true)); + // Needed for block properties for states + startGamePacket.getExperiments().add(new ExperimentData("upcoming_creator_features", true)); + // Needed for certain molang queries used in blocks and items + startGamePacket.getExperiments().add(new ExperimentData("experimental_molang_features", true)); + startGamePacket.setVanillaVersion("*"); startGamePacket.setInventoriesServerAuthoritative(true); startGamePacket.setServerEngine(""); // Do we want to fill this in? diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/SkullCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/SkullCache.java index ab8528c06..d6e376d8f 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/SkullCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/SkullCache.java @@ -31,9 +31,17 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import lombok.Data; import lombok.Getter; import lombok.RequiredArgsConstructor; +import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.block.custom.CustomBlockState; import org.geysermc.geyser.entity.type.player.SkullPlayerEntity; +import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.registry.BlockRegistries; +import org.geysermc.geyser.registry.type.CustomSkull; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.skin.SkinManager; +import java.io.IOException; import java.util.*; public class SkullCache { @@ -71,21 +79,44 @@ public class SkullCache { this.skullRenderDistanceSquared = distance * distance; } - public void putSkull(Vector3i position, UUID uuid, String texturesProperty, int blockState) { + public Skull putSkull(Vector3i position, UUID uuid, String texturesProperty, int blockState) { Skull skull = skulls.computeIfAbsent(position, Skull::new); skull.uuid = uuid; - skull.texturesProperty = texturesProperty; + if (!texturesProperty.equals(skull.texturesProperty)) { + skull.texturesProperty = texturesProperty; + skull.skinHash = null; + try { + SkinManager.GameProfileData gameProfileData = SkinManager.GameProfileData.loadFromJson(texturesProperty); + if (gameProfileData != null && gameProfileData.skinUrl() != null) { + String skinUrl = gameProfileData.skinUrl(); + skull.skinHash = skinUrl.substring(skinUrl.lastIndexOf('/') + 1); + } else { + session.getGeyser().getLogger().debug("Player skull with invalid Skin tag: " + position + " Textures: " + texturesProperty); + } + } catch (IOException e) { + session.getGeyser().getLogger().debug("Player skull with invalid Skin tag: " + position + " Textures: " + texturesProperty); + if (GeyserImpl.getInstance().getConfig().isDebugMode()) { + e.printStackTrace(); + } + } + } skull.blockState = blockState; + skull.blockDefinition = translateCustomSkull(skull.skinHash, blockState); + + if (skull.blockDefinition != null) { + reassignSkullEntity(skull); + return skull; + } if (skull.entity != null) { skull.entity.updateSkull(skull); } else { if (!cullingEnabled) { assignSkullEntity(skull); - return; + return skull; } if (lastPlayerPosition == null) { - return; + return skull; } skull.distanceSquared = position.distanceSquared(lastPlayerPosition.getX(), lastPlayerPosition.getY(), lastPlayerPosition.getZ()); if (skull.distanceSquared < skullRenderDistanceSquared) { @@ -105,24 +136,24 @@ public class SkullCache { } } } + return skull; } public void removeSkull(Vector3i position) { Skull skull = skulls.remove(position); if (skull != null) { - boolean hadEntity = skull.entity != null; - freeSkullEntity(skull); - - if (cullingEnabled) { - inRangeSkulls.remove(skull); - if (hadEntity && inRangeSkulls.size() >= maxVisibleSkulls) { - // Reassign entity to the closest skull without an entity - assignSkullEntity(inRangeSkulls.get(maxVisibleSkulls - 1)); - } - } + reassignSkullEntity(skull); } } + public Skull updateSkull(Vector3i position, int blockState) { + Skull skull = skulls.get(position); + if (skull != null) { + putSkull(position, skull.uuid, skull.texturesProperty, blockState); + } + return skull; + } + public void updateVisibleSkulls() { if (cullingEnabled) { // No need to recheck skull visibility for small movements @@ -133,6 +164,10 @@ public class SkullCache { inRangeSkulls.clear(); for (Skull skull : skulls.values()) { + if (skull.blockDefinition != null) { + continue; + } + skull.distanceSquared = skull.position.distanceSquared(lastPlayerPosition.getX(), lastPlayerPosition.getY(), lastPlayerPosition.getZ()); if (skull.distanceSquared > skullRenderDistanceSquared) { freeSkullEntity(skull); @@ -191,6 +226,19 @@ public class SkullCache { } } + private void reassignSkullEntity(Skull skull) { + boolean hadEntity = skull.entity != null; + freeSkullEntity(skull); + + if (cullingEnabled) { + inRangeSkulls.remove(skull); + if (hadEntity && inRangeSkulls.size() >= maxVisibleSkulls) { + // Reassign entity to the closest skull without an entity + assignSkullEntity(inRangeSkulls.get(maxVisibleSkulls - 1)); + } + } + } + public void clear() { skulls.clear(); inRangeSkulls.clear(); @@ -199,12 +247,33 @@ public class SkullCache { lastPlayerPosition = null; } + private BlockDefinition translateCustomSkull(String skinHash, int blockState) { + CustomSkull customSkull = BlockRegistries.CUSTOM_SKULLS.get(skinHash); + if (customSkull != null) { + byte floorRotation = BlockStateValues.getSkullRotation(blockState); + CustomBlockState customBlockState; + if (floorRotation == -1) { + // Wall skull + int wallDirection = BlockStateValues.getSkullWallDirections().get(blockState); + customBlockState = customSkull.getWallBlockState(wallDirection); + } else { + customBlockState = customSkull.getFloorBlockState(floorRotation); + } + + return session.getBlockMappings().getCustomBlockStateDefinitions().get(customBlockState); + } + return null; + } + @RequiredArgsConstructor @Data public static class Skull { private UUID uuid; private String texturesProperty; + private String skinHash; + private int blockState; + private BlockDefinition blockDefinition; private SkullPlayerEntity entity; private final Vector3i position; diff --git a/core/src/main/java/org/geysermc/geyser/skin/SkinManager.java b/core/src/main/java/org/geysermc/geyser/skin/SkinManager.java index b88bbe23c..79f181636 100644 --- a/core/src/main/java/org/geysermc/geyser/skin/SkinManager.java +++ b/core/src/main/java/org/geysermc/geyser/skin/SkinManager.java @@ -277,7 +277,7 @@ public class SkinManager { return null; } - static GameProfileData loadFromJson(String encodedJson) throws IOException, IllegalArgumentException { + public static GameProfileData loadFromJson(String encodedJson) throws IOException, IllegalArgumentException { JsonNode skinObject = GeyserImpl.JSON_MAPPER.readTree(new String(Base64.getDecoder().decode(encodedJson), StandardCharsets.UTF_8)); JsonNode textures = skinObject.get("textures"); diff --git a/core/src/main/java/org/geysermc/geyser/skin/SkinProvider.java b/core/src/main/java/org/geysermc/geyser/skin/SkinProvider.java index 1037b88ff..41f750990 100644 --- a/core/src/main/java/org/geysermc/geyser/skin/SkinProvider.java +++ b/core/src/main/java/org/geysermc/geyser/skin/SkinProvider.java @@ -460,7 +460,7 @@ public class SkinProvider { private static Skin supplySkin(UUID uuid, String textureUrl) { try { - byte[] skin = requestImage(textureUrl, null); + byte[] skin = requestImageData(textureUrl, null); return new Skin(uuid, textureUrl, skin, System.currentTimeMillis(), false, false); } catch (Exception ignored) {} // just ignore I guess @@ -470,7 +470,7 @@ public class SkinProvider { private static Cape supplyCape(String capeUrl, CapeProvider provider) { byte[] cape = EMPTY_CAPE.capeData(); try { - cape = requestImage(capeUrl, provider); + cape = requestImageData(capeUrl, provider); } catch (Exception ignored) { } // just ignore I guess @@ -527,7 +527,7 @@ public class SkinProvider { } @SuppressWarnings("ResultOfMethodCallIgnored") - private static byte[] requestImage(String imageUrl, CapeProvider provider) throws Exception { + public static BufferedImage requestImage(String imageUrl, CapeProvider provider) throws IOException { BufferedImage image = null; // First see if we have a cached file. We also update the modification stamp so we know when the file was last used @@ -587,6 +587,11 @@ public class SkinProvider { // TODO remove alpha channel } + return image; + } + + private static byte[] requestImageData(String imageUrl, CapeProvider provider) throws Exception { + BufferedImage image = requestImage(imageUrl, provider); byte[] data = bufferedImageToImageData(image); image.flush(); return data; 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 0934f33a7..23961694d 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 @@ -57,30 +57,32 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator { // See BlockInventoryHolder - same concept there except we're also dealing with a specific block state if (session.getLastInteractionPlayerPosition().equals(session.getPlayerEntity().getPosition())) { int javaBlockId = session.getGeyser().getWorldManager().getBlockAt(session, session.getLastInteractionBlockPosition()); - String[] javaBlockString = BlockRegistries.JAVA_BLOCKS.getOrDefault(javaBlockId, BlockMapping.AIR).getJavaIdentifier().split("\\["); - if (javaBlockString.length > 1 && (javaBlockString[0].equals("minecraft:chest") || javaBlockString[0].equals("minecraft:trapped_chest")) - && !javaBlockString[1].contains("type=single")) { - inventory.setHolderPosition(session.getLastInteractionBlockPosition()); - ((Container) inventory).setUsingRealBlock(true, javaBlockString[0]); + if (!BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.get().containsKey(javaBlockId)) { + String[] javaBlockString = BlockRegistries.JAVA_BLOCKS.getOrDefault(javaBlockId, BlockMapping.AIR).getJavaIdentifier().split("\\["); + if (javaBlockString.length > 1 && (javaBlockString[0].equals("minecraft:chest") || javaBlockString[0].equals("minecraft:trapped_chest")) + && !javaBlockString[1].contains("type=single")) { + inventory.setHolderPosition(session.getLastInteractionBlockPosition()); + ((Container) inventory).setUsingRealBlock(true, javaBlockString[0]); - NbtMapBuilder tag = NbtMap.builder() - .putString("id", "Chest") - .putInt("x", session.getLastInteractionBlockPosition().getX()) - .putInt("y", session.getLastInteractionBlockPosition().getY()) - .putInt("z", session.getLastInteractionBlockPosition().getZ()) - .putString("CustomName", inventory.getTitle()) - .putString("id", "Chest"); + NbtMapBuilder tag = NbtMap.builder() + .putString("id", "Chest") + .putInt("x", session.getLastInteractionBlockPosition().getX()) + .putInt("y", session.getLastInteractionBlockPosition().getY()) + .putInt("z", session.getLastInteractionBlockPosition().getZ()) + .putString("CustomName", inventory.getTitle()) + .putString("id", "Chest"); - DoubleChestValue chestValue = BlockStateValues.getDoubleChestValues().get(javaBlockId); - DoubleChestBlockEntityTranslator.translateChestValue(tag, chestValue, - session.getLastInteractionBlockPosition().getX(), session.getLastInteractionBlockPosition().getZ()); + DoubleChestValue chestValue = BlockStateValues.getDoubleChestValues().get(javaBlockId); + DoubleChestBlockEntityTranslator.translateChestValue(tag, chestValue, + session.getLastInteractionBlockPosition().getX(), session.getLastInteractionBlockPosition().getZ()); - BlockEntityDataPacket dataPacket = new BlockEntityDataPacket(); - dataPacket.setData(tag.build()); - dataPacket.setBlockPosition(session.getLastInteractionBlockPosition()); - session.sendUpstreamPacket(dataPacket); + BlockEntityDataPacket dataPacket = new BlockEntityDataPacket(); + dataPacket.setData(tag.build()); + dataPacket.setBlockPosition(session.getLastInteractionBlockPosition()); + session.sendUpstreamPacket(dataPacket); - return true; + return true; + } } } @@ -90,7 +92,7 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator { } Vector3i pairPosition = position.add(Vector3i.UNIT_X); - BlockDefinition definition = session.getBlockMappings().getBedrockBlock(defaultJavaBlockState); + BlockDefinition definition = session.getBlockMappings().getVanillaBedrockBlock(defaultJavaBlockState); UpdateBlockPacket blockPacket = new UpdateBlockPacket(); blockPacket.setDataLayer(0); 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 0f0421be8..336809e8a 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 @@ -28,9 +28,23 @@ package org.geysermc.geyser.translator.inventory.item; import com.github.steveice10.mc.protocol.data.game.Identifier; import com.github.steveice10.mc.protocol.data.game.entity.attribute.ModifierOperation; 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 net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; +import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; +import org.geysermc.geyser.api.block.custom.CustomBlockData; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.nbt.NbtList; @@ -41,12 +55,15 @@ import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.inventory.GeyserItemStack; +import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.registry.BlockRegistries; -import org.geysermc.geyser.registry.Registries; +import org.geysermc.geyser.registry.type.CustomSkull; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.skin.SkinManager; +import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.translator.text.MessageTranslator; @@ -143,9 +160,21 @@ public final class ItemTranslator { ItemData.Builder builder = javaItem.translateToBedrock(itemStack, bedrockItem, session.getItemMappings()); if (bedrockItem.isBlock()) { - builder.blockDefinition(bedrockItem.getBedrockBlockDefinition()); + CustomBlockData customBlockData = BlockRegistries.CUSTOM_BLOCK_ITEM_OVERRIDES.getOrDefault( + bedrockItem.getJavaItem().javaIdentifier(), null); + if (customBlockData != null) { + translateCustomBlock(customBlockData, session, builder); + } else { + builder.blockDefinition(bedrockItem.getBedrockBlockDefinition()); + } } + if (bedrockItem.getJavaItem().equals(Items.PLAYER_HEAD)) { + translatePlayerHead(session, nbt, builder); + } + + translateCustomItem(nbt, builder, bedrockItem); + if (nbt != null) { // Translate the canDestroy and canPlaceOn Java NBT ListTag canDestroy = nbt.get("CanDestroy"); @@ -362,10 +391,24 @@ public final class ItemTranslator { ItemMapping mapping = itemStack.asItem().toBedrockDefinition(itemStack.getNbt(), session.getItemMappings()); + ItemDefinition itemDefinition = mapping.getBedrockDefinition(); + CustomBlockData customBlockData = BlockRegistries.CUSTOM_BLOCK_ITEM_OVERRIDES.getOrDefault( + mapping.getJavaItem().javaIdentifier(), null); + if (customBlockData != null) { + itemDefinition = session.getItemMappings().getCustomBlockItemDefinitions().get(customBlockData); + } + + if (mapping.getJavaItem().equals(Items.PLAYER_HEAD)) { + CustomSkull customSkull = getCustomSkull(session, itemStack.getNbt()); + if (customSkull != null) { + itemDefinition = session.getItemMappings().getCustomBlockItemDefinitions().get(customSkull.getCustomBlockData()); + } + } + ItemDefinition definition = CustomItemTranslator.getCustomItem(itemStack.getNbt(), mapping); if (definition == null) { // No custom item - return mapping.getBedrockDefinition(); + return itemDefinition; } else { return definition; } @@ -553,6 +596,46 @@ public final class ItemTranslator { ItemDefinition definition = CustomItemTranslator.getCustomItem(nbt, mapping); if (definition != null) { builder.definition(definition); + builder.blockDefinition(null); + } + } + + /** + * Translates a custom block override + */ + private static void translateCustomBlock(CustomBlockData customBlockData, GeyserSession session, ItemData.Builder builder) { + ItemDefinition itemDefinition = session.getItemMappings().getCustomBlockItemDefinitions().get(customBlockData); + BlockDefinition blockDefinition = session.getBlockMappings().getCustomBlockStateDefinitions().get(customBlockData.defaultBlockState()); + builder.definition(itemDefinition); + builder.blockDefinition(blockDefinition); + } + + private static CustomSkull getCustomSkull(GeyserSession session, CompoundTag nbt) { + if (nbt != null && nbt.contains("SkullOwner")) { + if (!(nbt.get("SkullOwner") instanceof CompoundTag skullOwner)) { + // It's a username give up d: + return null; + } + SkinManager.GameProfileData data = SkinManager.GameProfileData.from(skullOwner); + if (data == null) { + session.getGeyser().getLogger().debug("Not sure how to handle skull head item display. " + nbt); + return null; + } + + String skinHash = data.skinUrl().substring(data.skinUrl().lastIndexOf('/') + 1); + return BlockRegistries.CUSTOM_SKULLS.get(skinHash); + } + return null; + } + + private static void translatePlayerHead(GeyserSession session, CompoundTag nbt, ItemData.Builder builder) { + CustomSkull customSkull = getCustomSkull(session, nbt); + if (customSkull != null) { + CustomBlockData customBlockData = customSkull.getCustomBlockData(); + ItemDefinition itemDefinition = session.getItemMappings().getCustomBlockItemDefinitions().get(customBlockData); + BlockDefinition blockDefinition = session.getBlockMappings().getCustomBlockStateDefinitions().get(customBlockData.defaultBlockState()); + builder.definition(itemDefinition); + builder.blockDefinition(blockDefinition); } } 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 cab42f3d0..634b7c6f1 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 @@ -42,7 +42,7 @@ import org.geysermc.geyser.level.physics.Axis; import org.geysermc.geyser.level.physics.BoundingBox; import org.geysermc.geyser.level.physics.CollisionManager; import org.geysermc.geyser.level.physics.Direction; -import org.geysermc.geyser.registry.Registries; +import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.PistonCache; import org.geysermc.geyser.translator.collision.BlockCollision; @@ -95,7 +95,7 @@ public class PistonBlockEntity { static { // Create a ~1 x ~0.5 x ~1 bounding box above the honey block - BlockCollision blockCollision = Registries.COLLISIONS.get(BlockStateValues.JAVA_HONEY_BLOCK_ID); + BlockCollision blockCollision = BlockRegistries.COLLISIONS.get(BlockStateValues.JAVA_HONEY_BLOCK_ID); if (blockCollision == null) { throw new RuntimeException("Failed to find honey block collision"); } @@ -485,7 +485,7 @@ public class PistonBlockEntity { pistonCache.displacePlayer(movement.mul(delta)); } else { // Move the player out of collision - BlockCollision blockCollision = Registries.COLLISIONS.get(javaId); + BlockCollision blockCollision = BlockRegistries.COLLISIONS.get(javaId); if (blockCollision != null) { Vector3d extend = movement.mul(Math.min(1 - blockMovement, 0.5)); Direction movementDirection = orientation; diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java index bc624ed4e..ace4d77b8 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java @@ -30,10 +30,14 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.IntArrayTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; +import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; +import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket; +import org.geysermc.geyser.GeyserImpl; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.SkullCache; import org.geysermc.geyser.skin.SkinProvider; import java.nio.charset.StandardCharsets; @@ -41,6 +45,7 @@ import java.util.LinkedHashMap; import java.util.Locale; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; @BlockEntity(type = BlockEntityType.SKULL) public class SkullBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState { @@ -91,21 +96,55 @@ public class SkullBlockEntityTranslator extends BlockEntityTranslator implements return CompletableFuture.completedFuture(texture.getValue()); } - public static void translateSkull(GeyserSession session, CompoundTag tag, int posX, int posY, int posZ, int blockState) { - Vector3i blockPosition = Vector3i.from(posX, posY, posZ); + public static BlockDefinition translateSkull(GeyserSession session, CompoundTag tag, Vector3i blockPosition, int blockState) { CompoundTag owner = tag.get("SkullOwner"); if (owner == null) { session.getSkullCache().removeSkull(blockPosition); - return; + return null; + } + UUID uuid = getUUID(owner); + + CompletableFuture texturesFuture = getTextures(owner, uuid); + if (texturesFuture.isDone()) { + try { + SkullCache.Skull skull = session.getSkullCache().putSkull(blockPosition, uuid, texturesFuture.get(), blockState); + return skull.getBlockDefinition(); + } catch (InterruptedException | ExecutionException e) { + session.getGeyser().getLogger().debug("Failed to acquire textures for custom skull: " + blockPosition + " " + tag); + if (GeyserImpl.getInstance().getConfig().isDebugMode()) { + e.printStackTrace(); + } + } + return null; } - UUID uuid = getUUID(owner); - getTextures(owner, uuid).whenComplete((texturesProperty, throwable) -> { + // SkullOwner contained a username, so we have to wait for it to be retrieved + texturesFuture.whenComplete((texturesProperty, throwable) -> { + if (texturesProperty == null) { + session.getGeyser().getLogger().debug("Custom skull with invalid SkullOwner tag: " + blockPosition + " " + tag); + return; + } if (session.getEventLoop().inEventLoop()) { - session.getSkullCache().putSkull(blockPosition, uuid, texturesProperty, blockState); + putSkull(session, blockPosition, uuid, texturesProperty, blockState); } else { - session.executeInEventLoop(() -> session.getSkullCache().putSkull(blockPosition, uuid, texturesProperty, blockState)); + session.executeInEventLoop(() -> putSkull(session, blockPosition, uuid, texturesProperty, blockState)); } }); + + // We don't have the textures yet, so we can't determine if a custom block was defined for this skull + return null; + } + + private static void putSkull(GeyserSession session, Vector3i blockPosition, UUID uuid, String texturesProperty, int blockState) { + SkullCache.Skull skull = session.getSkullCache().putSkull(blockPosition, uuid, texturesProperty, blockState); + if (skull.getBlockDefinition() != null) { + UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); + updateBlockPacket.setDataLayer(0); + updateBlockPacket.setBlockPosition(blockPosition); + updateBlockPacket.setDefinition(skull.getBlockDefinition()); + updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS); + updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); + session.sendUpstreamPacket(updateBlockPacket); + } } } 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 bf2c8b1cc..a614663ed 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 @@ -39,6 +39,7 @@ import org.cloudburstmc.math.vector.Vector3d; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.LevelEvent; +import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; @@ -66,6 +67,7 @@ import org.geysermc.geyser.item.type.SpawnEggItem; import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.SkullCache; import org.geysermc.geyser.skin.FakeHeadProvider; import org.geysermc.geyser.translator.inventory.InventoryTranslator; import org.geysermc.geyser.translator.inventory.item.ItemTranslator; @@ -181,6 +183,27 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator belowBlockPos = blockPos.add(0, -2, 0); + case 2 -> belowBlockPos = blockPos.add(0, -1, 1); + case 3 -> belowBlockPos = blockPos.add(0, -1, -1); + case 4 -> belowBlockPos = blockPos.add(1, -1, 0); + case 5 -> belowBlockPos = blockPos.add(-1, -1, 0); + } + + if (belowBlockPos != null) { + int belowBlock = session.getGeyser().getWorldManager().getBlockAt(session, belowBlockPos); + BlockDefinition extendedCollisionDefinition = session.getBlockMappings().getExtendedCollisionBoxes().get(belowBlock); + if (extendedCollisionDefinition != null && (System.currentTimeMillis() - session.getLastInteractionTime()) < 200) { + restoreCorrectBlock(session, blockPos, packet); + return; + } + } + } + // Check to make sure the client isn't spamming interaction // Based on Nukkit 1.0, with changes to ensure holding down still works boolean hasAlreadyClicked = System.currentTimeMillis() - session.getLastInteractionTime() < 110.0 && @@ -265,6 +288,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator= (breakTime+=2) * 50) { + // Play break sound and particle + LevelEventPacket effectPacket = new LevelEventPacket(); + effectPacket.setPosition(vectorFloat); + effectPacket.setType(LevelEvent.PARTICLE_DESTROY_BLOCK); + effectPacket.setData(session.getBlockMappings().getBedrockBlockId(breakingBlock)); + session.sendUpstreamPacket(effectPacket); + + // Break the block + ServerboundPlayerActionPacket finishBreakingPacket = new ServerboundPlayerActionPacket(PlayerAction.FINISH_DIGGING, + vector, Direction.VALUES[packet.getFace()], session.getWorldCache().nextPredictionSequence()); + session.sendDownstreamPacket(finishBreakingPacket); + session.setBlockBreakStartTime(0); + break; + } + } + updateBreak.setData((int) (65535 / breakTime)); session.sendUpstreamPacket(updateBreak); break; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java index 1af0ff814..7a14cebcb 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java @@ -110,7 +110,7 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator { ShapelessRecipeData shapelessRecipeData = (ShapelessRecipeData) recipe.getData(); ItemData output = ItemTranslator.translateToBedrock(session, shapelessRecipeData.getResult()); - if (output.equals(ItemData.AIR)) { + if (!output.isValid()) { // Likely modded item that Bedrock will complain about if it persists continue; } @@ -131,7 +131,7 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator { ShapedRecipeData shapedRecipeData = (ShapedRecipeData) recipe.getData(); ItemData output = ItemTranslator.translateToBedrock(session, shapedRecipeData.getResult()); - if (output.equals(ItemData.AIR)) { + if (!output.isValid()) { // Likely modded item that Bedrock will complain about if it persists continue; } @@ -213,7 +213,7 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator { + private static final ThreadLocal EXTENDED_COLLISIONS_STORAGE = ThreadLocal.withInitial(ExtendedCollisionsStorage::new); @Override public void translate(GeyserSession session, ClientboundLevelChunkWithLightPacket packet) { + final boolean useExtendedCollisions = !session.getBlockMappings().getExtendedCollisionBoxes().isEmpty(); + if (session.isSpawned()) { ChunkUtils.updateChunkPosition(session, session.getPlayerEntity().getPosition().toInt()); } @@ -111,19 +118,47 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator> 4)); if (bedrockSectionY < 0 || maxBedrockSectionY < bedrockSectionY) { // Ignore this chunk section since it goes outside the bounds accepted by the Bedrock client + if (useExtendedCollisions) { + EXTENDED_COLLISIONS_STORAGE.get().clear(); + } + extendedCollisionNextSection = false; continue; } // No need to encode an empty section... if (javaSection.isBlockCountEmpty()) { + // Unless we need to send extended collisions + if (useExtendedCollisions) { + if (extendedCollision) { + int blocks = EXTENDED_COLLISIONS_STORAGE.get().bottomLayerCollisions() + 1; + BitArray bedrockData = BitArrayVersion.forBitsCeil(Integer.SIZE - Integer.numberOfLeadingZeros(blocks)).createArray(BlockStorage.SIZE); + BlockStorage layer0 = new BlockStorage(bedrockData, new IntArrayList(blocks)); + + layer0.idFor(session.getBlockMappings().getBedrockAir().getRuntimeId()); + for (int yzx = 0; yzx < BlockStorage.SIZE / 16; yzx++) { + if (EXTENDED_COLLISIONS_STORAGE.get().get(yzx, sectionY) != 0) { + bedrockData.set(indexYZXtoXZY(yzx), layer0.idFor(EXTENDED_COLLISIONS_STORAGE.get().get(yzx, sectionY))); + EXTENDED_COLLISIONS_STORAGE.get().set(yzx, 0, sectionY); + } + } + + BlockStorage[] layers = new BlockStorage[]{ layer0 }; + sections[bedrockSectionY] = new GeyserChunkSection(layers, bedrockSectionY); + } + EXTENDED_COLLISIONS_STORAGE.get().clear(); + extendedCollisionNextSection = false; + } continue; } @@ -143,6 +178,24 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator> 5]; @@ -231,6 +311,64 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator> 5] |= 1 << (xzy & 0x1F); } } + + // V1 palette + IntList layer1Palette = IntList.of( + session.getBlockMappings().getBedrockAir().getRuntimeId(), // Air - see BlockStorage's constructor for more information + session.getBlockMappings().getBedrockWater().getRuntimeId()); + + layers = new BlockStorage[]{ layer0, new BlockStorage(BitArrayVersion.V1.createArray(BlockStorage.SIZE, layer1Data), layer1Palette) }; + } else if (waterloggedPaletteIds.isEmpty() && extendedCollision) { + for (int yzx = 0; yzx < BlockStorage.SIZE; yzx++) { + int paletteId = javaData.get(yzx); + int xzy = indexYZXtoXZY(yzx); + bedrockData.set(xzy, paletteId); + + if (EXTENDED_COLLISIONS_STORAGE.get().get(yzx, sectionY) != 0) { + if (paletteId == airPaletteId) { + bedrockData.set(xzy, layer0.idFor(EXTENDED_COLLISIONS_STORAGE.get().get(yzx, sectionY))); + } + EXTENDED_COLLISIONS_STORAGE.get().set(yzx, 0, sectionY); + continue; + } + BlockDefinition aboveBedrockExtendedCollisionDefinition = session.getBlockMappings() + .getExtendedCollisionBoxes().get(javaPalette.idToState(paletteId)); + if (aboveBedrockExtendedCollisionDefinition != null) { + EXTENDED_COLLISIONS_STORAGE.get().set((yzx + 0x100) & 0xFFF, aboveBedrockExtendedCollisionDefinition.getRuntimeId(), sectionY); + if ((xzy & 0xF) == 15) { + thisExtendedCollisionNextSection = true; + } + } + } + + layers = new BlockStorage[]{ layer0 }; + } else { + int[] layer1Data = new int[BlockStorage.SIZE >> 5]; + for (int yzx = 0; yzx < BlockStorage.SIZE; yzx++) { + int paletteId = javaData.get(yzx); + int xzy = indexYZXtoXZY(yzx); + bedrockData.set(xzy, paletteId); + + if (waterloggedPaletteIds.get(paletteId)) { + layer1Data[xzy >> 5] |= 1 << (xzy & 0x1F); + } + + if (EXTENDED_COLLISIONS_STORAGE.get().get(yzx, sectionY) != 0) { + if (paletteId == airPaletteId) { + bedrockData.set(xzy, layer0.idFor(EXTENDED_COLLISIONS_STORAGE.get().get(yzx, sectionY))); + } + EXTENDED_COLLISIONS_STORAGE.get().set(yzx, 0, sectionY); + continue; + } + BlockDefinition aboveBedrockExtendedCollisionDefinition = session.getBlockMappings().getExtendedCollisionBoxes() + .get(javaPalette.idToState(paletteId)); + if (aboveBedrockExtendedCollisionDefinition != null) { + EXTENDED_COLLISIONS_STORAGE.get().set((yzx + 0x100) & 0xFFF, aboveBedrockExtendedCollisionDefinition.getRuntimeId(), sectionY); + if ((xzy & 0xF) == 15) { + thisExtendedCollisionNextSection = true; + } + } + } // V1 palette IntList layer1Palette = IntList.of( @@ -241,6 +379,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator> 4) - (bedrockDimension.minY() >> 4); + if (0 <= bedrockSectionY && bedrockSectionY < maxBedrockSectionY) { + // Custom skull is in a section accepted by Bedrock + GeyserChunkSection bedrockSection = sections[bedrockSectionY]; + IntList palette = bedrockSection.getBlockStorageArray()[0].getPalette(); + if (palette instanceof IntImmutableList || palette instanceof IntLists.Singleton) { + // TODO there has to be a better way to expand the palette .-. + bedrockSection = bedrockSection.copy(bedrockSectionY); + sections[bedrockSectionY] = bedrockSection; + } + bedrockSection.setFullBlock(x, y & 0xF, z, 0, blockDefinition.getRuntimeId()); + } + } } } @@ -380,4 +533,50 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator Date: Thu, 24 Aug 2023 23:32:25 +0200 Subject: [PATCH 057/344] Don't throw errors when loading chunks with invalid skulls (#4081) * Don't throw errors with invalid skulls * Move IllegalArgumentException check to loadFromJson() method --- .../main/java/org/geysermc/geyser/skin/SkinManager.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/skin/SkinManager.java b/core/src/main/java/org/geysermc/geyser/skin/SkinManager.java index 79f181636..f7d6d7510 100644 --- a/core/src/main/java/org/geysermc/geyser/skin/SkinManager.java +++ b/core/src/main/java/org/geysermc/geyser/skin/SkinManager.java @@ -278,7 +278,14 @@ public class SkinManager { } public static GameProfileData loadFromJson(String encodedJson) throws IOException, IllegalArgumentException { - JsonNode skinObject = GeyserImpl.JSON_MAPPER.readTree(new String(Base64.getDecoder().decode(encodedJson), StandardCharsets.UTF_8)); + JsonNode skinObject; + try { + skinObject = GeyserImpl.JSON_MAPPER.readTree(new String(Base64.getDecoder().decode(encodedJson), StandardCharsets.UTF_8)); + } catch (IllegalArgumentException e) { + GeyserImpl.getInstance().getLogger().debug("Invalid base64 encoded skin entry: " + encodedJson); + return null; + } + JsonNode textures = skinObject.get("textures"); if (textures == null) { From 48ecde0f19ab111cbfed3572f1225f3199ab8fa5 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Sat, 26 Aug 2023 22:51:30 +0100 Subject: [PATCH 058/344] Allow srv resolving to be set per remote server (#4076) * Allow srv resolving to be set per remote server * Remove resolve-srv as a config option --- .../geyser/api/network/RemoteServer.java | 7 +++++++ .../GeyserJacksonConfiguration.java | 5 +++++ .../geysermc/geyser/session/GeyserSession.java | 17 +++++++++-------- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/api/src/main/java/org/geysermc/geyser/api/network/RemoteServer.java b/api/src/main/java/org/geysermc/geyser/api/network/RemoteServer.java index 8ac5d8a03..3e72ccd44 100644 --- a/api/src/main/java/org/geysermc/geyser/api/network/RemoteServer.java +++ b/api/src/main/java/org/geysermc/geyser/api/network/RemoteServer.java @@ -67,4 +67,11 @@ public interface RemoteServer { */ @NonNull AuthType authType(); + + /** + * Gets if we should attempt to resolve the SRV record for this server. + * + * @return if we should attempt to resolve the SRV record for this server + */ + boolean resolveSrv(); } diff --git a/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java b/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java index e096d58fa..64ab09954 100644 --- a/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java +++ b/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java @@ -270,6 +270,11 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration return authType; } + @Override + public boolean resolveSrv() { + return false; + } + @Getter @JsonProperty("allow-password-authentication") private boolean passwordAuthentication = true; diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 7197a4fc4..da91c32b7 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -935,7 +935,15 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { } else { downstream = new TcpClientSession(this.remoteServer.address(), this.remoteServer.port(), this.protocol); this.downstream = new DownstreamSession(downstream); - disableSrvResolving(); + + boolean resolveSrv = false; + try { + resolveSrv = this.remoteServer.resolveSrv(); + } catch (AbstractMethodError | NoSuchMethodError ignored) { + // Ignore if the method doesn't exist + // This will happen with extensions using old APIs + } + this.downstream.getSession().setFlag(BuiltinFlags.ATTEMPT_SRV_RESOLVE, resolveSrv); } if (geyser.getConfig().getRemote().isUseProxyProtocol()) { @@ -1419,13 +1427,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { sendDownstreamPacket(swapHandsPacket); } - /** - * Will be overwritten for GeyserConnect. - */ - protected void disableSrvResolving() { - this.downstream.getSession().setFlag(BuiltinFlags.ATTEMPT_SRV_RESOLVE, false); - } - @Override public String name() { return null; From 00def3b0c6de154d742273357fafccfcb6a84f2e Mon Sep 17 00:00:00 2001 From: chris Date: Sun, 27 Aug 2023 14:48:14 +0200 Subject: [PATCH 059/344] Fix duplicate extension's help command permission registration on Paper (#4079) * Fix duplicate permission registration * Register / help (and aliased ?) commands under the "geyser.command.exthelp.id" permission * Fix: Show correct header for /geyser help vs / help --- .../geyser/platform/spigot/GeyserSpigotPlugin.java | 13 ++++++------- .../geyser/command/GeyserCommandManager.java | 3 ++- .../geyser/command/defaults/HelpCommand.java | 3 ++- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java index 16ee13c82..b932962a0 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java @@ -165,13 +165,6 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { return; } - // Remove this in like a year - if (Bukkit.getPluginManager().getPlugin("floodgate-bukkit") != null) { - geyserLogger.severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.outdated", Constants.FLOODGATE_DOWNLOAD_LOCATION)); - this.getPluginLoader().disablePlugin(this); - return; - } - this.geyserCommandManager = new GeyserSpigotCommandManager(geyser); this.geyserCommandManager.init(); @@ -323,6 +316,12 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { continue; } + // Avoid registering the same permission twice, e.g. for the extension help commands + if (Bukkit.getPluginManager().getPermission(command.permission()) != null) { + GeyserImpl.getInstance().getLogger().debug("Skipping permission " + command.permission() + " as it is already registered"); + continue; + } + Bukkit.getPluginManager().addPermission(new Permission(command.permission(), GeyserLocale.getLocaleStringLog(command.description()), command.isSuggestedOpOnly() ? PermissionDefault.OP : PermissionDefault.TRUE)); diff --git a/core/src/main/java/org/geysermc/geyser/command/GeyserCommandManager.java b/core/src/main/java/org/geysermc/geyser/command/GeyserCommandManager.java index 483e8d4a7..373395ea2 100644 --- a/core/src/main/java/org/geysermc/geyser/command/GeyserCommandManager.java +++ b/core/src/main/java/org/geysermc/geyser/command/GeyserCommandManager.java @@ -107,7 +107,8 @@ public class GeyserCommandManager { // Register help commands for all extensions with commands for (Map.Entry> entry : this.extensionCommands.entrySet()) { - registerExtensionCommand(entry.getKey(), new HelpCommand(this.geyser, "help", "geyser.commands.exthelp.desc", "geyser.command.exthelp", entry.getKey().description().id(), entry.getValue())); + String id = entry.getKey().description().id(); + registerExtensionCommand(entry.getKey(), new HelpCommand(this.geyser, "help", "geyser.commands.exthelp.desc", "geyser.command.exthelp." + id, id, entry.getValue())); } } diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/HelpCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/HelpCommand.java index d4ec7d161..c9671b089 100644 --- a/core/src/main/java/org/geysermc/geyser/command/defaults/HelpCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/HelpCommand.java @@ -63,7 +63,8 @@ public class HelpCommand extends GeyserCommand { public void execute(GeyserSession session, GeyserCommandSource sender, String[] args) { int page = 1; int maxPage = 1; - String header = GeyserLocale.getPlayerLocaleString("geyser.commands.help.header", sender.locale(), page, maxPage); + String translationKey = this.baseCommand.equals("geyser") ? "geyser.commands.help.header" : "geyser.commands.extensions.header"; + String header = GeyserLocale.getPlayerLocaleString(translationKey, sender.locale(), page, maxPage); sender.sendMessage(header); this.commands.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEach(entry -> { From 35a8e1507d78394b5be3f4435e7d26a13f94b78f Mon Sep 17 00:00:00 2001 From: basaigh <53559772+basaigh@users.noreply.github.com> Date: Sun, 27 Aug 2023 22:41:14 +0300 Subject: [PATCH 060/344] Bump MCPL to fix issues (#4086) --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index cbceb3e7e..af106d29e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,7 +13,7 @@ protocol = "3.0.0.Beta1-20230718.000033-102" protocol-connection = "3.0.0.Beta1-20230718.000033-101" raknet = "1.0.0.CR1-20230703.195238-9" mcauthlib = "d9d773e" -mcprotocollib = "1.20-1-20230607.135651-6" # Temporary hack - needs to be updated to release once publishing is fixed +mcprotocollib = "1.20-2-20230827.192136-1" adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" From ec5a20113d0be5cfa5b20253c68bd828e549e6c5 Mon Sep 17 00:00:00 2001 From: chris Date: Tue, 29 Aug 2023 22:23:08 +0200 Subject: [PATCH 061/344] Fixes thrown error when skull skin cache doesnt exist (#4082) --- .../org/geysermc/geyser/pack/SkullResourcePackManager.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/src/main/java/org/geysermc/geyser/pack/SkullResourcePackManager.java b/core/src/main/java/org/geysermc/geyser/pack/SkullResourcePackManager.java index d9f7a6327..f59ae8026 100644 --- a/core/src/main/java/org/geysermc/geyser/pack/SkullResourcePackManager.java +++ b/core/src/main/java/org/geysermc/geyser/pack/SkullResourcePackManager.java @@ -139,6 +139,11 @@ public class SkullResourcePackManager { } public static void cleanSkullSkinCache() { + // No need to clean up if skin cache does not exist + if (!Files.exists(SKULL_SKIN_CACHE_PATH)) { + return; + } + try (Stream stream = Files.list(SKULL_SKIN_CACHE_PATH)) { int removeCount = 0; for (Path path : stream.toList()) { From d4ae42822508025f1a21f843778602011b7d0965 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Tue, 29 Aug 2023 16:58:51 -0400 Subject: [PATCH 062/344] Drop support for 1.19.80 (#4091) * Initial removal of any 1.19.80 logic * Re-add isPre1_20_1 method --- README.md | 2 +- .../geysermc/geyser/network/GameProtocol.java | 7 - .../geyser/network/UpstreamPacketHandler.java | 5 - .../populator/BlockRegistryPopulator.java | 44 - .../populator/ItemRegistryPopulator.java | 20 - .../geyser/session/GeyserSession.java | 5 - .../bedrock/block_palette.1_19_80.nbt | Bin 151078 -> 0 bytes .../bedrock/creative_items.1_19_80.json | 6183 ----------------- .../bedrock/runtime_item_states.1_19_80.json | 5066 -------------- core/src/main/resources/languages | 2 +- 10 files changed, 2 insertions(+), 11332 deletions(-) delete mode 100644 core/src/main/resources/bedrock/block_palette.1_19_80.nbt delete mode 100644 core/src/main/resources/bedrock/creative_items.1_19_80.json delete mode 100644 core/src/main/resources/bedrock/runtime_item_states.1_19_80.json diff --git a/README.md b/README.md index 6c742de63..3f5a9641a 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,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.19.80 - 1.20.10 and Minecraft Java 1.20/1.20.1. +### Currently supporting Minecraft Bedrock 1.20.0 - 1.20.10 and Minecraft Java 1.20/1.20.1. ## 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/GameProtocol.java b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java index d15a33315..3d598673d 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java @@ -60,9 +60,6 @@ public final class GameProtocol { private static final PacketCodec DEFAULT_JAVA_CODEC = MinecraftCodec.CODEC; static { - SUPPORTED_BEDROCK_CODECS.add(Bedrock_v582.CODEC.toBuilder() - .minecraftVersion("1.19.80/1.19.81") - .build()); SUPPORTED_BEDROCK_CODECS.add(Bedrock_v589.CODEC); SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC); } @@ -83,10 +80,6 @@ public final class GameProtocol { /* Bedrock convenience methods to gatekeep features and easily remove the check on version removal */ - public static boolean isPre1_20(GeyserSession session) { - return session.getUpstream().getProtocolVersion() < Bedrock_v589.CODEC.getProtocolVersion(); - } - public static boolean isPre1_20_10(GeyserSession session) { return session.getUpstream().getProtocolVersion() < Bedrock_v594.CODEC.getProtocolVersion(); } diff --git a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java index b7955e218..6b43422e5 100644 --- a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java +++ b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java @@ -231,11 +231,6 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { stackPacket.getExperiments().add(new ExperimentData("data_driven_items", true)); } - if (GameProtocol.isPre1_20(session)) { - stackPacket.getExperiments().add(new ExperimentData("next_major_update", true)); - stackPacket.getExperiments().add(new ExperimentData("sniffer", true)); - } - session.sendUpstreamPacket(stackPacket); break; 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 ce6cec075..d3a72d017 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 @@ -127,51 +127,7 @@ public final class BlockRegistryPopulator { return null; }; - // We are using mappings that directly support 1.20, so this maps it back to 1.19.80 - BiFunction legacyMapper = (bedrockIdentifier, statesBuilder) -> { - if (bedrockIdentifier.endsWith("pumpkin")) { - String direction = statesBuilder.remove("minecraft:cardinal_direction").toString(); - statesBuilder.putInt("direction", switch (direction) { - case "north" -> 2; - case "east" -> 3; - case "west" -> 1; - default -> 0; // south - }); - } else if (bedrockIdentifier.endsWith("carpet") && !bedrockIdentifier.startsWith("minecraft:moss")) { - String color = bedrockIdentifier.replace("minecraft:", "").replace("_carpet", ""); - if (color.equals("light_gray")) { - color = "silver"; - } - statesBuilder.putString("color", color); - return "minecraft:carpet"; - } else if (bedrockIdentifier.equals("minecraft:sniffer_egg")) { - statesBuilder.remove("cracked_state"); - return "minecraft:dragon_egg"; - } else if (bedrockIdentifier.endsWith("coral")) { - statesBuilder.putString("coral_color", "blue"); // all blue - statesBuilder.putBoolean("dead_bit", bedrockIdentifier.startsWith("minecraft:dead")); - return "minecraft:coral"; - } else if (bedrockIdentifier.endsWith("sculk_sensor")) { - int phase = (int) statesBuilder.remove("sculk_sensor_phase"); - statesBuilder.putBoolean("powered_bit", phase != 0); - } else if (bedrockIdentifier.endsWith("pitcher_plant")) { - statesBuilder.putString("double_plant_type", "sunflower"); - return "minecraft:double_plant"; - } else if (bedrockIdentifier.endsWith("pitcher_crop")) { - statesBuilder.remove("growth"); - if (((byte) statesBuilder.remove("upper_block_bit")) == 1){ - statesBuilder.putString("flower_type", "orchid"); - return "minecraft:red_flower"; // top - } - statesBuilder.putBoolean("update_bit", false); - return "minecraft:flower_pot"; // bottom - } - - return null; - }; - ImmutableMap, BiFunction> blockMappers = ImmutableMap., BiFunction>builder() - .put(ObjectIntPair.of("1_19_80", Bedrock_v582.CODEC.getProtocolVersion()), legacyMapper) .put(ObjectIntPair.of("1_20_0", Bedrock_v589.CODEC.getProtocolVersion()), emptyMapper) .put(ObjectIntPair.of("1_20_10", Bedrock_v594.CODEC.getProtocolVersion()), concreteAndShulkerBoxMapper) .build(); 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 f243d358a..db97beda4 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 @@ -87,27 +87,7 @@ public class ItemRegistryPopulator { } public static void populate() { - // Used for the 1.19.80 item palette - Map legacyJavaOnly = new HashMap<>(); - legacyJavaOnly.put(Items.MUSIC_DISC_RELIC, "minecraft:music_disc_wait"); - legacyJavaOnly.put(Items.PITCHER_PLANT, "minecraft:chorus_flower"); - legacyJavaOnly.put(Items.PITCHER_POD, "minecraft:beetroot"); - legacyJavaOnly.put(Items.SNIFFER_EGG, "minecraft:sniffer_spawn_egg"); // the BlockItem of the sniffer egg block - List paletteVersions = new ArrayList<>(2); - paletteVersions.add(new PaletteVersion("1_19_80", Bedrock_v582.CODEC.getProtocolVersion(), legacyJavaOnly, (item, mapping) -> { - // Backward-map 1.20 mappings to 1.19.80 - String id = item.javaIdentifier(); - if (id.endsWith("pottery_sherd")) { - return mapping.withBedrockIdentifier(id.replace("sherd", "shard")); - } else if (id.endsWith("carpet") && !id.startsWith("minecraft:moss")) { - return mapping.withBedrockIdentifier("minecraft:carpet"); - } else if (id.endsWith("coral")) { - return mapping.withBedrockIdentifier("minecraft:coral"); - } - - return mapping; - })); paletteVersions.add(new PaletteVersion("1_20_0", Bedrock_v589.CODEC.getProtocolVersion())); paletteVersions.add(new PaletteVersion("1_20_10", Bedrock_v594.CODEC.getProtocolVersion(), Collections.emptyMap(), (item, mapping) -> { // Forward-map 1.20 mappings to 1.20.10 diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index da91c32b7..9cfc29889 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -1594,11 +1594,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { startGamePacket.setRewindHistorySize(0); startGamePacket.setServerAuthoritativeBlockBreaking(false); - if (GameProtocol.isPre1_20(this)) { - startGamePacket.getExperiments().add(new ExperimentData("next_major_update", true)); - startGamePacket.getExperiments().add(new ExperimentData("sniffer", true)); - } - upstream.sendPacket(startGamePacket); } diff --git a/core/src/main/resources/bedrock/block_palette.1_19_80.nbt b/core/src/main/resources/bedrock/block_palette.1_19_80.nbt deleted file mode 100644 index 04eefe48483efefd53261873608790bc6810d06d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 151078 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�ER{;Rmri0J`u&=z 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

*|y7&{8R?>6?;6jSB@+;cJYMACRSEe?$K-gCM1 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 literal 0 HcmV?d00001 diff --git a/core/src/main/resources/bedrock/creative_items.1_20_30.json b/core/src/main/resources/bedrock/creative_items.1_20_30.json new file mode 100644 index 000000000..cce3f8a50 --- /dev/null +++ b/core/src/main/resources/bedrock/creative_items.1_20_30.json @@ -0,0 +1,5787 @@ +{ + "items": [ + { + "id": "minecraft:planks", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBsYW5rcwQJAG5hbWVfaGFzaA+7EGxL5oikAwoAbmV0d29ya19pZE/NqzcKBgBzdGF0ZXMICQB3b29kX3R5cGUDAG9hawADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:planks", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBsYW5rcwQJAG5hbWVfaGFzaA+7EGxL5oikAwoAbmV0d29ya19pZHl/r2YKBgBzdGF0ZXMICQB3b29kX3R5cGUGAHNwcnVjZQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:planks", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBsYW5rcwQJAG5hbWVfaGFzaA+7EGxL5oikAwoAbmV0d29ya19pZL6SoXYKBgBzdGF0ZXMICQB3b29kX3R5cGUFAGJpcmNoAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:planks", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBsYW5rcwQJAG5hbWVfaGFzaA+7EGxL5oikAwoAbmV0d29ya19pZKYD6L0KBgBzdGF0ZXMICQB3b29kX3R5cGUGAGp1bmdsZQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:planks", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBsYW5rcwQJAG5hbWVfaGFzaA+7EGxL5oikAwoAbmV0d29ya19pZJ0zTHYKBgBzdGF0ZXMICQB3b29kX3R5cGUGAGFjYWNpYQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:planks", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBsYW5rcwQJAG5hbWVfaGFzaA+7EGxL5oikAwoAbmV0d29ya19pZOf6hVkKBgBzdGF0ZXMICQB3b29kX3R5cGUIAGRhcmtfb2FrAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:mangrove_planks", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX3BsYW5rcwQJAG5hbWVfaGFzaPvLtcEA0F8xAwoAbmV0d29ya19pZEvnlCYKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:cherry_planks", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9wbGFua3MECQBuYW1lX2hhc2hNIvVh/lVW7gMKAG5ldHdvcmtfaWQTXpRoCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:bamboo_planks", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19wbGFua3MECQBuYW1lX2hhc2gYnjNz7SCCjgMKAG5ldHdvcmtfaWTi8ySSCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:bamboo_mosaic", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19tb3NhaWMECQBuYW1lX2hhc2izSEgiMKOp/AMKAG5ldHdvcmtfaWQZ/p8xCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:crimson_planks", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fcGxhbmtzBAkAbmFtZV9oYXNoJc5IKqNXJnwDCgBuZXR3b3JrX2lkwtJDdQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:warped_planks", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9wbGFua3MECQBuYW1lX2hhc2g3yGXEWhe6LgMKAG5ldHdvcmtfaWStTABvCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWSE4JosCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCwBjb2JibGVzdG9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWTUvV6XCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEQBtb3NzeV9jb2JibGVzdG9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWT4opb2CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBwBncmFuaXRlCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQAMQTVCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBwBkaW9yaXRlCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQIbDOcCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCABhbmRlc2l0ZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWSZKhusCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCQBzYW5kc3RvbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWSp4zgCCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlDQByZWRfc2FuZHN0b25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRbqVHTCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCwBzdG9uZV9icmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRr0ZT/CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEQBtb3NzeV9zdG9uZV9icmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRnLis3CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBQBicmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQNLzfSCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlDABuZXRoZXJfYnJpY2sIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQ5h0xwCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEAByZWRfbmV0aGVyX2JyaWNrCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWS9J0B2CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCQBlbmRfYnJpY2sIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRPbkJeCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCgBwcmlzbWFyaW5lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:blackstone_wall", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmJsYWNrc3RvbmVfd2FsbAQJAG5hbWVfaGFzaMP8XppUSU1RAwoAbmV0d29ya19pZMbeBBsKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:polished_blackstone_wall", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfd2FsbAQJAG5hbWVfaGFzaP6SwV08YwzAAwoAbmV0d29ya19pZAJLsz8KBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:polished_blackstone_brick_wall", + "block_state_b64": "CgAACAQAbmFtZSgAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfd2FsbAQJAG5hbWVfaGFzaBBIDZbHxiEzAwoAbmV0d29ya19pZEbLV8cKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:cobbled_deepslate_wall", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3dhbGwECQBuYW1lX2hhc2iECY5oKxeT+gMKAG5ldHdvcmtfaWRCnPrFCgYAc3RhdGVzCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:deepslate_tile_wall", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3dhbGwECQBuYW1lX2hhc2jz7N+PeuEXgQMKAG5ldHdvcmtfaWTqw4s4CgYAc3RhdGVzCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:polished_deepslate_wall", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV93YWxsBAkAbmFtZV9oYXNoHxjTdj9pevMDCgBuZXR3b3JrX2lkIvBYYwoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:deepslate_brick_wall", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja193YWxsBAkAbmFtZV9oYXNoEs3EQrjroyEDCgBuZXR3b3JrX2lkwlrCGwoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:mud_brick_wall", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0Om11ZF9icmlja193YWxsBAkAbmFtZV9oYXNov9b98ATpUSwDCgBuZXR3b3JrX2lkH/1WZQoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:oak_fence", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0Om9ha19mZW5jZQQJAG5hbWVfaGFzaGEmid7AaCWRAwoAbmV0d29ya19pZDvPEXcKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:spruce_fence", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnNwcnVjZV9mZW5jZQQJAG5hbWVfaGFzaPQCm+aX1ZQeAwoAbmV0d29ya19pZD1QUEoKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:birch_fence", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmJpcmNoX2ZlbmNlBAkAbmFtZV9oYXNo6CJ2ATpANfgDCgBuZXR3b3JrX2lkmCUV2QoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:jungle_fence", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0Omp1bmdsZV9mZW5jZQQJAG5hbWVfaGFzaOX4cD9uAmsdAwoAbmV0d29ya19pZHz1VxkKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:acacia_fence", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmFjYWNpYV9mZW5jZQQJAG5hbWVfaGFzaGjn+RlKVDH6AwoAbmV0d29ya19pZNVGubwKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:dark_oak_fence", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmRhcmtfb2FrX2ZlbmNlBAkAbmFtZV9oYXNoGPj0gCgM0c0DCgBuZXR3b3JrX2lk2w+gEwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:mangrove_fence", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hbmdyb3ZlX2ZlbmNlBAkAbmFtZV9oYXNowwAd7tPu9bsDCgBuZXR3b3JrX2lkKEcd0goGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:cherry_fence", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmNoZXJyeV9mZW5jZQQJAG5hbWVfaGFzaFmtUfHfTxcxAwoAbmV0d29ya19pZPCBxAIKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:bamboo_fence", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJhbWJvb19mZW5jZQQJAG5hbWVfaGFzaCKRbxfXsfkiAwoAbmV0d29ya19pZJNXKFcKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:nether_brick_fence", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0Om5ldGhlcl9icmlja19mZW5jZQQJAG5hbWVfaGFzaA6030ngawxcAwoAbmV0d29ya19pZLnjLF4KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:crimson_fence", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNyaW1zb25fZmVuY2UECQBuYW1lX2hhc2jhUhKv1HGj9AMKAG5ldHdvcmtfaWR3OH3OCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:warped_fence", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OndhcnBlZF9mZW5jZQQJAG5hbWVfaGFzaJfb3/YuKmOWAwoAbmV0d29ya19pZCpaGC8KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:fence_gate", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmZlbmNlX2dhdGUECQBuYW1lX2hhc2hTxpjEDmRzAwMKAG5ldHdvcmtfaWR+T9kTCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:spruce_fence_gate", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnNwcnVjZV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoanTVB84HRbkDCgBuZXR3b3JrX2lkEnw5egoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:birch_fence_gate", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmJpcmNoX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2jmfPklI8azSwMKAG5ldHdvcmtfaWQL77/BCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:jungle_fence_gate", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0Omp1bmdsZV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNobYVQkfBomIcDCgBuZXR3b3JrX2lkA1zgtgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:acacia_fence_gate", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmFjYWNpYV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoZnrLUx/XSekDCgBuZXR3b3JrX2lkHg/kTgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:dark_oak_fence_gate", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmRhcmtfb2FrX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2j2PTvdJJHcVQMKAG5ldHdvcmtfaWTwjOCeCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:mangrove_fence_gate", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0Om1hbmdyb3ZlX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2i/kOhBKiI/dAMKAG5ldHdvcmtfaWSfweCSCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:cherry_fence_gate", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmNoZXJyeV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoKWLgCk0z+PsDCgBuZXR3b3JrX2lk/9bTZQoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:bamboo_fence_gate", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmJhbWJvb19mZW5jZV9nYXRlBAkAbmFtZV9oYXNopH1JrUgwdIADCgBuZXR3b3JrX2lkzIpPywoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:crimson_fence_gate", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmNyaW1zb25fZmVuY2VfZ2F0ZQQJAG5hbWVfaGFzaHE3Gfd0Z2d2AwoAbmV0d29ya19pZDQzVbEKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQsAaW5fd2FsbF9iaXQAAQgAb3Blbl9iaXQAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:warped_fence_gate", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OndhcnBlZF9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoy0oIBjDIG4kDCgBuZXR3b3JrX2lkkf+/3QoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:normal_stone_stairs", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0Om5vcm1hbF9zdG9uZV9zdGFpcnMECQBuYW1lX2hhc2hAEktZZOkGIwMKAG5ldHdvcmtfaWQeH1ALCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:stone_stairs", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnN0b25lX3N0YWlycwQJAG5hbWVfaGFzaNRjqVC5GRVDAwoAbmV0d29ya19pZDcCv+MKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:mossy_cobblestone_stairs", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0Om1vc3N5X2NvYmJsZXN0b25lX3N0YWlycwQJAG5hbWVfaGFzaMVSTq5z9n1RAwoAbmV0d29ya19pZFIfrhkKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:oak_stairs", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Om9ha19zdGFpcnMECQBuYW1lX2hhc2jk/HFzdXy0FQMKAG5ldHdvcmtfaWQJjyzBCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:spruce_stairs", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9zdGFpcnMECQBuYW1lX2hhc2iznygw7uBPBQMKAG5ldHdvcmtfaWTv+is3CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:birch_stairs", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX3N0YWlycwQJAG5hbWVfaGFzaPfhbL619a3GAwoAbmV0d29ya19pZFyPlHAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:jungle_stairs", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9zdGFpcnMECQBuYW1lX2hhc2jodJsHUbOVxQMKAG5ldHdvcmtfaWR0z5d4CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:acacia_stairs", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9zdGFpcnMECQBuYW1lX2hhc2h3x1NmD43IqQMKAG5ldHdvcmtfaWS7Jwz6CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:dark_oak_stairs", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX3N0YWlycwQJAG5hbWVfaGFzaMfwkbYPbNmAAwoAbmV0d29ya19pZCmBYKAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:mangrove_stairs", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX3N0YWlycwQJAG5hbWVfaGFzaNpUDY+uGMpyAwoAbmV0d29ya19pZChzUAsKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:cherry_stairs", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9zdGFpcnMECQBuYW1lX2hhc2jMtr0v9JY4zwMKAG5ldHdvcmtfaWRQwq31CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:bamboo_stairs", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19zdGFpcnMECQBuYW1lX2hhc2jFOzWL8PalKwMKAG5ldHdvcmtfaWTVPh42CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:bamboo_mosaic_stairs", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmJhbWJvb19tb3NhaWNfc3RhaXJzBAkAbmFtZV9oYXNoNLPiveSHPaoDCgBuZXR3b3JrX2lk44PHjgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:stone_brick_stairs", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnN0b25lX2JyaWNrX3N0YWlycwQJAG5hbWVfaGFzaN6tQViRo5cwAwoAbmV0d29ya19pZDMyMgIKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:mossy_stone_brick_stairs", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0Om1vc3N5X3N0b25lX2JyaWNrX3N0YWlycwQJAG5hbWVfaGFzaIB/Zv5YBPuYAwoAbmV0d29ya19pZANTOsMKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:sandstone_stairs", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnNhbmRzdG9uZV9zdGFpcnMECQBuYW1lX2hhc2hOyA0BoYUOPQMKAG5ldHdvcmtfaWSV/834CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:smooth_sandstone_stairs", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnNtb290aF9zYW5kc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNoB+CuCd8Ruz8DCgBuZXR3b3JrX2lksR+m8QoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:red_sandstone_stairs", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNoPs0LpHPL24YDCgBuZXR3b3JrX2lkLYVt3woGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:smooth_red_sandstone_stairs", + "block_state_b64": "CgAACAQAbmFtZSUAbWluZWNyYWZ0OnNtb290aF9yZWRfc2FuZHN0b25lX3N0YWlycwQJAG5hbWVfaGFzaBvjtQv5pf+MAwoAbmV0d29ya19pZMHNND8KBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:granite_stairs", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmdyYW5pdGVfc3RhaXJzBAkAbmFtZV9oYXNoGzpvtoqKQjgDCgBuZXR3b3JrX2lkPkcB1goGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:polished_granite_stairs", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2dyYW5pdGVfc3RhaXJzBAkAbmFtZV9oYXNo3PvbSfEQklIDCgBuZXR3b3JrX2lkMmEm3AoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:diorite_stairs", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmRpb3JpdGVfc3RhaXJzBAkAbmFtZV9oYXNoi73T8VQuZmcDCgBuZXR3b3JrX2lk6i6nBQoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:polished_diorite_stairs", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2Rpb3JpdGVfc3RhaXJzBAkAbmFtZV9oYXNoFKRJd5Wk5L0DCgBuZXR3b3JrX2lkbt2ioAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:andesite_stairs", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmFuZGVzaXRlX3N0YWlycwQJAG5hbWVfaGFzaO5w2FKBw76EAwoAbmV0d29ya19pZKhXEgUKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:polished_andesite_stairs", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2FuZGVzaXRlX3N0YWlycwQJAG5hbWVfaGFzaNcZZ/zmLInIAwoAbmV0d29ya19pZJTHrlEKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:brick_stairs", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJyaWNrX3N0YWlycwQJAG5hbWVfaGFzaMyt+cRDk5O2AwoAbmV0d29ya19pZNeMh58KBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:nether_brick_stairs", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0Om5ldGhlcl9icmlja19zdGFpcnMECQBuYW1lX2hhc2jRqIoOXgifBAMKAG5ldHdvcmtfaWQDiw5yCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:red_nether_brick_stairs", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnJlZF9uZXRoZXJfYnJpY2tfc3RhaXJzBAkAbmFtZV9oYXNogQvosSbcj7kDCgBuZXR3b3JrX2lkx2IMtAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:end_brick_stairs", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmVuZF9icmlja19zdGFpcnMECQBuYW1lX2hhc2hmlAk+QhsUsQMKAG5ldHdvcmtfaWTN7KFaCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:quartz_stairs", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnF1YXJ0el9zdGFpcnMECQBuYW1lX2hhc2hmvpvOqGi6egMKAG5ldHdvcmtfaWRmUTh7CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:smooth_quartz_stairs", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnNtb290aF9xdWFydHpfc3RhaXJzBAkAbmFtZV9oYXNoNZZ9rX0qZOsDCgBuZXR3b3JrX2lkzsgQyQoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:purpur_stairs", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnB1cl9zdGFpcnMECQBuYW1lX2hhc2ifwDxeezXD7gMKAG5ldHdvcmtfaWTT+rxiCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:prismarine_stairs", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnByaXNtYXJpbmVfc3RhaXJzBAkAbmFtZV9oYXNooTHSZ+IrYtcDCgBuZXR3b3JrX2lkxTJfeAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:dark_prismarine_stairs", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmRhcmtfcHJpc21hcmluZV9zdGFpcnMECQBuYW1lX2hhc2hIciLmam4o4AMKAG5ldHdvcmtfaWTVu7TCCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:prismarine_bricks_stairs", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnByaXNtYXJpbmVfYnJpY2tzX3N0YWlycwQJAG5hbWVfaGFzaNIjq1oBlZMMAwoAbmV0d29ya19pZGEFwLYKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:crimson_stairs", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fc3RhaXJzBAkAbmFtZV9oYXNoZJqIzCBpCq4DCgBuZXR3b3JrX2lktXE00AoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:warped_stairs", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9zdGFpcnMECQBuYW1lX2hhc2hOkY27jLD4RQMKAG5ldHdvcmtfaWQ+E5VrCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:blackstone_stairs", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmJsYWNrc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNokdoUb76p9McDCgBuZXR3b3JrX2lk5fWI5goGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:polished_blackstone_stairs", + "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNolCFtFIE8MmADCgBuZXR3b3JrX2lkGTf7sgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:polished_blackstone_brick_stairs", + "block_state_b64": "CgAACAQAbmFtZSoAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfc3RhaXJzBAkAbmFtZV9oYXNonks6UlfpOmkDCgBuZXR3b3JrX2lkgYeOdAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:cut_copper_stairs", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmN1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoHfoAXYq5G3MDCgBuZXR3b3JrX2lkeetf7woGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:exposed_cut_copper_stairs", + "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcl9zdGFpcnMECQBuYW1lX2hhc2howneQGtZ9cgMKAG5ldHdvcmtfaWSg73zdCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:weathered_cut_copper_stairs", + "block_state_b64": "CgAACAQAbmFtZSUAbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyX3N0YWlycwQJAG5hbWVfaGFzaP+R5loXxrVgAwoAbmV0d29ya19pZOnbRf4KBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:oxidized_cut_copper_stairs", + "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNo6Jeoq5rsPxsDCgBuZXR3b3JrX2lkmRjDnQoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:waxed_cut_copper_stairs", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoh07CQj0/SR8DCgBuZXR3b3JrX2lkmYqoqAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:waxed_exposed_cut_copper_stairs", + "block_state_b64": "CgAACAQAbmFtZSkAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcl9zdGFpcnMECQBuYW1lX2hhc2guVct1ilmxTwMKAG5ldHdvcmtfaWQgCPROCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:waxed_weathered_cut_copper_stairs", + "block_state_b64": "CgAACAQAbmFtZSsAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyX3N0YWlycwQJAG5hbWVfaGFzaPXC8Sz/phCpAwoAbmV0d29ya19pZHlwHVsKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:waxed_oxidized_cut_copper_stairs", + "block_state_b64": "CgAACAQAbmFtZSoAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoaqGdkuhxVZUDCgBuZXR3b3JrX2lkYQXzzgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:cobbled_deepslate_stairs", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3N0YWlycwQJAG5hbWVfaGFzaPIfa+TpyJcIAwoAbmV0d29ya19pZJUvOYIKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:deepslate_tile_stairs", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3N0YWlycwQJAG5hbWVfaGFzaGFRFzB72mN2AwoAbmV0d29ya19pZJEOgIsKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:polished_deepslate_stairs", + "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV9zdGFpcnMECQBuYW1lX2hhc2iNCYxVik9sGAMKAG5ldHdvcmtfaWSRVPnYCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:deepslate_brick_stairs", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja19zdGFpcnMECQBuYW1lX2hhc2hIasOahEf83wMKAG5ldHdvcmtfaWQ1qEDCCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:mud_brick_stairs", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0Om11ZF9icmlja19zdGFpcnMECQBuYW1lX2hhc2gt3qxK1NWajAMKAG5ldHdvcmtfaWSm9N3MCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:wooden_door" + }, + { + "id": "minecraft:spruce_door" + }, + { + "id": "minecraft:birch_door" + }, + { + "id": "minecraft:jungle_door" + }, + { + "id": "minecraft:acacia_door" + }, + { + "id": "minecraft:dark_oak_door" + }, + { + "id": "minecraft:mangrove_door" + }, + { + "id": "minecraft:cherry_door" + }, + { + "id": "minecraft:bamboo_door" + }, + { + "id": "minecraft:iron_door" + }, + { + "id": "minecraft:crimson_door" + }, + { + "id": "minecraft:warped_door" + }, + { + "id": "minecraft:trapdoor", + "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OnRyYXBkb29yBAkAbmFtZV9oYXNotYiAJGtN0xADCgBuZXR3b3JrX2lkyTAWkAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:spruce_trapdoor", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnNwcnVjZV90cmFwZG9vcgQJAG5hbWVfaGFzaOwlfbgBkUW4AwoAbmV0d29ya19pZPHy1K0KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:birch_trapdoor", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmJpcmNoX3RyYXBkb29yBAkAbmFtZV9oYXNoSLtLweOLJ7wDCgBuZXR3b3JrX2lkeJWDfgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:jungle_trapdoor", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Omp1bmdsZV90cmFwZG9vcgQJAG5hbWVfaGFzaDP/TnM9wyCIAwoAbmV0d29ya19pZEy2fJoKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:acacia_trapdoor", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmFjYWNpYV90cmFwZG9vcgQJAG5hbWVfaGFzaMj8xi3vmEKOAwoAbmV0d29ya19pZOHj8E8KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:dark_oak_trapdoor", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmRhcmtfb2FrX3RyYXBkb29yBAkAbmFtZV9oYXNomB2GGJQ2aOMDCgBuZXR3b3JrX2lko5ZHTwoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:mangrove_trapdoor", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0Om1hbmdyb3ZlX3RyYXBkb29yBAkAbmFtZV9oYXNooV3kQsQUUmkDCgBuZXR3b3JrX2lkkF/mxAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:cherry_trapdoor", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmNoZXJyeV90cmFwZG9vcgQJAG5hbWVfaGFzaH/PefpfdHgtAwoAbmV0d29ya19pZOA7eNgKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:bamboo_trapdoor", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmJhbWJvb190cmFwZG9vcgQJAG5hbWVfaGFzaJrEOpsTwtKCAwoAbmV0d29ya19pZLvbPz8KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:iron_trapdoor", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Omlyb25fdHJhcGRvb3IECQBuYW1lX2hhc2gwA+IumsEiGQMKAG5ldHdvcmtfaWTvSVl/CgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAEPAHVwc2lkZV9kb3duX2JpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:crimson_trapdoor", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNyaW1zb25fdHJhcGRvb3IECQBuYW1lX2hhc2jHXufTnwUkYgMKAG5ldHdvcmtfaWQLjMYVCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAEPAHVwc2lkZV9kb3duX2JpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:warped_trapdoor", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OndhcnBlZF90cmFwZG9vcgQJAG5hbWVfaGFzaA20wG/+vkd6AwoAbmV0d29ya19pZHKR/hYKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:iron_bars", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0Omlyb25fYmFycwQJAG5hbWVfaGFzaPuefWSNAe56AwoAbmV0d29ya19pZN2LB5IKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:glass", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmdsYXNzBAkAbmFtZV9oYXNowGJByfWff6gDCgBuZXR3b3JrX2lk0hdLNwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:white_stained_glass", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OndoaXRlX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2iHubqoMbu9fAMKAG5ldHdvcmtfaWRndBrUCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:light_gray_stained_glass", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaKKa+LrRsHQhAwoAbmV0d29ya19pZEv2giYKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:gray_stained_glass", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmdyYXlfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaIETy7Y/HZREAwoAbmV0d29ya19pZDomVrUKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:black_stained_glass", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmJsYWNrX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2iV6BCwpfDMmwMKAG5ldHdvcmtfaWSV7doJCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:brown_stained_glass", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmJyb3duX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2igsEiq5np8JgMKAG5ldHdvcmtfaWRMzE/lCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:red_stained_glass", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnJlZF9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNoCa2J12/lQoIDCgBuZXR3b3JrX2lk283lWAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:orange_stained_glass", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0Om9yYW5nZV9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNozgjAuvzhxGsDCgBuZXR3b3JrX2lkW5CkhQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:yellow_stained_glass", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnllbGxvd19zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNo7EbHMd5WVugDCgBuZXR3b3JrX2lkkdDyXQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:lime_stained_glass", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmxpbWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaBtZA1nZtwcFAwoAbmV0d29ya19pZDxX85UKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:green_stained_glass", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmdyZWVuX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2h91ptDgbehWwMKAG5ldHdvcmtfaWTlDhnECgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:cyan_stained_glass", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmN5YW5fc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaBkIYQ8nQLqbAwoAbmV0d29ya19pZOL1lHsKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:light_blue_stained_glass", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaLt05n1G0fiSAwoAbmV0d29ya19pZNbwulIKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:blue_stained_glass", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmJsdWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaPhLocSfzduRAwoAbmV0d29ya19pZENsjFwKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:purple_stained_glass", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnB1cnBsZV9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNoJk0DhRO0szUDCgBuZXR3b3JrX2lkD98ZxgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:magenta_stained_glass", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0Om1hZ2VudGFfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaFEDeFiJj3zSAwoAbmV0d29ya19pZG+iFRoKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:pink_stained_glass", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnBpbmtfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaDijTX87ywxhAwoAbmV0d29ya19pZKdEricKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:tinted_glass", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnRpbnRlZF9nbGFzcwQJAG5hbWVfaGFzaAFZWSamk6KdAwoAbmV0d29ya19pZGSvWX8KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:glass_pane", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmdsYXNzX3BhbmUECQBuYW1lX2hhc2gRSBHwNMQ4gQMKAG5ldHdvcmtfaWRGwixuCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:white_stained_glass_pane", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OndoaXRlX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaHgxQmgJVtRrAwoAbmV0d29ya19pZBEr/DYKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:light_gray_stained_glass_pane", + "block_state_b64": "CgAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNon0aQw9lNkSEDCgBuZXR3b3JrX2lk9dp5VgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:gray_stained_glass_pane", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmdyYXlfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNors74IIw+2MMDCgBuZXR3b3JrX2lkmrGO5woGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:black_stained_glass_pane", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OmJsYWNrX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaOK/5ZRRd+M1AwoAbmV0d29ya19pZDv++oQKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:brown_stained_glass_pane", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OmJyb3duX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaLHeGJyRFTIWAwoAbmV0d29ya19pZMz9L0wKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:red_stained_glass_pane", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OnJlZF9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2gGr4x6JheAywMKAG5ldHdvcmtfaWQBjCTmCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:orange_stained_glass_pane", + "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0Om9yYW5nZV9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2hbHxPD2gEbEAMKAG5ldHdvcmtfaWSt/7a5CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:yellow_stained_glass_pane", + "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0OnllbGxvd19zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2g9tl4aOCyZBwMKAG5ldHdvcmtfaWTXRAS7CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:lime_stained_glass_pane", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmxpbWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNo3CtUyLwoGegDCgBuZXR3b3JrX2lkYJDnggoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:green_stained_glass_pane", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OmdyZWVuX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaJo6YP7IMy9SAwoAbmV0d29ya19pZHOnixoKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:cyan_stained_glass_pane", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmN5YW5fc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoti97c6QrbLQDCgBuZXR3b3JrX2lkUqFUeQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:light_blue_stained_glass_pane", + "block_state_b64": "CgAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNovDg/gQle104DCgBuZXR3b3JrX2lkFuy4MQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:blue_stained_glass_pane", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmJsdWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoGc57tiexbQMDCgBuZXR3b3JrX2lk1eBLUAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:purple_stained_glass_pane", + "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0OnB1cnBsZV9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2hDJHYdd0FdfQMKAG5ldHdvcmtfaWSNsdK5CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:magenta_stained_glass_pane", + "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0Om1hZ2VudGFfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNo3pcOw5bs5XoDCgBuZXR3b3JrX2lkVbOR7AoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:pink_stained_glass_pane", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnBpbmtfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoWRhSACMWgswDCgBuZXR3b3JrX2lkIR92xwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:ladder", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmxhZGRlcgQJAG5hbWVfaGFzaKBhqheJVOz+AwoAbmV0d29ya19pZCgvzlsKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:scaffolding", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnNjYWZmb2xkaW5nBAkAbmFtZV9oYXNoYrkevrqcljwDCgBuZXR3b3JrX2lkD13mlAoGAHN0YXRlcwMJAHN0YWJpbGl0eQAAAAABDwBzdGFiaWxpdHlfY2hlY2sAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWTkNl0JCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQwAc21vb3RoX3N0b25lAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:stone_block_slab4", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkQJoxlgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNAUAc3RvbmUAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWRHh04KCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQsAY29iYmxlc3RvbmUAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkVRZB+woGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhEAbW9zc3lfY29iYmxlc3RvbmUAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:wooden_slab", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lkBaobgAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20ICQB3b29kX3R5cGUDAG9hawADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:wooden_slab", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lkhz9TeQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20ICQB3b29kX3R5cGUGAHNwcnVjZQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:wooden_slab", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lk3HkwowoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20ICQB3b29kX3R5cGUFAGJpcmNoAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:wooden_slab", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lkDIBqVQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20ICQB3b29kX3R5cGUGAGp1bmdsZQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:wooden_slab", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lkL5hFYAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20ICQB3b29kX3R5cGUGAGFjYWNpYQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:wooden_slab", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lkKRUHSQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20ICQB3b29kX3R5cGUIAGRhcmtfb2FrAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:mangrove_slab", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Om1hbmdyb3ZlX3NsYWIECQBuYW1lX2hhc2jYCcmhJPeNMwMKAG5ldHdvcmtfaWQx6U1yCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:cherry_slab", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNoZXJyeV9zbGFiBAkAbmFtZV9oYXNoTt0MmVn/mqoDCgBuZXR3b3JrX2lk2VVsZQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:bamboo_slab", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmJhbWJvb19zbGFiBAkAbmFtZV9oYXNoo1xuFqINeLYDCgBuZXR3b3JrX2lkVC+0twoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:bamboo_mosaic_slab", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmJhbWJvb19tb3NhaWNfc2xhYgQJAG5hbWVfaGFzaNbVRBZ/ChI3AwoAbmV0d29ya19pZOLZHFMKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWQSiInOCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQsAc3RvbmVfYnJpY2sAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:stone_block_slab4", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkoF89tgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNBEAbW9zc3lfc3RvbmVfYnJpY2sAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWSkoAE4CgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQkAc2FuZHN0b25lAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:stone_block_slab4", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkWfF7pgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNA0AY3V0X3NhbmRzdG9uZQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkbKRChAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAc21vb3RoX3NhbmRzdG9uZQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkBlrvqAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMg0AcmVkX3NhbmRzdG9uZQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:stone_block_slab4", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkRWFXuwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNBEAY3V0X3JlZF9zYW5kc3RvbmUAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkom8neQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxQAc21vb3RoX3JlZF9zYW5kc3RvbmUAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkd1ZaWgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMwcAZ3Jhbml0ZQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkISH4iwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxAAcG9saXNoZWRfZ3Jhbml0ZQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkqxEDMwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMwcAZGlvcml0ZQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkSYs86QoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxAAcG9saXNoZWRfZGlvcml0ZQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkq6BU6goGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMwgAYW5kZXNpdGUAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkTSXY8AoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxEAcG9saXNoZWRfYW5kZXNpdGUAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWQiYHKTCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQUAYnJpY2sAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWTk/0LfCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQwAbmV0aGVyX2JyaWNrAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lk/hXQ7AoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAcmVkX25ldGhlcl9icmljawADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkYJNxrwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMw8AZW5kX3N0b25lX2JyaWNrAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWRlj0/sCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQYAcXVhcnR6AAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:stone_block_slab4", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkMae+2goGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNA0Ac21vb3RoX3F1YXJ0egADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lk+kMHGAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMgYAcHVycHVyAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkKOSOMAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAcHJpc21hcmluZV9yb3VnaAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lk8igLCQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMg8AcHJpc21hcmluZV9kYXJrAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkSFbyEwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAcHJpc21hcmluZV9icmljawADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:crimson_slab", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmNyaW1zb25fc2xhYgQJAG5hbWVfaGFzaKZ+EfP0ZYOZAwoAbmV0d29ya19pZAxRUWAKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:warped_slab", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OndhcnBlZF9zbGFiBAkAbmFtZV9oYXNo/AT0e/Z9W7UDCgBuZXR3b3JrX2lk1yq11AoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:blackstone_slab", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmJsYWNrc3RvbmVfc2xhYgQJAG5hbWVfaGFzaF/DD4ZUlNgtAwoAbmV0d29ya19pZGy1DjwKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:polished_blackstone_slab", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfc2xhYgQJAG5hbWVfaGFzaDYnuUs86EWfAwoAbmV0d29ya19pZJj2bXIKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:polished_blackstone_brick_slab", + "block_state_b64": "CgAACAQAbmFtZSgAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfc2xhYgQJAG5hbWVfaGFzaKySLqvHc4xXAwoAbmV0d29ya19pZOyWX94KBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:cut_copper_slab", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmN1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaDsNpb2qs4iBAwoAbmV0d29ya19pZOTm2nsKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:exposed_cut_copper_slab", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcl9zbGFiBAkAbmFtZV9oYXNoahQ5OwIQb7kDCgBuZXR3b3JrX2lkrUlZLwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:weathered_cut_copper_slab", + "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyX3NsYWIECQBuYW1lX2hhc2hBIuGIOVVXogMKAG5ldHdvcmtfaWQgnaDiCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:oxidized_cut_copper_slab", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaOptj9ycfpaDAwoAbmV0d29ya19pZMzFSRgKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:waxed_cut_copper_slab", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaAlx6DZOCTHzAwoAbmV0d29ya19pZFRBvDAKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:waxed_exposed_cut_copper_slab", + "block_state_b64": "CgAACAQAbmFtZScAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcl9zbGFiBAkAbmFtZV9oYXNo3KqS5OnhtRIDCgBuZXR3b3JrX2lkHTGcTgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:waxed_weathered_cut_copper_slab", + "block_state_b64": "CgAACAQAbmFtZSkAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyX3NsYWIECQBuYW1lX2hhc2gzZ1oX0HCFtwMKAG5ldHdvcmtfaWSgJR+XCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:waxed_oxidized_cut_copper_slab", + "block_state_b64": "CgAACAQAbmFtZSgAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaMjjTnLu1KcqAwoAbmV0d29ya19pZIxsnFYKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:cobbled_deepslate_slab", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3NsYWIECQBuYW1lX2hhc2gwJIVWK1TM2QMKAG5ldHdvcmtfaWTYAoX5CgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:polished_deepslate_slab", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV9zbGFiBAkAbmFtZV9oYXNoC/Adiz8k6RYDCgBuZXR3b3JrX2lkuFYMAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:deepslate_tile_slab", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3NsYWIECQBuYW1lX2hhc2hPydV6emzIXAMKAG5ldHdvcmtfaWQwlbFCCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:deepslate_brick_slab", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja19zbGFiBAkAbmFtZV9oYXNoSv62V7iw10UDCgBuZXR3b3JrX2lkWMoragoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:mud_brick_slab", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0Om11ZF9icmlja19zbGFiBAkAbmFtZV9oYXNoq/tGBQWkv08DCgBuZXR3b3JrX2lkl4nnMwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:brick_block", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmJyaWNrX2Jsb2NrBAkAbmFtZV9oYXNo5Qc2E005S3oDCgBuZXR3b3JrX2lkqeGWRgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:chiseled_nether_bricks", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmNoaXNlbGVkX25ldGhlcl9icmlja3MECQBuYW1lX2hhc2g31SBPTcUK1QMKAG5ldHdvcmtfaWS8TJ+TCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:cracked_nether_bricks", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmNyYWNrZWRfbmV0aGVyX2JyaWNrcwQJAG5hbWVfaGFzaAdC6eKzXT5tAwoAbmV0d29ya19pZIUSejwKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:quartz_bricks", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnF1YXJ0el9icmlja3MECQBuYW1lX2hhc2jSZO590dd8sAMKAG5ldHdvcmtfaWSc5xCLCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:stonebrick", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWQ5kni1CgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQcAZGVmYXVsdAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:stonebrick", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWTDw813CgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQUAbW9zc3kAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:stonebrick", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWSTvQGECgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQcAY3JhY2tlZAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:stonebrick", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWQIM0OwCgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQgAY2hpc2VsZWQAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:end_bricks", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmVuZF9icmlja3MECQBuYW1lX2hhc2hIUFfxNLZaFgMKAG5ldHdvcmtfaWQ/vDihCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:prismarine", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnByaXNtYXJpbmUECQBuYW1lX2hhc2jcnQCHi9CspQMKAG5ldHdvcmtfaWSH021WCgYAc3RhdGVzCBUAcHJpc21hcmluZV9ibG9ja190eXBlBgBicmlja3MAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:polished_blackstone_bricks", + "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tzBAkAbmFtZV9oYXNoIHgsgIdzKXcDCgBuZXR3b3JrX2lkUw9b3woGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:cracked_polished_blackstone_bricks", + "block_state_b64": "CgAACAQAbmFtZSwAbWluZWNyYWZ0OmNyYWNrZWRfcG9saXNoZWRfYmxhY2tzdG9uZV9icmlja3MECQBuYW1lX2hhc2jQIO1GQDk80AMKAG5ldHdvcmtfaWQ3UlRYCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:gilded_blackstone", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmdpbGRlZF9ibGFja3N0b25lBAkAbmFtZV9oYXNoNoWt1ocG0HEDCgBuZXR3b3JrX2lktL8gUwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:chiseled_polished_blackstone", + "block_state_b64": "CgAACAQAbmFtZSYAbWluZWNyYWZ0OmNoaXNlbGVkX3BvbGlzaGVkX2JsYWNrc3RvbmUECQBuYW1lX2hhc2gzFa+kEjCJgAMKAG5ldHdvcmtfaWR2NJX2CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:deepslate_tiles", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlcwQJAG5hbWVfaGFzaGcLLx3NXAFvAwoAbmV0d29ya19pZI/G/xYKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:cracked_deepslate_tiles", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmNyYWNrZWRfZGVlcHNsYXRlX3RpbGVzBAkAbmFtZV9oYXNo9zWgkFuMM1QDCgBuZXR3b3JrX2lkGwY6OgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:deepslate_bricks", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja3MECQBuYW1lX2hhc2gucvFmPdZxigMKAG5ldHdvcmtfaWSH4HDPCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:cracked_deepslate_bricks", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OmNyYWNrZWRfZGVlcHNsYXRlX2JyaWNrcwQJAG5hbWVfaGFzaN40aqhh9WqHAwoAbmV0d29ya19pZO9GPBQKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:chiseled_deepslate", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmNoaXNlbGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaEU7/uRG8HSBAwoAbmV0d29ya19pZEqmI0EKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:cobblestone", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvYmJsZXN0b25lBAkAbmFtZV9oYXNoPoK7mGlSUz4DCgBuZXR3b3JrX2lkLm7RZwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:mossy_cobblestone", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0Om1vc3N5X2NvYmJsZXN0b25lBAkAbmFtZV9oYXNoGJ67FCbkChMDCgBuZXR3b3JrX2lk/pYs1AoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:cobbled_deepslate", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlBAkAbmFtZV9oYXNoLUz9Y/ywmLwDCgBuZXR3b3JrX2lkNwzZ+AoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:smooth_stone", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnNtb290aF9zdG9uZQQJAG5hbWVfaGFzaMwf87/JaTNvAwoAbmV0d29ya19pZLkZICEKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:sandstone", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZB2wApMKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGUHAGRlZmF1bHQAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:sandstone", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZB7E+eQKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGULAGhlaXJvZ2x5cGhzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:sandstone", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZFQnDaEKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGUDAGN1dAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:sandstone", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZPO4A3IKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGUGAHNtb290aAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:red_sandstone", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWRhNYiFCgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlBwBkZWZhdWx0AAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:red_sandstone", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWTqXJr1CgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlCwBoZWlyb2dseXBocwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:red_sandstone", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWTQRGkFCgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlAwBjdXQAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:red_sandstone", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWTvAHWDCgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlBgBzbW9vdGgAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:coal_block", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmNvYWxfYmxvY2sECQBuYW1lX2hhc2jH8QQP3t5PiAMKAG5ldHdvcmtfaWRo+sR+CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:dried_kelp_block", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmRyaWVkX2tlbHBfYmxvY2sECQBuYW1lX2hhc2iRoucexkrl8wMKAG5ldHdvcmtfaWQQCCrvCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:gold_block", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmdvbGRfYmxvY2sECQBuYW1lX2hhc2iYLshvjtXzFwMKAG5ldHdvcmtfaWTDJGBcCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:iron_block", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Omlyb25fYmxvY2sECQBuYW1lX2hhc2jYINmJQbvV/gMKAG5ldHdvcmtfaWRf7AbICgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:copper_block", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmNvcHBlcl9ibG9jawQJAG5hbWVfaGFzaDVxnehsGaZ1AwoAbmV0d29ya19pZIiUodwKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:exposed_copper", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmV4cG9zZWRfY29wcGVyBAkAbmFtZV9oYXNoQH3Fukmu3CEDCgBuZXR3b3JrX2lk72jFIwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:weathered_copper", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OndlYXRoZXJlZF9jb3BwZXIECQBuYW1lX2hhc2hJCQXbvobv+gMKAG5ldHdvcmtfaWQwM0lJCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:oxidized_copper", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om94aWRpemVkX2NvcHBlcgQJAG5hbWVfaGFzaMDtJqR0G5Y7AwoAbmV0d29ya19pZGjN8bUKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:waxed_copper", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OndheGVkX2NvcHBlcgQJAG5hbWVfaGFzaPF+FG6Eh5fsAwoAbmV0d29ya19pZIjtz/0KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:waxed_exposed_copper", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY29wcGVyBAkAbmFtZV9oYXNoig8IOc+SCikDCgBuZXR3b3JrX2lklz8yWQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:waxed_weathered_copper", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jb3BwZXIECQBuYW1lX2hhc2gjtPq8MOdvKgMKAG5ldHdvcmtfaWSQ9Ln9CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:waxed_oxidized_copper", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OndheGVkX294aWRpemVkX2NvcHBlcgQJAG5hbWVfaGFzaMaORhsO+LzjAwoAbmV0d29ya19pZJhGfLEKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:cut_copper", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmN1dF9jb3BwZXIECQBuYW1lX2hhc2hAfN3NGax3eAMKAG5ldHdvcmtfaWTnFBtYCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:exposed_cut_copper", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcgQJAG5hbWVfaGFzaA85G3yv/w6pAwoAbmV0d29ya19pZMQhr0QKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:weathered_cut_copper", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyBAkAbmFtZV9oYXNoVgRV0fBaz88DCgBuZXR3b3JrX2lk/0cYugoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:oxidized_cut_copper", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2iP8WmFWOkriwMKAG5ldHdvcmtfaWQPdce7CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:waxed_cut_copper", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2jumiwOZIqv2AMKAG5ldHdvcmtfaWQvuxx9CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:waxed_exposed_cut_copper", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcgQJAG5hbWVfaGFzaPE/OfK6IoVMAwoAbmV0d29ya19pZHy5HkcKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:waxed_weathered_cut_copper", + "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyBAkAbmFtZV9oYXNoCA1xDp11bnwDCgBuZXR3b3JrX2lkDyEDVQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:waxed_oxidized_cut_copper", + "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2i1pZAsZYHLDAMKAG5ldHdvcmtfaWQ/wSkCCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:emerald_block", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmVtZXJhbGRfYmxvY2sECQBuYW1lX2hhc2hK6QunqJznNAMKAG5ldHdvcmtfaWRk5+otCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:diamond_block", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmRpYW1vbmRfYmxvY2sECQBuYW1lX2hhc2iGKrxuvkytFQMKAG5ldHdvcmtfaWQQeQZXCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:lapis_block", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmxhcGlzX2Jsb2NrBAkAbmFtZV9oYXNoDZ44xdb2zVoDCgBuZXR3b3JrX2lktVy0BAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:raw_iron_block", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnJhd19pcm9uX2Jsb2NrBAkAbmFtZV9oYXNo9XyzNIQXxvwDCgBuZXR3b3JrX2lknms1QAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:raw_copper_block", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnJhd19jb3BwZXJfYmxvY2sECQBuYW1lX2hhc2hw1KG0TNUGgwMKAG5ldHdvcmtfaWS1vGo/CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:raw_gold_block", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnJhd19nb2xkX2Jsb2NrBAkAbmFtZV9oYXNo6YuwuLwfOBwDCgBuZXR3b3JrX2lkLiQ5gQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:quartz_block", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZEupC1AKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQcAZGVmYXVsdAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:quartz_block", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZM97+l0KBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQUAbGluZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:quartz_block", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZCbTfssKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQgAY2hpc2VsZWQICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:quartz_block", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZJss8V0KBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQYAc21vb3RoCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:prismarine", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnByaXNtYXJpbmUECQBuYW1lX2hhc2jcnQCHi9CspQMKAG5ldHdvcmtfaWRFIsoGCgYAc3RhdGVzCBUAcHJpc21hcmluZV9ibG9ja190eXBlBwBkZWZhdWx0AAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:prismarine", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnByaXNtYXJpbmUECQBuYW1lX2hhc2jcnQCHi9CspQMKAG5ldHdvcmtfaWTDNWOvCgYAc3RhdGVzCBUAcHJpc21hcmluZV9ibG9ja190eXBlBABkYXJrAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:slime", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnNsaW1lBAkAbmFtZV9oYXNoHJiEEJx+JlkDCgBuZXR3b3JrX2lkfgfVzAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:honey_block", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmhvbmV5X2Jsb2NrBAkAbmFtZV9oYXNo9zLYSUlelywDCgBuZXR3b3JrX2lko+dyWgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:honeycomb_block", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmhvbmV5Y29tYl9ibG9jawQJAG5hbWVfaGFzaASIPuOCYd1oAwoAbmV0d29ya19pZKys4n4KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:hay_block", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmhheV9ibG9jawQJAG5hbWVfaGFzaIB2VxKxX8EpAwoAbmV0d29ya19pZKuQSloKBgBzdGF0ZXMDCgBkZXByZWNhdGVkAAAAAAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:bone_block", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmJvbmVfYmxvY2sECQBuYW1lX2hhc2i4ZX576W9AWgMKAG5ldHdvcmtfaWTWGacQCgYAc3RhdGVzAwoAZGVwcmVjYXRlZAAAAAAICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:nether_brick", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0Om5ldGhlcl9icmljawQJAG5hbWVfaGFzaMxcRiheU+nXAwoAbmV0d29ya19pZMkmzloKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:red_nether_brick", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnJlZF9uZXRoZXJfYnJpY2sECQBuYW1lX2hhc2j8pRO4LfoECAMKAG5ldHdvcmtfaWRpdF0YCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:netherite_block", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om5ldGhlcml0ZV9ibG9jawQJAG5hbWVfaGFzaMghh6Zib/ZKAwoAbmV0d29ya19pZIz0mq0KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:lodestone", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmxvZGVzdG9uZQQJAG5hbWVfaGFzaJ2gmHOTlXv8AwoAbmV0d29ya19pZEfgB4wKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:white_wool", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OndoaXRlX3dvb2wECQBuYW1lX2hhc2jRWB7vaIEDiQMKAG5ldHdvcmtfaWSO8paQCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:light_gray_wool", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfd29vbAQJAG5hbWVfaGFzaOpdQ1a2v4b3AwoAbmV0d29ya19pZIqZCYEKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:gray_wool", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmdyYXlfd29vbAQJAG5hbWVfaGFzaLsc1Lp1xdIOAwoAbmV0d29ya19pZFUs+HgKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:black_wool", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmJsYWNrX3dvb2wECQBuYW1lX2hhc2hP2HC6o0X4HAMKAG5ldHdvcmtfaWRUbORcCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:brown_wool", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmJyb3duX3dvb2wECQBuYW1lX2hhc2ig5IW89PrREwMKAG5ldHdvcmtfaWRjT9j8CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:red_wool", + "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OnJlZF93b29sBAkAbmFtZV9oYXNoY4TBDq+mFgUDCgBuZXR3b3JrX2lktn9lcAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:orange_wool", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om9yYW5nZV93b29sBAkAbmFtZV9oYXNoFstfrTZfSCgDCgBuZXR3b3JrX2lk+rqywwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:yellow_wool", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnllbGxvd193b29sBAkAbmFtZV9oYXNoTFyus2RHegcDCgBuZXR3b3JrX2lkkKBhXAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:lime_wool", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmxpbWVfd29vbAQJAG5hbWVfaGFzaNVnnzKiMxmeAwoAbmV0d29ya19pZG9b32kKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:green_wool", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmdyZWVuX3dvb2wECQBuYW1lX2hhc2i3mElRYHIcSQMKAG5ldHdvcmtfaWSssprwCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:cyan_wool", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmN5YW5fd29vbAQJAG5hbWVfaGFzaBNDfvHn8dqFAwoAbmV0d29ya19pZK0hAbgKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:light_blue_wool", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfd29vbAQJAG5hbWVfaGFzaLWFAUfyxFPNAwoAbmV0d29ya19pZL2oEugKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:blue_wool", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmJsdWVfd29vbAQJAG5hbWVfaGFzaLjHyxxbTWCLAwoAbmV0d29ya19pZPaLdFQKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:purple_wool", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnB1cnBsZV93b29sBAkAbmFtZV9oYXNojvFtqzjAf/4DCgBuZXR3b3JrX2lklqASNQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:magenta_wool", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0Om1hZ2VudGFfd29vbAQJAG5hbWVfaGFzaGuOHvf+Pd4yAwoAbmV0d29ya19pZI4UoDQKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:pink_wool", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnBpbmtfd29vbAQJAG5hbWVfaGFzaPiVA2pFeoFLAwoAbmV0d29ya19pZOZRO6oKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:white_carpet", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OndoaXRlX2NhcnBldAQJAG5hbWVfaGFzaNeMHTI1fWPXAwoAbmV0d29ya19pZEahDFcKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:light_gray_carpet", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY2FycGV0BAkAbmFtZV9oYXNoHPw6ArBAsP0DCgBuZXR3b3JrX2lkQoAeUAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:gray_carpet", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmdyYXlfY2FycGV0BAkAbmFtZV9oYXNoZVR0OI+1VRADCgBuZXR3b3JrX2lkETF4WwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:black_carpet", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJsYWNrX2NhcnBldAQJAG5hbWVfaGFzaOk7LP9NptyhAwoAbmV0d29ya19pZFjmXtIKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:brown_carpet", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJyb3duX2NhcnBldAQJAG5hbWVfaGFzaNaXFyOsAvIvAwoAbmV0d29ya19pZHPjFuoKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:red_carpet", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9jYXJwZXQECQBuYW1lX2hhc2i9eSKBf6SO3wMKAG5ldHdvcmtfaWQuhI/KCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:orange_carpet", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Om9yYW5nZV9jYXJwZXQECQBuYW1lX2hhc2hIUkO4HlAdygMKAG5ldHdvcmtfaWSyKV9OCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:yellow_carpet", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19jYXJwZXQECQBuYW1lX2hhc2hSDKX3scCamwMKAG5ldHdvcmtfaWT8nq+ECgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:lime_carpet", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmxpbWVfY2FycGV0BAkAbmFtZV9oYXNo+6KFOpzsib4DCgBuZXR3b3JrX2lkT+DS4woGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:green_carpet", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmdyZWVuX2NhcnBldAQJAG5hbWVfaGFzaCHPMP9ltqFJAwoAbmV0d29ya19pZBgwAvAKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:cyan_carpet", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmN5YW5fY2FycGV0BAkAbmFtZV9oYXNobXf62dQBJj8DCgBuZXR3b3JrX2lkKVppLgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:light_blue_carpet", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY2FycGV0BAkAbmFtZV9oYXNo20l4oktdZ3sDCgBuZXR3b3JrX2lkjdeMiwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:blue_carpet", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmJsdWVfY2FycGV0BAkAbmFtZV9oYXNo3p3lsW0eQwsDCgBuZXR3b3JrX2lkAovdPQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:purple_carpet", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnBsZV9jYXJwZXQECQBuYW1lX2hhc2jwIA9pW/qp7QMKAG5ldHdvcmtfaWTqJqhjCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:magenta_carpet", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hZ2VudGFfY2FycGV0BAkAbmFtZV9oYXNoFXT36YNNZhMDCgBuZXR3b3JrX2lk+tqsGAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:pink_carpet", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfY2FycGV0BAkAbmFtZV9oYXNoHll72oqk+OoDCgBuZXR3b3JrX2lkrnBYDwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:white_concrete_powder", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OndoaXRlX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaFUk9iXVjwV8AwoAbmV0d29ya19pZJPZY8AKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:light_gray_concrete_powder", + "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNo7EUk30hmUtYDCgBuZXR3b3JrX2lkh8jVIwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:gray_concrete_powder", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmdyYXlfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoW77af6WihdwDCgBuZXR3b3JrX2lkSsqC1woGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:black_concrete_powder", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmJsYWNrX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaAfWYp0xtgcfAwoAbmV0d29ya19pZMWTC8EKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:brown_concrete_powder", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmJyb3duX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaB74EeiLO46XAwoAbmV0d29ya19pZEDHKqwKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:red_concrete_powder", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OnJlZF9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2gjFut6Z/VH1gMKAG5ldHdvcmtfaWSvcmwYCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:orange_concrete_powder", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0Om9yYW5nZV9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2gADDj2IJiw+gMKAG5ldHdvcmtfaWTHph0FCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:yellow_concrete_powder", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OnllbGxvd19jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2iy6qKNn3ob5wMKAG5ldHdvcmtfaWQZAI39CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:lime_concrete_powder", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmxpbWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNo4dYIPslbXPUDCgBuZXR3b3JrX2lk2O8X0AoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:green_concrete_powder", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmdyZWVuX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaM/c9x2aJh3HAwoAbmV0d29ya19pZA0VfBMKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:cyan_concrete_powder", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmN5YW5fY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNok+xKAe7XXjoDCgBuZXR3b3JrX2lkmkn6uwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:light_blue_concrete_powder", + "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNogScpIQceyAEDCgBuZXR3b3JrX2lkOmVSbgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:blue_concrete_powder", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmJsdWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoFp7mmeL86r0DCgBuZXR3b3JrX2lkS3b3RQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:purple_concrete_powder", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OnB1cnBsZV9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2iYcVU04hoStwMKAG5ldHdvcmtfaWQXimEjCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:magenta_concrete_powder", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0Om1hZ2VudGFfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoy/70q6VPsWgDCgBuZXR3b3JrX2lkf9mxQwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:pink_concrete_powder", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnBpbmtfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoVikSAf8DwV0DCgBuZXR3b3JrX2lku2MivwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:white_concrete", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OndoaXRlX2NvbmNyZXRlBAkAbmFtZV9oYXNo6zAp7lsLlvkDCgBuZXR3b3JrX2lk3MAYQAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:light_gray_concrete", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY29uY3JldGUECQBuYW1lX2hhc2hEtet5wuDIKAMKAG5ldHdvcmtfaWQISs02CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:gray_concrete", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmdyYXlfY29uY3JldGUECQBuYW1lX2hhc2j92INnb0a83AMKAG5ldHdvcmtfaWQj8RHwCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:black_concrete", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmJsYWNrX2NvbmNyZXRlBAkAbmFtZV9oYXNo2X7NDIQmZ70DCgBuZXR3b3JrX2lk2uiVDQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:brown_concrete", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmJyb3duX2NvbmNyZXRlBAkAbmFtZV9oYXNoeka02BwXf6oDCgBuZXR3b3JrX2lkYf+xDQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:red_concrete", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZF9jb25jcmV0ZQQJAG5hbWVfaGFzaPWmNowLGubqAwoAbmV0d29ya19pZKwyx58KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:orange_concrete", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om9yYW5nZV9jb25jcmV0ZQQJAG5hbWVfaGFzaAgE8XmaAi6+AwoAbmV0d29ya19pZMDQNz8KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:yellow_concrete", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnllbGxvd19jb25jcmV0ZQQJAG5hbWVfaGFzaE6ONfJPBd0+AwoAbmV0d29ya19pZMarutwKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:lime_concrete", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmxpbWVfY29uY3JldGUECQBuYW1lX2hhc2gnd8JW6wmJcAMKAG5ldHdvcmtfaWTd47aoCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:green_concrete", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmdyZWVuX2NvbmNyZXRlBAkAbmFtZV9oYXNokbFxRKchQZkDCgBuZXR3b3JrX2lkmhZWUgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:cyan_concrete", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmN5YW5fY29uY3JldGUECQBuYW1lX2hhc2hFRrWJ33qj1wMKAG5ldHdvcmtfaWQbi5b8CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:light_blue_concrete", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY29uY3JldGUECQBuYW1lX2hhc2gHAe0kl0SE4AMKAG5ldHdvcmtfaWRL/GbSCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:blue_concrete", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmJsdWVfY29uY3JldGUECQBuYW1lX2hhc2hiay301nnj1wMKAG5ldHdvcmtfaWRMvFXNCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:purple_concrete", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnB1cnBsZV9jb25jcmV0ZQQJAG5hbWVfaGFzaHBHflsPIwdXAwoAbmV0d29ya19pZCyKA5gKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:magenta_concrete", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0Om1hZ2VudGFfY29uY3JldGUECQBuYW1lX2hhc2gN7LuB/OvdZAMKAG5ldHdvcmtfaWTc6ZOdCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:pink_concrete", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnBpbmtfY29uY3JldGUECQBuYW1lX2hhc2ii2G5F0u3SOAMKAG5ldHdvcmtfaWSszGgrCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:clay", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OmNsYXkECQBuYW1lX2hhc2j/S6sKXRcpzwMKAG5ldHdvcmtfaWRmsb8nCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:hardened_clay", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmhhcmRlbmVkX2NsYXkECQBuYW1lX2hhc2jrnRwCJ0krJAMKAG5ldHdvcmtfaWRBCOrrCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:white_terracotta", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OndoaXRlX3RlcnJhY290dGEECQBuYW1lX2hhc2j3RSdgmnAIewMKAG5ldHdvcmtfaWSimKw+CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:light_gray_terracotta", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmxpZ2h0X2dyYXlfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAz1Ri3wIxomAwoAbmV0d29ya19pZH5qgOcKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:gray_terracotta", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmdyYXlfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAXdSLAaNZ9vAwoAbmV0d29ya19pZM1QDV0KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:black_terracotta", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmJsYWNrX3RlcnJhY290dGEECQBuYW1lX2hhc2jxssdv5vlbpgMKAG5ldHdvcmtfaWRE3Ru/CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:brown_terracotta", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmJyb3duX3RlcnJhY290dGEECQBuYW1lX2hhc2gG4kPenmOF9gMKAG5ldHdvcmtfaWQ/i0iNCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:red_terracotta", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNo7fX56HXFejEDCgBuZXR3b3JrX2lk8tTF8QoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:orange_terracotta", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0Om9yYW5nZV90ZXJyYWNvdHRhBAkAbmFtZV9oYXNo0Hjmql3sruMDCgBuZXR3b3JrX2lklmqmkAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:yellow_terracotta", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnllbGxvd190ZXJyYWNvdHRhBAkAbmFtZV9oYXNoqkyKKrmA3VcDCgBuZXR3b3JrX2lkaM/orAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:lime_terracotta", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmxpbWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaANjADFOF9v7AwoAbmV0d29ya19pZJt0XsgKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:green_terracotta", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmdyZWVuX3RlcnJhY290dGEECQBuYW1lX2hhc2j5Ybq36yYwRQMKAG5ldHdvcmtfaWQ8kGdHCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:cyan_terracotta", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmN5YW5fdGVycmFjb3R0YQQJAG5hbWVfaGFzaN09COzMuHwAAwoAbmV0d29ya19pZIWPCzoKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:light_blue_terracotta", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmxpZ2h0X2JsdWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaOMytez7cOZiAwoAbmV0d29ya19pZFHK1UsKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:blue_terracotta", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmJsdWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaF6inyTK5RpAAwoAbmV0d29ya19pZF5mVZIKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:purple_terracotta", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnB1cnBsZV90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoKF7YG61yTbEDCgBuZXR3b3JrX2lkhtRDlwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:magenta_terracotta", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0Om1hZ2VudGFfdGVycmFjb3R0YQQJAG5hbWVfaGFzaLWvtpAVtztyAwoAbmV0d29ya19pZN5SoakKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:pink_terracotta", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnBpbmtfdGVycmFjb3R0YQQJAG5hbWVfaGFzaJ7mzvyzSQZTAwoAbmV0d29ya19pZDJWe4YKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:white_glazed_terracotta", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OndoaXRlX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoiVzCdoHAJo0DCgBuZXR3b3JrX2lkIlj9AAoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:silver_glazed_terracotta", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnNpbHZlcl9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAVsA0CnhzA4AwoAbmV0d29ya19pZPnxtJEKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:gray_glazed_terracotta", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmdyYXlfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2jvLZt9u/lF/AMKAG5ldHdvcmtfaWQVU8eFCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:black_glazed_terracotta", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmJsYWNrX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoe8I4xAXbO5UDCgBuZXR3b3JrX2lk2Icb9AoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:brown_glazed_terracotta", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmJyb3duX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoSiNZOobbpjoDCgBuZXR3b3JrX2lkJy0jwgoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:red_glazed_terracotta", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnJlZF9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaBdWFGLmCLFVAwoAbmV0d29ya19pZMYBJSEKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:orange_glazed_terracotta", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0Om9yYW5nZV9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaMyJMrnPr7szAwoAbmV0d29ya19pZN6+7TUKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:yellow_glazed_terracotta", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnllbGxvd19nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaN6NaIhf6m0uAwoAbmV0d29ya19pZKRHXeoKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:lime_glazed_terracotta", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmxpbWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2iF3E68/rB2EAMKAG5ldHdvcmtfaWSP7qQWCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:green_glazed_terracotta", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmdyZWVuX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNow5mo8aQDFboDCgBuZXR3b3JrX2lkoF11kgoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:cyan_glazed_terracotta", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmN5YW5fZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2gnNB+cCFRJhwMKAG5ldHdvcmtfaWT9buMtCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:light_blue_glazed_terracotta", + "block_state_b64": "CgAACAQAbmFtZSYAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2gladnCDBKCigMKAG5ldHdvcmtfaWS5CszFCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:blue_glazed_terracotta", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmJsdWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2giOZK+2nB1igMKAG5ldHdvcmtfaWR+e22CCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:purple_glazed_terracotta", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnB1cnBsZV9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaIQU03txeAfHAwoAbmV0d29ya19pZLKbSE4KBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:magenta_glazed_terracotta", + "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0Om1hZ2VudGFfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2i/SNqDJbfjMgMKAG5ldHdvcmtfaWQKf9UvCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:pink_glazed_terracotta", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OnBpbmtfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2hik8DVt4g+twMKAG5ldHdvcmtfaWTKzav2CgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:purpur_block", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnB1cnB1cl9ibG9jawQJAG5hbWVfaGFzaAgLwnUZGlzsAwoAbmV0d29ya19pZLD8ox4KBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQcAZGVmYXVsdAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:purpur_block", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnB1cnB1cl9ibG9jawQJAG5hbWVfaGFzaAgLwnUZGlzsAwoAbmV0d29ya19pZPSAFFsKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQUAbGluZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:packed_mud", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnBhY2tlZF9tdWQECQBuYW1lX2hhc2gHOMa121h4FgMKAG5ldHdvcmtfaWTUb6LyCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:mud_bricks", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Om11ZF9icmlja3MECQBuYW1lX2hhc2iDL/SVl/PewQMKAG5ldHdvcmtfaWSkBjaDCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:nether_wart_block", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0Om5ldGhlcl93YXJ0X2Jsb2NrBAkAbmFtZV9oYXNo9XGS4GNnlV4DCgBuZXR3b3JrX2lkh3apIgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:warped_wart_block", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OndhcnBlZF93YXJ0X2Jsb2NrBAkAbmFtZV9oYXNo9IqDS9yUPJoDCgBuZXR3b3JrX2lkMpKAbAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:shroomlight", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnNocm9vbWxpZ2h0BAkAbmFtZV9oYXNoZHCHcHX/HYADCgBuZXR3b3JrX2lkLG2JiwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:crimson_nylium", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fbnlsaXVtBAkAbmFtZV9oYXNoOr6DJYW2bFYDCgBuZXR3b3JrX2lkuWpRDgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:warped_nylium", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9ueWxpdW0ECQBuYW1lX2hhc2g0Zf89cfr3rwMKAG5ldHdvcmtfaWSu/kekCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:netherrack", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Om5ldGhlcnJhY2sECQBuYW1lX2hhc2i/r5ZyRsvPyQMKAG5ldHdvcmtfaWTAiTOACgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:basalt", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmJhc2FsdAQJAG5hbWVfaGFzaH+UQO2yWodiAwoAbmV0d29ya19pZBPNSV4KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:polished_basalt", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnBvbGlzaGVkX2Jhc2FsdAQJAG5hbWVfaGFzaMS+L0gMnRcBAwoAbmV0d29ya19pZF+/mHwKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:smooth_basalt", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnNtb290aF9iYXNhbHQECQBuYW1lX2hhc2jKPUdz89kuNAMKAG5ldHdvcmtfaWTkb/oVCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:soul_soil", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnNvdWxfc29pbAQJAG5hbWVfaGFzaC1/87ccutuTAwoAbmV0d29ya19pZKc63SMKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:dirt", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OmRpcnQECQBuYW1lX2hhc2hXp6jnXAe+kQMKAG5ldHdvcmtfaWQmkQtoCgYAc3RhdGVzCAkAZGlydF90eXBlBgBub3JtYWwAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:dirt", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OmRpcnQECQBuYW1lX2hhc2hXp6jnXAe+kQMKAG5ldHdvcmtfaWQId9pLCgYAc3RhdGVzCAkAZGlydF90eXBlBgBjb2Fyc2UAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:farmland", + "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OmZhcm1sYW5kBAkAbmFtZV9oYXNoxyQ5ag7LolADCgBuZXR3b3JrX2lkX618FQoGAHN0YXRlcwMSAG1vaXN0dXJpemVkX2Ftb3VudAAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:grass", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmdyYXNzBAkAbmFtZV9oYXNosppASPWFlsUDCgBuZXR3b3JrX2lkhLLQkQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:grass_path", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmdyYXNzX3BhdGgECQBuYW1lX2hhc2i0/KZV8Qsy+gMKAG5ldHdvcmtfaWT7CcdzCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:podzol", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBvZHpvbAQJAG5hbWVfaGFzaBzqokRjH4Z1AwoAbmV0d29ya19pZPPS/GUKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:mycelium", + "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0Om15Y2VsaXVtBAkAbmFtZV9oYXNojTN09cKickIDCgBuZXR3b3JrX2lkLNPxXQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:mud", + "block_state_b64": "CgAACAQAbmFtZQ0AbWluZWNyYWZ0Om11ZAQJAG5hbWVfaGFzaPb/3P+uLy+9AwoAbmV0d29ya19pZPIUlUkKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:stone", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lky8FPmgoGAHN0YXRlcwgKAHN0b25lX3R5cGUFAHN0b25lAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:iron_ore", + "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0Omlyb25fb3JlBAkAbmFtZV9oYXNoS7BYtLnfx3gDCgBuZXR3b3JrX2lk3loneQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:gold_ore", + "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OmdvbGRfb3JlBAkAbmFtZV9oYXNoC5Y+DUGXLC4DCgBuZXR3b3JrX2lkNhvMfwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:diamond_ore", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmRpYW1vbmRfb3JlBAkAbmFtZV9oYXNokUOJ2wZZrGQDCgBuZXR3b3JrX2lk/dChVAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:lapis_ore", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmxhcGlzX29yZQQJAG5hbWVfaGFzaMrmrUrSzb7qAwoAbmV0d29ya19pZMg+qK4KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:redstone_ore", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZHN0b25lX29yZQQJAG5hbWVfaGFzaFHVnp8Wc4JbAwoAbmV0d29ya19pZKDYvQoKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:coal_ore", + "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OmNvYWxfb3JlBAkAbmFtZV9oYXNo1OjA+Iuy51oDCgBuZXR3b3JrX2lk+R/aKAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:copper_ore", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmNvcHBlcl9vcmUECQBuYW1lX2hhc2iSZduSntOzOwMKAG5ldHdvcmtfaWQtIuCnCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:emerald_ore", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmVtZXJhbGRfb3JlBAkAbmFtZV9oYXNoJTovr+VgINsDCgBuZXR3b3JrX2lknbkqCgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:quartz_ore", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnF1YXJ0el9vcmUECQBuYW1lX2hhc2g0yNHLMK9TaQMKAG5ldHdvcmtfaWSzN7nzCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:nether_gold_ore", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om5ldGhlcl9nb2xkX29yZQQJAG5hbWVfaGFzaEJZ7segIBgBAwoAbmV0d29ya19pZNI9pDgKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:ancient_debris", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmFuY2llbnRfZGVicmlzBAkAbmFtZV9oYXNoNrbxMc9AwKcDCgBuZXR3b3JrX2lkrSNjEAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:deepslate_iron_ore", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9pcm9uX29yZQQJAG5hbWVfaGFzaB/fDL9pgvXXAwoAbmV0d29ya19pZFA0bz4KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:deepslate_gold_ore", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9nb2xkX29yZQQJAG5hbWVfaGFzaF9G7WYhKFinAwoAbmV0d29ya19pZHQTfBUKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:deepslate_diamond_ore", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV9kaWFtb25kX29yZQQJAG5hbWVfaGFzaEUH5USh+iD3AwoAbmV0d29ya19pZHP6VzAKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:deepslate_lapis_ore", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV9sYXBpc19vcmUECQBuYW1lX2hhc2j+yFxU/KZs1gMKAG5ldHdvcmtfaWRKINzICgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:deepslate_redstone_ore", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmRlZXBzbGF0ZV9yZWRzdG9uZV9vcmUECQBuYW1lX2hhc2iVgM3wWWD6ugMKAG5ldHdvcmtfaWReBdYRCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:deepslate_emerald_ore", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV9lbWVyYWxkX29yZQQJAG5hbWVfaGFzaNlfo5HTwS6wAwoAbmV0d29ya19pZNeie6sKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:deepslate_coal_ore", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9jb2FsX29yZQQJAG5hbWVfaGFzaIjikmcbRrPPAwoAbmV0d29ya19pZD9TiygKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:deepslate_copper_ore", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9jb3BwZXJfb3JlBAkAbmFtZV9oYXNottjV4Ev5LAQDCgBuZXR3b3JrX2lkP23rgQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:gravel", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmdyYXZlbAQJAG5hbWVfaGFzaOFxz8XJd2r/AwoAbmV0d29ya19pZBpfI1sKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:stone", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lkbtgs0goGAHN0YXRlcwgKAHN0b25lX3R5cGUHAGdyYW5pdGUAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:stone", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lk3sDePAoGAHN0YXRlcwgKAHN0b25lX3R5cGUHAGRpb3JpdGUAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:stone", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lkYG+0YwoGAHN0YXRlcwgKAHN0b25lX3R5cGUIAGFuZGVzaXRlAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:blackstone", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmJsYWNrc3RvbmUECQBuYW1lX2hhc2iMFYziD80D6QMKAG5ldHdvcmtfaWSrUryHCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:deepslate", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmRlZXBzbGF0ZQQJAG5hbWVfaGFzaKX5pAblxz8TAwoAbmV0d29ya19pZOJoQjsKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:stone", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lkREbyhwoGAHN0YXRlcwgKAHN0b25lX3R5cGUOAGdyYW5pdGVfc21vb3RoAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:stone", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lk/EZ3UwoGAHN0YXRlcwgKAHN0b25lX3R5cGUOAGRpb3JpdGVfc21vb3RoAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:stone", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lkmjeVIwoGAHN0YXRlcwgKAHN0b25lX3R5cGUPAGFuZGVzaXRlX3Ntb290aAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:polished_blackstone", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmUECQBuYW1lX2hhc2jT9fHCl6vWQQMKAG5ldHdvcmtfaWR/Ho6oCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:polished_deepslate", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaHC1edoaWF3uAwoAbmV0d29ya19pZCPeQsEKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:sand", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OnNhbmQECQBuYW1lX2hhc2i6lthXXbAyWAMKAG5ldHdvcmtfaWTekU/mCgYAc3RhdGVzCAkAc2FuZF90eXBlBgBub3JtYWwAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:sand", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OnNhbmQECQBuYW1lX2hhc2i6lthXXbAyWAMKAG5ldHdvcmtfaWSTgcqmCgYAc3RhdGVzCAkAc2FuZF90eXBlAwByZWQAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:cactus", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmNhY3R1cwQJAG5hbWVfaGFzaCG9zL0N4wvGAwoAbmV0d29ya19pZDeCERAKBgBzdGF0ZXMDAwBhZ2UAAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:oak_log", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0Om9ha19sb2cECQBuYW1lX2hhc2ho6TS+K7PZFQMKAG5ldHdvcmtfaWQjfjoxCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:stripped_oak_log", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0cmlwcGVkX29ha19sb2cECQBuYW1lX2hhc2h8dqh+OOHU4wMKAG5ldHdvcmtfaWSYKjdrCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:spruce_log", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnNwcnVjZV9sb2cECQBuYW1lX2hhc2hZ03qaLoF3WgMKAG5ldHdvcmtfaWRlFD8eCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:stripped_spruce_log", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX3NwcnVjZV9sb2cECQBuYW1lX2hhc2iNrhKjS5IyrgMKAG5ldHdvcmtfaWRQcEC3CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:birch_log", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmJpcmNoX2xvZwQJAG5hbWVfaGFzaBUzT3NxsZAnAwoAbmV0d29ya19pZBKN3VQKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:stripped_birch_log", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnN0cmlwcGVkX2JpcmNoX2xvZwQJAG5hbWVfaGFzaCFKS4AeuSidAwoAbmV0d29ya19pZN0IONIKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:jungle_log", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Omp1bmdsZV9sb2cECQBuYW1lX2hhc2gkwW0KNulqDgMKAG5ldHdvcmtfaWQaziU/CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:stripped_jungle_log", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2p1bmdsZV9sb2cECQBuYW1lX2hhc2hAwMsgOk02JAMKAG5ldHdvcmtfaWQvls0eCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:acacia_log", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmFjYWNpYV9sb2cECQBuYW1lX2hhc2iV48VpYhjoYQMKAG5ldHdvcmtfaWRxEqe0CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:stripped_acacia_log", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2FjYWNpYV9sb2cECQBuYW1lX2hhc2hJb0lQqnEqlgMKAG5ldHdvcmtfaWRg3IdRCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:dark_oak_log", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRhcmtfb2FrX2xvZwQJAG5hbWVfaGFzaIWfVRd0XUo3AwoAbmV0d29ya19pZPMM7LYKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:stripped_dark_oak_log", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2Rhcmtfb2FrX2xvZwQJAG5hbWVfaGFzaPFTdxRdPwkOAwoAbmV0d29ya19pZDIzenIKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:mangrove_log", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0Om1hbmdyb3ZlX2xvZwQJAG5hbWVfaGFzaHZe6DzPZBobAwoAbmV0d29ya19pZG6DuYkKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:stripped_mangrove_log", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX21hbmdyb3ZlX2xvZwQJAG5hbWVfaGFzaLqIBo4hwA//AwoAbmV0d29ya19pZPtRn7UKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:cherry_log", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmNoZXJyeV9sb2cECQBuYW1lX2hhc2hwFlaioppB1wMKAG5ldHdvcmtfaWS2sdXECgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:stripped_cherry_log", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2NoZXJyeV9sb2cECQBuYW1lX2hhc2i85H6G+WhXaAMKAG5ldHdvcmtfaWRjzoglCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:crimson_stem", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmNyaW1zb25fc3RlbQQJAG5hbWVfaGFzaM0FzfL0UTKZAwoAbmV0d29ya19pZKvzID0KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:stripped_crimson_stem", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2NyaW1zb25fc3RlbQQJAG5hbWVfaGFzaDlA6nood57EAwoAbmV0d29ya19pZHrIqjIKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:warped_stem", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OndhcnBlZF9zdGVtBAkAbmFtZV9oYXNon7cKfPZxdrUDCgBuZXR3b3JrX2lkerWyMwoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:stripped_warped_stem", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX3dhcnBlZF9zdGVtBAkAbmFtZV9oYXNoEw+y0dDPSd8DCgBuZXR3b3JrX2lkIQ9vBAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWSYGFlqCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlAwBvYWsAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWSxnUzvCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlAwBvYWsAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWToyw4RCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlBgBzcHJ1Y2UAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWTL0a3ZCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlBgBzcHJ1Y2UAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWQV99vJCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlBQBiaXJjaAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWQYDJk1CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlBQBiaXJjaAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWSfH48gCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlBgBqdW5nbGUAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWQ44auiCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlBgBqdW5nbGUAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWSogpPYCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlBgBhY2FjaWEAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWSD7hT1CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlBgBhY2FjaWEAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWQagb3gCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlCABkYXJrX29hawADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWQdnWU+CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlCABkYXJrX29hawADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:mangrove_wood", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Om1hbmdyb3ZlX3dvb2QECQBuYW1lX2hhc2iXVxG0JG2fVAMKAG5ldHdvcmtfaWTok1JCCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:stripped_mangrove_wood", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OnN0cmlwcGVkX21hbmdyb3ZlX3dvb2QECQBuYW1lX2hhc2h7CkbaBF7/WAMKAG5ldHdvcmtfaWQLAX88CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:cherry_wood", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNoZXJyeV93b29kBAkAbmFtZV9oYXNoAW8srlmpBM8DCgBuZXR3b3JrX2lkEALMfAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AQwAc3RyaXBwZWRfYml0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:stripped_cherry_wood", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX2NoZXJyeV93b29kBAkAbmFtZV9oYXNo/e7KXv+CB38DCgBuZXR3b3JrX2lkg5aVtQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:crimson_hyphae", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25faHlwaGFlBAkAbmFtZV9oYXNouRmKmfSqEWADCgBuZXR3b3JrX2lk+Tm5rQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:stripped_crimson_hyphae", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnN0cmlwcGVkX2NyaW1zb25faHlwaGFlBAkAbmFtZV9oYXNoFffwmABq4LUDCgBuZXR3b3JrX2lkZAlUbgoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:warped_hyphae", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9oeXBoYWUECQBuYW1lX2hhc2hn8plQUr6pmQMKAG5ldHdvcmtfaWRU2AIBCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:stripped_warped_hyphae", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OnN0cmlwcGVkX3dhcnBlZF9oeXBoYWUECQBuYW1lX2hhc2irKq+HYPSgjQMKAG5ldHdvcmtfaWSbrOPDCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:bamboo_block", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJhbWJvb19ibG9jawQJAG5hbWVfaGFzaAbDeur6stIBAwoAbmV0d29ya19pZCJAwn0KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:stripped_bamboo_block", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2JhbWJvb19ibG9jawQJAG5hbWVfaGFzaJpwytpZOZM9AwoAbmV0d29ya19pZKuRbNEKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:leaves", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmxlYXZlcwQJAG5hbWVfaGFzaACPIsusW0mnAwoAbmV0d29ya19pZOmqtzMKBgBzdGF0ZXMIDQBvbGRfbGVhZl90eXBlAwBvYWsBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:leaves", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmxlYXZlcwQJAG5hbWVfaGFzaACPIsusW0mnAwoAbmV0d29ya19pZFMVNEQKBgBzdGF0ZXMIDQBvbGRfbGVhZl90eXBlBgBzcHJ1Y2UBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:leaves", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmxlYXZlcwQJAG5hbWVfaGFzaACPIsusW0mnAwoAbmV0d29ya19pZKCZEm8KBgBzdGF0ZXMIDQBvbGRfbGVhZl90eXBlBQBiaXJjaAEOAHBlcnNpc3RlbnRfYml0AAEKAHVwZGF0ZV9iaXQAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:leaves", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmxlYXZlcwQJAG5hbWVfaGFzaACPIsusW0mnAwoAbmV0d29ya19pZABprGgKBgBzdGF0ZXMIDQBvbGRfbGVhZl90eXBlBgBqdW5nbGUBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:leaves2", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmxlYXZlczIECQBuYW1lX2hhc2gy/bgrncY1ZAMKAG5ldHdvcmtfaWSFh3olCgYAc3RhdGVzCA0AbmV3X2xlYWZfdHlwZQYAYWNhY2lhAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:leaves2", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmxlYXZlczIECQBuYW1lX2hhc2gy/bgrncY1ZAMKAG5ldHdvcmtfaWTvEAyeCgYAc3RhdGVzCA0AbmV3X2xlYWZfdHlwZQgAZGFya19vYWsBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:mangrove_leaves", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX2xlYXZlcwQJAG5hbWVfaGFzaKyI/dWvhEG8AwoAbmV0d29ya19pZPQxCZ8KBgBzdGF0ZXMBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:cherry_leaves", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9sZWF2ZXMECQBuYW1lX2hhc2giTs9ChhYBlQMKAG5ldHdvcmtfaWR8bPpwCgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:azalea_leaves", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmF6YWxlYV9sZWF2ZXMECQBuYW1lX2hhc2iXFhD57wFS7AMKAG5ldHdvcmtfaWTNB/9ECgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:azalea_leaves_flowered", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmF6YWxlYV9sZWF2ZXNfZmxvd2VyZWQECQBuYW1lX2hhc2gs8jxlS/pMrwMKAG5ldHdvcmtfaWQ7W4PyCgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:sapling", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWQmoOEvCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUDAG9hawADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:sapling", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWQO8pAmCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUGAHNwcnVjZQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:sapling", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWQDHhokCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUFAGJpcmNoAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:sapling", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWTdQrcyCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUGAGp1bmdsZQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:sapling", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWRCDffNCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUGAGFjYWNpYQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:sapling", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWR0BRzPCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUIAGRhcmtfb2FrAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:mangrove_propagule", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0Om1hbmdyb3ZlX3Byb3BhZ3VsZQQJAG5hbWVfaGFzaJGeox6hkfLFAwoAbmV0d29ya19pZAIpvpYKBgBzdGF0ZXMBBwBoYW5naW5nAAMPAHByb3BhZ3VsZV9zdGFnZQAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:cherry_sapling", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNoZXJyeV9zYXBsaW5nBAkAbmFtZV9oYXNoGrPpNMf1LtcDCgBuZXR3b3JrX2lkypakXQoGAHN0YXRlcwEHAGFnZV9iaXQAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:bee_nest", + "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OmJlZV9uZXN0BAkAbmFtZV9oYXNo2R2WBxUHEZIDCgBuZXR3b3JrX2lkiXWLEAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAADCwBob25leV9sZXZlbAAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:wheat_seeds" + }, + { + "id": "minecraft:pumpkin_seeds" + }, + { + "id": "minecraft:melon_seeds" + }, + { + "id": "minecraft:beetroot_seeds" + }, + { + "id": "minecraft:torchflower_seeds" + }, + { + "id": "minecraft:pitcher_pod" + }, + { + "id": "minecraft:wheat" + }, + { + "id": "minecraft:beetroot" + }, + { + "id": "minecraft:potato" + }, + { + "id": "minecraft:poisonous_potato" + }, + { + "id": "minecraft:carrot" + }, + { + "id": "minecraft:golden_carrot" + }, + { + "id": "minecraft:apple" + }, + { + "id": "minecraft:golden_apple" + }, + { + "id": "minecraft:enchanted_golden_apple" + }, + { + "id": "minecraft:melon_block", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1lbG9uX2Jsb2NrBAkAbmFtZV9oYXNoXxSm0iYpAx8DCgBuZXR3b3JrX2lkC9rqygoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:melon_slice" + }, + { + "id": "minecraft:glistering_melon_slice" + }, + { + "id": "minecraft:sweet_berries" + }, + { + "id": "minecraft:glow_berries" + }, + { + "id": "minecraft:pumpkin", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnB1bXBraW4ECQBuYW1lX2hhc2gc8A3jaSzWbgMKAG5ldHdvcmtfaWRFGA+xCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:carved_pumpkin", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNhcnZlZF9wdW1wa2luBAkAbmFtZV9oYXNoPu1T0MJuG90DCgBuZXR3b3JrX2lkXNNn5QoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:lit_pumpkin", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmxpdF9wdW1wa2luBAkAbmFtZV9oYXNo7gWtEm2uPL0DCgBuZXR3b3JrX2lki8sU4AoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:honeycomb" + }, + { + "id": "minecraft:tallgrass", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnRhbGxncmFzcwQJAG5hbWVfaGFzaC3PXpAXXYswAwoAbmV0d29ya19pZOh33DMKBgBzdGF0ZXMIDwB0YWxsX2dyYXNzX3R5cGUEAGZlcm4AAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:double_plant", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZMx1sfgKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQQAZmVybgEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:tallgrass", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnRhbGxncmFzcwQJAG5hbWVfaGFzaC3PXpAXXYswAwoAbmV0d29ya19pZErptfIKBgBzdGF0ZXMIDwB0YWxsX2dyYXNzX3R5cGUEAHRhbGwAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:double_plant", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZAbadmIKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQUAZ3Jhc3MBDwB1cHBlcl9ibG9ja19iaXQAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:nether_sprouts" + }, + { + "id": "minecraft:fire_coral", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmZpcmVfY29yYWwECQBuYW1lX2hhc2hOHyyECVQVJwMKAG5ldHdvcmtfaWS9vF0UCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:brain_coral", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmJyYWluX2NvcmFsBAkAbmFtZV9oYXNoRiWlLCwA2ycDCgBuZXR3b3JrX2lkrjAuhgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:bubble_coral", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJ1YmJsZV9jb3JhbAQJAG5hbWVfaGFzaJz6rWnl+v2qAwoAbmV0d29ya19pZImIWy0KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:tube_coral", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnR1YmVfY29yYWwECQBuYW1lX2hhc2iYa8oO/tgk7wMKAG5ldHdvcmtfaWRTfND5CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:horn_coral", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Omhvcm5fY29yYWwECQBuYW1lX2hhc2iZnRHjZbnLPgMKAG5ldHdvcmtfaWR+GGp8CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:dead_fire_coral", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfZmlyZV9jb3JhbAQJAG5hbWVfaGFzaEPU6tFy/latAwoAbmV0d29ya19pZNMa7V4KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:dead_brain_coral", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmRlYWRfYnJhaW5fY29yYWwECQBuYW1lX2hhc2j5L6QJCISvzwMKAG5ldHdvcmtfaWQkKzeiCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:dead_bubble_coral", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmRlYWRfYnViYmxlX2NvcmFsBAkAbmFtZV9oYXNoSTOZ/8wpeNYDCgBuZXR3b3JrX2lka6w9DAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:dead_tube_coral", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfdHViZV9jb3JhbAQJAG5hbWVfaGFzaJGjNWhlaIJeAwoAbmV0d29ya19pZO3Z0ygKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:dead_horn_coral", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfaG9ybl9jb3JhbAQJAG5hbWVfaGFzaJBkz3qt+g2cAwoAbmV0d29ya19pZBAN+eYKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:coral_fan", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZOg7iS4KBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgMAcmVkAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:coral_fan", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZIDj8HMKBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgQAcGluawMTAGNvcmFsX2Zhbl9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:coral_fan", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZLCJP0kKBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgYAcHVycGxlAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:coral_fan", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZFz2ly4KBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgQAYmx1ZQMTAGNvcmFsX2Zhbl9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:coral_fan", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZE4TgnYKBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgYAeWVsbG93AxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:coral_fan_dead", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkdhLQzwoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yAwByZWQDEwBjb3JhbF9mYW5fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:coral_fan_dead", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkSi6srQoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABwaW5rAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:coral_fan_dead", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkGiGSzAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgBwdXJwbGUDEwBjb3JhbF9mYW5fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:coral_fan_dead", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkmvZKOgoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABibHVlAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:coral_fan_dead", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lknLw+4QoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgB5ZWxsb3cDEwBjb3JhbF9mYW5fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:crimson_roots", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNyaW1zb25fcm9vdHMECQBuYW1lX2hhc2j1fWgQLViv5QMKAG5ldHdvcmtfaWRLh5DXCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:warped_roots", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OndhcnBlZF9yb290cwQJAG5hbWVfaGFzaBc3WvbJOLlkAwoAbmV0d29ya19pZNLgDnAKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:yellow_flower", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19mbG93ZXIECQBuYW1lX2hhc2jWbU1pF0OUGAMKAG5ldHdvcmtfaWQgO3hpCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWSqsqQGCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUFAHBvcHB5AAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWTqDajjCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUGAG9yY2hpZAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWT5CjveCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUGAGFsbGl1bQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWTORIBJCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUJAGhvdXN0b25pYQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWTuNhmYCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUJAHR1bGlwX3JlZAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWT0O4nfCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUMAHR1bGlwX29yYW5nZQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWTqkthyCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGULAHR1bGlwX3doaXRlAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWRMbBA7CgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUKAHR1bGlwX3BpbmsAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWRexMAuCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUFAG94ZXllAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWQgs7BECgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUKAGNvcm5mbG93ZXIAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWRvDuNbCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUSAGxpbHlfb2ZfdGhlX3ZhbGxleQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:double_plant", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZOemRt4KBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQkAc3VuZmxvd2VyAQ8AdXBwZXJfYmxvY2tfYml0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:double_plant", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZOFugoEKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQcAc3lyaW5nYQEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:double_plant", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZN4O+/gKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQQAcm9zZQEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:double_plant", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZI3w4GMKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQcAcGFlb25pYQEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:pitcher_plant", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnBpdGNoZXJfcGxhbnQECQBuYW1lX2hhc2hRJHzsbDH+SQMKAG5ldHdvcmtfaWRnY76VCgYAc3RhdGVzAQ8AdXBwZXJfYmxvY2tfYml0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:pink_petals", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfcGV0YWxzBAkAbmFtZV9oYXNo6DQwN9SwV3QDCgBuZXR3b3JrX2lkNWneGgoGAHN0YXRlcwMGAGdyb3d0aAAAAAAIHABtaW5lY3JhZnQ6Y2FyZGluYWxfZGlyZWN0aW9uBQBzb3V0aAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:wither_rose", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OndpdGhlcl9yb3NlBAkAbmFtZV9oYXNoaSKxl3I516gDCgBuZXR3b3JrX2lkATXLPwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:torchflower", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnRvcmNoZmxvd2VyBAkAbmFtZV9oYXNoL+mHtElwbqQDCgBuZXR3b3JrX2lkI34O+AoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:white_dye" + }, + { + "id": "minecraft:light_gray_dye" + }, + { + "id": "minecraft:gray_dye" + }, + { + "id": "minecraft:black_dye" + }, + { + "id": "minecraft:brown_dye" + }, + { + "id": "minecraft:red_dye" + }, + { + "id": "minecraft:orange_dye" + }, + { + "id": "minecraft:yellow_dye" + }, + { + "id": "minecraft:lime_dye" + }, + { + "id": "minecraft:green_dye" + }, + { + "id": "minecraft:cyan_dye" + }, + { + "id": "minecraft:light_blue_dye" + }, + { + "id": "minecraft:blue_dye" + }, + { + "id": "minecraft:purple_dye" + }, + { + "id": "minecraft:magenta_dye" + }, + { + "id": "minecraft:pink_dye" + }, + { + "id": "minecraft:ink_sac" + }, + { + "id": "minecraft:glow_ink_sac" + }, + { + "id": "minecraft:cocoa_beans" + }, + { + "id": "minecraft:lapis_lazuli" + }, + { + "id": "minecraft:bone_meal" + }, + { + "id": "minecraft:vine", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OnZpbmUECQBuYW1lX2hhc2j0Sj8/XeXOLAMKAG5ldHdvcmtfaWSUkDtbCgYAc3RhdGVzAxMAdmluZV9kaXJlY3Rpb25fYml0cwAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:weeping_vines", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndlZXBpbmdfdmluZXMECQBuYW1lX2hhc2jrLgLHkQygiwMKAG5ldHdvcmtfaWQ8NHSJCgYAc3RhdGVzAxEAd2VlcGluZ192aW5lc19hZ2UAAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:twisting_vines", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnR3aXN0aW5nX3ZpbmVzBAkAbmFtZV9oYXNoDYR5QgVUQJADCgBuZXR3b3JrX2lk5kYVIQoGAHN0YXRlcwMSAHR3aXN0aW5nX3ZpbmVzX2FnZQAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:waterlily", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OndhdGVybGlseQQJAG5hbWVfaGFzaEHgC4c1SXg0AwoAbmV0d29ya19pZOOerp8KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:seagrass", + "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OnNlYWdyYXNzBAkAbmFtZV9oYXNoHSBFtoHdWxIDCgBuZXR3b3JrX2lkd3lhEAoGAHN0YXRlcwgOAHNlYV9ncmFzc190eXBlBwBkZWZhdWx0AAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:kelp" + }, + { + "id": "minecraft:deadbush", + "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OmRlYWRidXNoBAkAbmFtZV9oYXNoPFODe4IScnYDCgBuZXR3b3JrX2lkVfnl+goGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:bamboo", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmJhbWJvbwQJAG5hbWVfaGFzaBgpGmyzhedCAwoAbmV0d29ya19pZIZv1nYKBgBzdGF0ZXMBBwBhZ2VfYml0AAgQAGJhbWJvb19sZWFmX3NpemUJAG5vX2xlYXZlcwgWAGJhbWJvb19zdGFsa190aGlja25lc3MEAHRoaW4AAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:snow", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OnNub3cECQBuYW1lX2hhc2gVHr5XXdETWAMKAG5ldHdvcmtfaWQ0zCeHCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:ice", + "block_state_b64": "CgAACAQAbmFtZQ0AbWluZWNyYWZ0OmljZQQJAG5hbWVfaGFzaNF26f+uUT29AwoAbmV0d29ya19pZOUMaQYKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:packed_ice", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnBhY2tlZF9pY2UECQBuYW1lX2hhc2hk4bu123ZrFgMKAG5ldHdvcmtfaWTr/ooaCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:blue_ice", + "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OmJsdWVfaWNlBAkAbmFtZV9oYXNo+EKxYgFhKcgDCgBuZXR3b3JrX2lkxfsA8goGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:snow_layer", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnNub3dfbGF5ZXIECQBuYW1lX2hhc2hXka6atMYUCQMKAG5ldHdvcmtfaWRCrIPcCgYAc3RhdGVzAQsAY292ZXJlZF9iaXQAAwYAaGVpZ2h0AAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:pointed_dripstone", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnBvaW50ZWRfZHJpcHN0b25lBAkAbmFtZV9oYXNoJMISzmHQgt8DCgBuZXR3b3JrX2lkbWrtYgoGAHN0YXRlcwgTAGRyaXBzdG9uZV90aGlja25lc3MDAHRpcAEHAGhhbmdpbmcBAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:dripstone_block", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRyaXBzdG9uZV9ibG9jawQJAG5hbWVfaGFzaIIXnEqY77YsAwoAbmV0d29ya19pZMZi2kwKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:moss_carpet", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vc3NfY2FycGV0BAkAbmFtZV9oYXNo/NEDxRPTshYDCgBuZXR3b3JrX2lkaGG3QwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:moss_block", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Om1vc3NfYmxvY2sECQBuYW1lX2hhc2iovcsPUYX2tgMKAG5ldHdvcmtfaWT3JSbfCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:dirt_with_roots", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRpcnRfd2l0aF9yb290cwQJAG5hbWVfaGFzaLCNDYPviDCIAwoAbmV0d29ya19pZNCkwzoKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:hanging_roots", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Omhhbmdpbmdfcm9vdHMECQBuYW1lX2hhc2jaXn+Y5UZpDAMKAG5ldHdvcmtfaWRU4c2vCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:mangrove_roots", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hbmdyb3ZlX3Jvb3RzBAkAbmFtZV9oYXNoa786PzQGZ6kDCgBuZXR3b3JrX2lklA0AHgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:muddy_mangrove_roots", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0Om11ZGR5X21hbmdyb3ZlX3Jvb3RzBAkAbmFtZV9oYXNo9YApdHpo1RkDCgBuZXR3b3JrX2lkH0Oc4woGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:big_dripleaf", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJpZ19kcmlwbGVhZgQJAG5hbWVfaGFzaGBEhXjo6qSdAwoAbmV0d29ya19pZMETsb8KBgBzdGF0ZXMBEQBiaWdfZHJpcGxlYWZfaGVhZAEIEQBiaWdfZHJpcGxlYWZfdGlsdAQAbm9uZQgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:small_dripleaf_block", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnNtYWxsX2RyaXBsZWFmX2Jsb2NrBAkAbmFtZV9oYXNojxRAgXP9uWADCgBuZXR3b3JrX2lkozbVPwoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24EAGVhc3QBDwB1cHBlcl9ibG9ja19iaXQBAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:spore_blossom", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnNwb3JlX2Jsb3Nzb20ECQBuYW1lX2hhc2il3U72Gbco2gMKAG5ldHdvcmtfaWSbbbgcCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:azalea", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmF6YWxlYQQJAG5hbWVfaGFzaNyUl+BW9JrBAwoAbmV0d29ya19pZO/XZtQKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:flowering_azalea", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmZsb3dlcmluZ19hemFsZWEECQBuYW1lX2hhc2ie9r33wz8kiwMKAG5ldHdvcmtfaWQ3ij0VCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:glow_lichen", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Omdsb3dfbGljaGVuBAkAbmFtZV9oYXNobyPUrIYlo44DCgBuZXR3b3JrX2lkCh8lSAoGAHN0YXRlcwMZAG11bHRpX2ZhY2VfZGlyZWN0aW9uX2JpdHM/AAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:amethyst_block", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmFtZXRoeXN0X2Jsb2NrBAkAbmFtZV9oYXNob+JK1iiAthcDCgBuZXR3b3JrX2lk8HtpzgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:budding_amethyst", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmJ1ZGRpbmdfYW1ldGh5c3QECQBuYW1lX2hhc2gJvAwfI14fxgMKAG5ldHdvcmtfaWTQYqfACgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:amethyst_cluster", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmFtZXRoeXN0X2NsdXN0ZXIECQBuYW1lX2hhc2jK82S88Jgm8wMKAG5ldHdvcmtfaWSCPMPGCgYAc3RhdGVzCBQAbWluZWNyYWZ0OmJsb2NrX2ZhY2UCAHVwAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:large_amethyst_bud", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmxhcmdlX2FtZXRoeXN0X2J1ZAQJAG5hbWVfaGFzaAHhdpWD+sd5AwoAbmV0d29ya19pZKkQxOcKBgBzdGF0ZXMIFABtaW5lY3JhZnQ6YmxvY2tfZmFjZQIAdXAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:medium_amethyst_bud", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0Om1lZGl1bV9hbWV0aHlzdF9idWQECQBuYW1lX2hhc2g5lBGtC0DzZQMKAG5ldHdvcmtfaWSYiP4gCgYAc3RhdGVzCBQAbWluZWNyYWZ0OmJsb2NrX2ZhY2UCAHVwAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:small_amethyst_bud", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnNtYWxsX2FtZXRoeXN0X2J1ZAQJAG5hbWVfaGFzaEnb4+q9PO4YAwoAbmV0d29ya19pZGWzxrQKBgBzdGF0ZXMIFABtaW5lY3JhZnQ6YmxvY2tfZmFjZQIAdXAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:tuff", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OnR1ZmYECQBuYW1lX2hhc2h1Rwc1XYsBGwMKAG5ldHdvcmtfaWRwQGn0CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:calcite", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmNhbGNpdGUECQBuYW1lX2hhc2ixKLu8ZIdzDQMKAG5ldHdvcmtfaWQlSbJDCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:chicken" + }, + { + "id": "minecraft:porkchop" + }, + { + "id": "minecraft:beef" + }, + { + "id": "minecraft:mutton" + }, + { + "id": "minecraft:rabbit" + }, + { + "id": "minecraft:cod" + }, + { + "id": "minecraft:salmon" + }, + { + "id": "minecraft:tropical_fish" + }, + { + "id": "minecraft:pufferfish" + }, + { + "id": "minecraft:brown_mushroom", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmJyb3duX211c2hyb29tBAkAbmFtZV9oYXNonYw/FO78WDoDCgBuZXR3b3JrX2lkLh1OXAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:red_mushroom", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZF9tdXNocm9vbQQJAG5hbWVfaGFzaPpzJua7669xAwoAbmV0d29ya19pZCvWPYkKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:crimson_fungus", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fZnVuZ3VzBAkAbmFtZV9oYXNolIcCUuFM2u0DCgBuZXR3b3JrX2lkD2NN0QoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:warped_fungus", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9mdW5ndXMECQBuYW1lX2hhc2gq8bSnRVTAFgMKAG5ldHdvcmtfaWTkwS+rCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:brown_mushroom_block", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkdOMhDAoGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cw4AAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:red_mushroom_block", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnJlZF9tdXNocm9vbV9ibG9jawQJAG5hbWVfaGFzaJTTyJbth9M9AwoAbmV0d29ya19pZM+AyboKBgBzdGF0ZXMDEgBodWdlX211c2hyb29tX2JpdHMOAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:brown_mushroom_block", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkbdt3CAoGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cw8AAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:brown_mushroom_block", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkSrMl9goGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cwAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:egg" + }, + { + "id": "minecraft:sugar_cane" + }, + { + "id": "minecraft:sugar" + }, + { + "id": "minecraft:rotten_flesh" + }, + { + "id": "minecraft:bone" + }, + { + "id": "minecraft:web", + "block_state_b64": "CgAACAQAbmFtZQ0AbWluZWNyYWZ0OndlYgQJAG5hbWVfaGFzaA4GKQCvG4i9AwoAbmV0d29ya19pZApt+jgKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:spider_eye" + }, + { + "id": "minecraft:mob_spawner", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vYl9zcGF3bmVyBAkAbmFtZV9oYXNoNwGrCV/Fkh8DCgBuZXR3b3JrX2lkM1wTmgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:monster_egg", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkqXH7RgoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGUFAHN0b25lAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:monster_egg", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkeIBb6QoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGULAGNvYmJsZXN0b25lAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:monster_egg", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkDZ2cFQoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGULAHN0b25lX2JyaWNrAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:monster_egg", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkOR/cTAoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGURAG1vc3N5X3N0b25lX2JyaWNrAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:monster_egg", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkqdwlHAoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGUTAGNyYWNrZWRfc3RvbmVfYnJpY2sAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:monster_egg", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkFqqPggoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGUUAGNoaXNlbGVkX3N0b25lX2JyaWNrAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:infested_deepslate", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmluZmVzdGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaICF2VYccxF1AwoAbmV0d29ya19pZDa/624KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:dragon_egg", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmRyYWdvbl9lZ2cECQBuYW1lX2hhc2inMzXrV+/e1wMKAG5ldHdvcmtfaWTgO1yRCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:turtle_egg", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnR1cnRsZV9lZ2cECQBuYW1lX2hhc2iwSRcxOJIJ9gMKAG5ldHdvcmtfaWSIRNUhCgYAc3RhdGVzCA0AY3JhY2tlZF9zdGF0ZQkAbm9fY3JhY2tzCBAAdHVydGxlX2VnZ19jb3VudAcAb25lX2VnZwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:sniffer_egg", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnNuaWZmZXJfZWdnBAkAbmFtZV9oYXNoY1lozc8lPcYDCgBuZXR3b3JrX2lk7yb/2QoGAHN0YXRlcwgNAGNyYWNrZWRfc3RhdGUJAG5vX2NyYWNrcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:frog_spawn", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmZyb2dfc3Bhd24ECQBuYW1lX2hhc2iWmd7idp3ZZwMKAG5ldHdvcmtfaWRFzJudCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:pearlescent_froglight", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnBlYXJsZXNjZW50X2Zyb2dsaWdodAQJAG5hbWVfaGFzaKkcFRyycYGyAwoAbmV0d29ya19pZJqYakAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:verdant_froglight", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnZlcmRhbnRfZnJvZ2xpZ2h0BAkAbmFtZV9oYXNoA+eXuTBohrQDCgBuZXR3b3JrX2lkDIVnsQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:ochre_froglight", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om9jaHJlX2Zyb2dsaWdodAQJAG5hbWVfaGFzaMY59kjPe+c3AwoAbmV0d29ya19pZO2TD50KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:chicken_spawn_egg" + }, + { + "id": "minecraft:bee_spawn_egg" + }, + { + "id": "minecraft:cow_spawn_egg" + }, + { + "id": "minecraft:pig_spawn_egg" + }, + { + "id": "minecraft:sheep_spawn_egg" + }, + { + "id": "minecraft:wolf_spawn_egg" + }, + { + "id": "minecraft:polar_bear_spawn_egg" + }, + { + "id": "minecraft:ocelot_spawn_egg" + }, + { + "id": "minecraft:cat_spawn_egg" + }, + { + "id": "minecraft:mooshroom_spawn_egg" + }, + { + "id": "minecraft:bat_spawn_egg" + }, + { + "id": "minecraft:parrot_spawn_egg" + }, + { + "id": "minecraft:rabbit_spawn_egg" + }, + { + "id": "minecraft:llama_spawn_egg" + }, + { + "id": "minecraft:horse_spawn_egg" + }, + { + "id": "minecraft:donkey_spawn_egg" + }, + { + "id": "minecraft:mule_spawn_egg" + }, + { + "id": "minecraft:skeleton_horse_spawn_egg" + }, + { + "id": "minecraft:zombie_horse_spawn_egg" + }, + { + "id": "minecraft:tropical_fish_spawn_egg" + }, + { + "id": "minecraft:cod_spawn_egg" + }, + { + "id": "minecraft:pufferfish_spawn_egg" + }, + { + "id": "minecraft:salmon_spawn_egg" + }, + { + "id": "minecraft:dolphin_spawn_egg" + }, + { + "id": "minecraft:turtle_spawn_egg" + }, + { + "id": "minecraft:panda_spawn_egg" + }, + { + "id": "minecraft:fox_spawn_egg" + }, + { + "id": "minecraft:creeper_spawn_egg" + }, + { + "id": "minecraft:enderman_spawn_egg" + }, + { + "id": "minecraft:silverfish_spawn_egg" + }, + { + "id": "minecraft:skeleton_spawn_egg" + }, + { + "id": "minecraft:wither_skeleton_spawn_egg" + }, + { + "id": "minecraft:stray_spawn_egg" + }, + { + "id": "minecraft:slime_spawn_egg" + }, + { + "id": "minecraft:spider_spawn_egg" + }, + { + "id": "minecraft:zombie_spawn_egg" + }, + { + "id": "minecraft:zombie_pigman_spawn_egg" + }, + { + "id": "minecraft:husk_spawn_egg" + }, + { + "id": "minecraft:drowned_spawn_egg" + }, + { + "id": "minecraft:squid_spawn_egg" + }, + { + "id": "minecraft:glow_squid_spawn_egg" + }, + { + "id": "minecraft:cave_spider_spawn_egg" + }, + { + "id": "minecraft:witch_spawn_egg" + }, + { + "id": "minecraft:guardian_spawn_egg" + }, + { + "id": "minecraft:elder_guardian_spawn_egg" + }, + { + "id": "minecraft:endermite_spawn_egg" + }, + { + "id": "minecraft:magma_cube_spawn_egg" + }, + { + "id": "minecraft:strider_spawn_egg" + }, + { + "id": "minecraft:hoglin_spawn_egg" + }, + { + "id": "minecraft:piglin_spawn_egg" + }, + { + "id": "minecraft:zoglin_spawn_egg" + }, + { + "id": "minecraft:piglin_brute_spawn_egg" + }, + { + "id": "minecraft:goat_spawn_egg" + }, + { + "id": "minecraft:axolotl_spawn_egg" + }, + { + "id": "minecraft:warden_spawn_egg" + }, + { + "id": "minecraft:allay_spawn_egg" + }, + { + "id": "minecraft:frog_spawn_egg" + }, + { + "id": "minecraft:tadpole_spawn_egg" + }, + { + "id": "minecraft:trader_llama_spawn_egg" + }, + { + "id": "minecraft:camel_spawn_egg" + }, + { + "id": "minecraft:ghast_spawn_egg" + }, + { + "id": "minecraft:blaze_spawn_egg" + }, + { + "id": "minecraft:shulker_spawn_egg" + }, + { + "id": "minecraft:vindicator_spawn_egg" + }, + { + "id": "minecraft:evoker_spawn_egg" + }, + { + "id": "minecraft:vex_spawn_egg" + }, + { + "id": "minecraft:villager_spawn_egg" + }, + { + "id": "minecraft:wandering_trader_spawn_egg" + }, + { + "id": "minecraft:zombie_villager_spawn_egg" + }, + { + "id": "minecraft:phantom_spawn_egg" + }, + { + "id": "minecraft:pillager_spawn_egg" + }, + { + "id": "minecraft:ravager_spawn_egg" + }, + { + "id": "minecraft:iron_golem_spawn_egg" + }, + { + "id": "minecraft:snow_golem_spawn_egg" + }, + { + "id": "minecraft:sniffer_spawn_egg" + }, + { + "id": "minecraft:obsidian", + "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0Om9ic2lkaWFuBAkAbmFtZV9oYXNoiz4qrb8QjyEDCgBuZXR3b3JrX2lkuqnPpQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:crying_obsidian", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmNyeWluZ19vYnNpZGlhbgQJAG5hbWVfaGFzaKT0JlA7Z1K+AwoAbmV0d29ya19pZCjbPV4KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:bedrock", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmJlZHJvY2sECQBuYW1lX2hhc2hWfFrh4LVtxwMKAG5ldHdvcmtfaWT7fKz1CgYAc3RhdGVzAQ4AaW5maW5pYnVybl9iaXQAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:soul_sand", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnNvdWxfc2FuZAQJAG5hbWVfaGFzaMaf+bccu+KTAwoAbmV0d29ya19pZBQSHrMKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:magma", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0Om1hZ21hBAkAbmFtZV9oYXNoqyTjKaIsWfYDCgBuZXR3b3JrX2lkyfWAZgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:nether_wart" + }, + { + "id": "minecraft:end_stone", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmVuZF9zdG9uZQQJAG5hbWVfaGFzaH1J9jA39GJNAwoAbmV0d29ya19pZFeFQ7UKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:chorus_flower", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNob3J1c19mbG93ZXIECQBuYW1lX2hhc2iMpSodli5uawMKAG5ldHdvcmtfaWRnd1ZWCgYAc3RhdGVzAwMAYWdlAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:chorus_plant", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmNob3J1c19wbGFudAQJAG5hbWVfaGFzaJhSrmNGKwaMAwoAbmV0d29ya19pZA3uVqMKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:chorus_fruit" + }, + { + "id": "minecraft:popped_chorus_fruit" + }, + { + "id": "minecraft:sponge", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnNwb25nZQQJAG5hbWVfaGFzaLrd2ScYRDMiAwoAbmV0d29ya19pZF01rO0KBgBzdGF0ZXMICwBzcG9uZ2VfdHlwZQMAZHJ5AAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:sponge", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnNwb25nZQQJAG5hbWVfaGFzaLrd2ScYRDMiAwoAbmV0d29ya19pZPiOc4QKBgBzdGF0ZXMICwBzcG9uZ2VfdHlwZQMAd2V0AAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkGnlaAwoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABibHVlAQgAZGVhZF9iaXQAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkSnHuagoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABwaW5rAQgAZGVhZF9iaXQAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkmkHyegoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgBwdXJwbGUBCABkZWFkX2JpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkdpUDxgoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yAwByZWQBCABkZWFkX2JpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkYNWvYgoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgB5ZWxsb3cBCABkZWFkX2JpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkZSxBQgoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABibHVlAQgAZGVhZF9iaXQBAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lklSTVqQoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABwaW5rAQgAZGVhZF9iaXQBAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lk5fTYuQoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgBwdXJwbGUBCABkZWFkX2JpdAEAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkwUjqBAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yAwByZWQBCABkZWFkX2JpdAEAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkq4iWoQoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgB5ZWxsb3cBCABkZWFkX2JpdAEAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:sculk", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnNjdWxrBAkAbmFtZV9oYXNo2Lq7T5yQF8kDCgBuZXR3b3JrX2lkyqUPPgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:sculk_vein", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnNjdWxrX3ZlaW4ECQBuYW1lX2hhc2gJUdhVooV4zwMKAG5ldHdvcmtfaWSUfn1XCgYAc3RhdGVzAxkAbXVsdGlfZmFjZV9kaXJlY3Rpb25fYml0cwAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:sculk_catalyst", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnNjdWxrX2NhdGFseXN0BAkAbmFtZV9oYXNo+gCpbrCHST4DCgBuZXR3b3JrX2lkMJ2n/woGAHN0YXRlcwEFAGJsb29tAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:sculk_shrieker", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnNjdWxrX3Nocmlla2VyBAkAbmFtZV9oYXNo5OXtyObniQ4DCgBuZXR3b3JrX2lkxapoNAoGAHN0YXRlcwEGAGFjdGl2ZQABCgBjYW5fc3VtbW9uAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:sculk_sensor", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnNjdWxrX3NlbnNvcgQJAG5hbWVfaGFzaCkmHreeTgNnAwoAbmV0d29ya19pZLj2WPcKBgBzdGF0ZXMDEgBzY3Vsa19zZW5zb3JfcGhhc2UAAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:calibrated_sculk_sensor", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmNhbGlicmF0ZWRfc2N1bGtfc2Vuc29yBAkAbmFtZV9oYXNoffAcXXN/iJUDCgBuZXR3b3JrX2lkwOx3QQoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAxIAc2N1bGtfc2Vuc29yX3BoYXNlAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:reinforced_deepslate", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnJlaW5mb3JjZWRfZGVlcHNsYXRlBAkAbmFtZV9oYXNoldDmj91EapQDCgBuZXR3b3JrX2lkHIt+aQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:leather_helmet" + }, + { + "id": "minecraft:chainmail_helmet" + }, + { + "id": "minecraft:iron_helmet" + }, + { + "id": "minecraft:golden_helmet" + }, + { + "id": "minecraft:diamond_helmet" + }, + { + "id": "minecraft:netherite_helmet" + }, + { + "id": "minecraft:leather_chestplate" + }, + { + "id": "minecraft:chainmail_chestplate" + }, + { + "id": "minecraft:iron_chestplate" + }, + { + "id": "minecraft:golden_chestplate" + }, + { + "id": "minecraft:diamond_chestplate" + }, + { + "id": "minecraft:netherite_chestplate" + }, + { + "id": "minecraft:leather_leggings" + }, + { + "id": "minecraft:chainmail_leggings" + }, + { + "id": "minecraft:iron_leggings" + }, + { + "id": "minecraft:golden_leggings" + }, + { + "id": "minecraft:diamond_leggings" + }, + { + "id": "minecraft:netherite_leggings" + }, + { + "id": "minecraft:leather_boots" + }, + { + "id": "minecraft:chainmail_boots" + }, + { + "id": "minecraft:iron_boots" + }, + { + "id": "minecraft:golden_boots" + }, + { + "id": "minecraft:diamond_boots" + }, + { + "id": "minecraft:netherite_boots" + }, + { + "id": "minecraft:wooden_sword" + }, + { + "id": "minecraft:stone_sword" + }, + { + "id": "minecraft:iron_sword" + }, + { + "id": "minecraft:golden_sword" + }, + { + "id": "minecraft:diamond_sword" + }, + { + "id": "minecraft:netherite_sword" + }, + { + "id": "minecraft:wooden_axe" + }, + { + "id": "minecraft:stone_axe" + }, + { + "id": "minecraft:iron_axe" + }, + { + "id": "minecraft:golden_axe" + }, + { + "id": "minecraft:diamond_axe" + }, + { + "id": "minecraft:netherite_axe" + }, + { + "id": "minecraft:wooden_pickaxe" + }, + { + "id": "minecraft:stone_pickaxe" + }, + { + "id": "minecraft:iron_pickaxe" + }, + { + "id": "minecraft:golden_pickaxe" + }, + { + "id": "minecraft:diamond_pickaxe" + }, + { + "id": "minecraft:netherite_pickaxe" + }, + { + "id": "minecraft:wooden_shovel" + }, + { + "id": "minecraft:stone_shovel" + }, + { + "id": "minecraft:iron_shovel" + }, + { + "id": "minecraft:golden_shovel" + }, + { + "id": "minecraft:diamond_shovel" + }, + { + "id": "minecraft:netherite_shovel" + }, + { + "id": "minecraft:wooden_hoe" + }, + { + "id": "minecraft:stone_hoe" + }, + { + "id": "minecraft:iron_hoe" + }, + { + "id": "minecraft:golden_hoe" + }, + { + "id": "minecraft:diamond_hoe" + }, + { + "id": "minecraft:netherite_hoe" + }, + { + "id": "minecraft:bow" + }, + { + "id": "minecraft:crossbow" + }, + { + "id": "minecraft:arrow" + }, + { + "id": "minecraft:arrow", + "damage": 6 + }, + { + "id": "minecraft:arrow", + "damage": 7 + }, + { + "id": "minecraft:arrow", + "damage": 8 + }, + { + "id": "minecraft:arrow", + "damage": 9 + }, + { + "id": "minecraft:arrow", + "damage": 10 + }, + { + "id": "minecraft:arrow", + "damage": 11 + }, + { + "id": "minecraft:arrow", + "damage": 12 + }, + { + "id": "minecraft:arrow", + "damage": 13 + }, + { + "id": "minecraft:arrow", + "damage": 14 + }, + { + "id": "minecraft:arrow", + "damage": 15 + }, + { + "id": "minecraft:arrow", + "damage": 16 + }, + { + "id": "minecraft:arrow", + "damage": 17 + }, + { + "id": "minecraft:arrow", + "damage": 18 + }, + { + "id": "minecraft:arrow", + "damage": 19 + }, + { + "id": "minecraft:arrow", + "damage": 20 + }, + { + "id": "minecraft:arrow", + "damage": 21 + }, + { + "id": "minecraft:arrow", + "damage": 22 + }, + { + "id": "minecraft:arrow", + "damage": 23 + }, + { + "id": "minecraft:arrow", + "damage": 24 + }, + { + "id": "minecraft:arrow", + "damage": 25 + }, + { + "id": "minecraft:arrow", + "damage": 26 + }, + { + "id": "minecraft:arrow", + "damage": 27 + }, + { + "id": "minecraft:arrow", + "damage": 28 + }, + { + "id": "minecraft:arrow", + "damage": 29 + }, + { + "id": "minecraft:arrow", + "damage": 30 + }, + { + "id": "minecraft:arrow", + "damage": 31 + }, + { + "id": "minecraft:arrow", + "damage": 32 + }, + { + "id": "minecraft:arrow", + "damage": 33 + }, + { + "id": "minecraft:arrow", + "damage": 34 + }, + { + "id": "minecraft:arrow", + "damage": 35 + }, + { + "id": "minecraft:arrow", + "damage": 36 + }, + { + "id": "minecraft:arrow", + "damage": 37 + }, + { + "id": "minecraft:arrow", + "damage": 38 + }, + { + "id": "minecraft:arrow", + "damage": 39 + }, + { + "id": "minecraft:arrow", + "damage": 40 + }, + { + "id": "minecraft:arrow", + "damage": 41 + }, + { + "id": "minecraft:arrow", + "damage": 42 + }, + { + "id": "minecraft:arrow", + "damage": 43 + }, + { + "id": "minecraft:shield" + }, + { + "id": "minecraft:cooked_chicken" + }, + { + "id": "minecraft:cooked_porkchop" + }, + { + "id": "minecraft:cooked_beef" + }, + { + "id": "minecraft:cooked_mutton" + }, + { + "id": "minecraft:cooked_rabbit" + }, + { + "id": "minecraft:cooked_cod" + }, + { + "id": "minecraft:cooked_salmon" + }, + { + "id": "minecraft:bread" + }, + { + "id": "minecraft:mushroom_stew" + }, + { + "id": "minecraft:beetroot_soup" + }, + { + "id": "minecraft:rabbit_stew" + }, + { + "id": "minecraft:baked_potato" + }, + { + "id": "minecraft:cookie" + }, + { + "id": "minecraft:pumpkin_pie" + }, + { + "id": "minecraft:cake" + }, + { + "id": "minecraft:dried_kelp" + }, + { + "id": "minecraft:fishing_rod" + }, + { + "id": "minecraft:carrot_on_a_stick" + }, + { + "id": "minecraft:warped_fungus_on_a_stick" + }, + { + "id": "minecraft:snowball" + }, + { + "id": "minecraft:shears" + }, + { + "id": "minecraft:flint_and_steel" + }, + { + "id": "minecraft:lead" + }, + { + "id": "minecraft:clock" + }, + { + "id": "minecraft:compass" + }, + { + "id": "minecraft:recovery_compass" + }, + { + "id": "minecraft:goat_horn" + }, + { + "id": "minecraft:goat_horn", + "damage": 1 + }, + { + "id": "minecraft:goat_horn", + "damage": 2 + }, + { + "id": "minecraft:goat_horn", + "damage": 3 + }, + { + "id": "minecraft:goat_horn", + "damage": 4 + }, + { + "id": "minecraft:goat_horn", + "damage": 5 + }, + { + "id": "minecraft:goat_horn", + "damage": 6 + }, + { + "id": "minecraft:goat_horn", + "damage": 7 + }, + { + "id": "minecraft:empty_map" + }, + { + "id": "minecraft:empty_map", + "damage": 2 + }, + { + "id": "minecraft:saddle" + }, + { + "id": "minecraft:leather_horse_armor" + }, + { + "id": "minecraft:iron_horse_armor" + }, + { + "id": "minecraft:golden_horse_armor" + }, + { + "id": "minecraft:diamond_horse_armor" + }, + { + "id": "minecraft:trident" + }, + { + "id": "minecraft:turtle_helmet" + }, + { + "id": "minecraft:elytra" + }, + { + "id": "minecraft:totem_of_undying" + }, + { + "id": "minecraft:glass_bottle" + }, + { + "id": "minecraft:experience_bottle" + }, + { + "id": "minecraft:potion" + }, + { + "id": "minecraft:potion", + "damage": 1 + }, + { + "id": "minecraft:potion", + "damage": 2 + }, + { + "id": "minecraft:potion", + "damage": 3 + }, + { + "id": "minecraft:potion", + "damage": 4 + }, + { + "id": "minecraft:potion", + "damage": 5 + }, + { + "id": "minecraft:potion", + "damage": 6 + }, + { + "id": "minecraft:potion", + "damage": 7 + }, + { + "id": "minecraft:potion", + "damage": 8 + }, + { + "id": "minecraft:potion", + "damage": 9 + }, + { + "id": "minecraft:potion", + "damage": 10 + }, + { + "id": "minecraft:potion", + "damage": 11 + }, + { + "id": "minecraft:potion", + "damage": 12 + }, + { + "id": "minecraft:potion", + "damage": 13 + }, + { + "id": "minecraft:potion", + "damage": 14 + }, + { + "id": "minecraft:potion", + "damage": 15 + }, + { + "id": "minecraft:potion", + "damage": 16 + }, + { + "id": "minecraft:potion", + "damage": 17 + }, + { + "id": "minecraft:potion", + "damage": 18 + }, + { + "id": "minecraft:potion", + "damage": 19 + }, + { + "id": "minecraft:potion", + "damage": 20 + }, + { + "id": "minecraft:potion", + "damage": 21 + }, + { + "id": "minecraft:potion", + "damage": 22 + }, + { + "id": "minecraft:potion", + "damage": 23 + }, + { + "id": "minecraft:potion", + "damage": 24 + }, + { + "id": "minecraft:potion", + "damage": 25 + }, + { + "id": "minecraft:potion", + "damage": 26 + }, + { + "id": "minecraft:potion", + "damage": 27 + }, + { + "id": "minecraft:potion", + "damage": 28 + }, + { + "id": "minecraft:potion", + "damage": 29 + }, + { + "id": "minecraft:potion", + "damage": 30 + }, + { + "id": "minecraft:potion", + "damage": 31 + }, + { + "id": "minecraft:potion", + "damage": 32 + }, + { + "id": "minecraft:potion", + "damage": 33 + }, + { + "id": "minecraft:potion", + "damage": 34 + }, + { + "id": "minecraft:potion", + "damage": 35 + }, + { + "id": "minecraft:potion", + "damage": 36 + }, + { + "id": "minecraft:potion", + "damage": 37 + }, + { + "id": "minecraft:potion", + "damage": 38 + }, + { + "id": "minecraft:potion", + "damage": 39 + }, + { + "id": "minecraft:potion", + "damage": 40 + }, + { + "id": "minecraft:potion", + "damage": 41 + }, + { + "id": "minecraft:potion", + "damage": 42 + }, + { + "id": "minecraft:splash_potion" + }, + { + "id": "minecraft:splash_potion", + "damage": 1 + }, + { + "id": "minecraft:splash_potion", + "damage": 2 + }, + { + "id": "minecraft:splash_potion", + "damage": 3 + }, + { + "id": "minecraft:splash_potion", + "damage": 4 + }, + { + "id": "minecraft:splash_potion", + "damage": 5 + }, + { + "id": "minecraft:splash_potion", + "damage": 6 + }, + { + "id": "minecraft:splash_potion", + "damage": 7 + }, + { + "id": "minecraft:splash_potion", + "damage": 8 + }, + { + "id": "minecraft:splash_potion", + "damage": 9 + }, + { + "id": "minecraft:splash_potion", + "damage": 10 + }, + { + "id": "minecraft:splash_potion", + "damage": 11 + }, + { + "id": "minecraft:splash_potion", + "damage": 12 + }, + { + "id": "minecraft:splash_potion", + "damage": 13 + }, + { + "id": "minecraft:splash_potion", + "damage": 14 + }, + { + "id": "minecraft:splash_potion", + "damage": 15 + }, + { + "id": "minecraft:splash_potion", + "damage": 16 + }, + { + "id": "minecraft:splash_potion", + "damage": 17 + }, + { + "id": "minecraft:splash_potion", + "damage": 18 + }, + { + "id": "minecraft:splash_potion", + "damage": 19 + }, + { + "id": "minecraft:splash_potion", + "damage": 20 + }, + { + "id": "minecraft:splash_potion", + "damage": 21 + }, + { + "id": "minecraft:splash_potion", + "damage": 22 + }, + { + "id": "minecraft:splash_potion", + "damage": 23 + }, + { + "id": "minecraft:splash_potion", + "damage": 24 + }, + { + "id": "minecraft:splash_potion", + "damage": 25 + }, + { + "id": "minecraft:splash_potion", + "damage": 26 + }, + { + "id": "minecraft:splash_potion", + "damage": 27 + }, + { + "id": "minecraft:splash_potion", + "damage": 28 + }, + { + "id": "minecraft:splash_potion", + "damage": 29 + }, + { + "id": "minecraft:splash_potion", + "damage": 30 + }, + { + "id": "minecraft:splash_potion", + "damage": 31 + }, + { + "id": "minecraft:splash_potion", + "damage": 32 + }, + { + "id": "minecraft:splash_potion", + "damage": 33 + }, + { + "id": "minecraft:splash_potion", + "damage": 34 + }, + { + "id": "minecraft:splash_potion", + "damage": 35 + }, + { + "id": "minecraft:splash_potion", + "damage": 36 + }, + { + "id": "minecraft:splash_potion", + "damage": 37 + }, + { + "id": "minecraft:splash_potion", + "damage": 38 + }, + { + "id": "minecraft:splash_potion", + "damage": 39 + }, + { + "id": "minecraft:splash_potion", + "damage": 40 + }, + { + "id": "minecraft:splash_potion", + "damage": 41 + }, + { + "id": "minecraft:splash_potion", + "damage": 42 + }, + { + "id": "minecraft:lingering_potion" + }, + { + "id": "minecraft:lingering_potion", + "damage": 1 + }, + { + "id": "minecraft:lingering_potion", + "damage": 2 + }, + { + "id": "minecraft:lingering_potion", + "damage": 3 + }, + { + "id": "minecraft:lingering_potion", + "damage": 4 + }, + { + "id": "minecraft:lingering_potion", + "damage": 5 + }, + { + "id": "minecraft:lingering_potion", + "damage": 6 + }, + { + "id": "minecraft:lingering_potion", + "damage": 7 + }, + { + "id": "minecraft:lingering_potion", + "damage": 8 + }, + { + "id": "minecraft:lingering_potion", + "damage": 9 + }, + { + "id": "minecraft:lingering_potion", + "damage": 10 + }, + { + "id": "minecraft:lingering_potion", + "damage": 11 + }, + { + "id": "minecraft:lingering_potion", + "damage": 12 + }, + { + "id": "minecraft:lingering_potion", + "damage": 13 + }, + { + "id": "minecraft:lingering_potion", + "damage": 14 + }, + { + "id": "minecraft:lingering_potion", + "damage": 15 + }, + { + "id": "minecraft:lingering_potion", + "damage": 16 + }, + { + "id": "minecraft:lingering_potion", + "damage": 17 + }, + { + "id": "minecraft:lingering_potion", + "damage": 18 + }, + { + "id": "minecraft:lingering_potion", + "damage": 19 + }, + { + "id": "minecraft:lingering_potion", + "damage": 20 + }, + { + "id": "minecraft:lingering_potion", + "damage": 21 + }, + { + "id": "minecraft:lingering_potion", + "damage": 22 + }, + { + "id": "minecraft:lingering_potion", + "damage": 23 + }, + { + "id": "minecraft:lingering_potion", + "damage": 24 + }, + { + "id": "minecraft:lingering_potion", + "damage": 25 + }, + { + "id": "minecraft:lingering_potion", + "damage": 26 + }, + { + "id": "minecraft:lingering_potion", + "damage": 27 + }, + { + "id": "minecraft:lingering_potion", + "damage": 28 + }, + { + "id": "minecraft:lingering_potion", + "damage": 29 + }, + { + "id": "minecraft:lingering_potion", + "damage": 30 + }, + { + "id": "minecraft:lingering_potion", + "damage": 31 + }, + { + "id": "minecraft:lingering_potion", + "damage": 32 + }, + { + "id": "minecraft:lingering_potion", + "damage": 33 + }, + { + "id": "minecraft:lingering_potion", + "damage": 34 + }, + { + "id": "minecraft:lingering_potion", + "damage": 35 + }, + { + "id": "minecraft:lingering_potion", + "damage": 36 + }, + { + "id": "minecraft:lingering_potion", + "damage": 37 + }, + { + "id": "minecraft:lingering_potion", + "damage": 38 + }, + { + "id": "minecraft:lingering_potion", + "damage": 39 + }, + { + "id": "minecraft:lingering_potion", + "damage": 40 + }, + { + "id": "minecraft:lingering_potion", + "damage": 41 + }, + { + "id": "minecraft:lingering_potion", + "damage": 42 + }, + { + "id": "minecraft:spyglass" + }, + { + "id": "minecraft:brush" + }, + { + "id": "minecraft:stick" + }, + { + "id": "minecraft:bed" + }, + { + "id": "minecraft:bed", + "damage": 8 + }, + { + "id": "minecraft:bed", + "damage": 7 + }, + { + "id": "minecraft:bed", + "damage": 15 + }, + { + "id": "minecraft:bed", + "damage": 12 + }, + { + "id": "minecraft:bed", + "damage": 14 + }, + { + "id": "minecraft:bed", + "damage": 1 + }, + { + "id": "minecraft:bed", + "damage": 4 + }, + { + "id": "minecraft:bed", + "damage": 5 + }, + { + "id": "minecraft:bed", + "damage": 13 + }, + { + "id": "minecraft:bed", + "damage": 9 + }, + { + "id": "minecraft:bed", + "damage": 3 + }, + { + "id": "minecraft:bed", + "damage": 11 + }, + { + "id": "minecraft:bed", + "damage": 10 + }, + { + "id": "minecraft:bed", + "damage": 2 + }, + { + "id": "minecraft:bed", + "damage": 6 + }, + { + "id": "minecraft:torch", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnRvcmNoBAkAbmFtZV9oYXNoagn7rmDBzisDCgBuZXR3b3JrX2lk+BwwuQoGAHN0YXRlcwgWAHRvcmNoX2ZhY2luZ19kaXJlY3Rpb24HAHVua25vd24AAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:soul_torch", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnNvdWxfdG9yY2gECQBuYW1lX2hhc2huixOT04BRdQMKAG5ldHdvcmtfaWShbFILCgYAc3RhdGVzCBYAdG9yY2hfZmFjaW5nX2RpcmVjdGlvbgcAdW5rbm93bgADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:sea_pickle", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnNlYV9waWNrbGUECQBuYW1lX2hhc2iONEfZJB+glgMKAG5ldHdvcmtfaWSINWQyCgYAc3RhdGVzAw0AY2x1c3Rlcl9jb3VudAAAAAABCABkZWFkX2JpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:lantern", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmxhbnRlcm4ECQBuYW1lX2hhc2hMw44VI2HWygMKAG5ldHdvcmtfaWRkjQvzCgYAc3RhdGVzAQcAaGFuZ2luZwAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:soul_lantern", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnNvdWxfbGFudGVybgQJAG5hbWVfaGFzaGjIpjxk9z+RAwoAbmV0d29ya19pZGfoP8cKBgBzdGF0ZXMBBwBoYW5naW5nAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:candle", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmNhbmRsZQQJAG5hbWVfaGFzaHPd+MsNdWTfAwoAbmV0d29ya19pZHsBMA0KBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:white_candle", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OndoaXRlX2NhbmRsZQQJAG5hbWVfaGFzaN1EG5Q1mHiEAwoAbmV0d29ya19pZKN1mmgKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:orange_candle", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Om9yYW5nZV9jYW5kbGUECQBuYW1lX2hhc2jySEVWHgUIHQMKAG5ldHdvcmtfaWSfVz82CgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:magenta_candle", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hZ2VudGFfY2FuZGxlBAkAbmFtZV9oYXNoG0u6YIOoBSEDCgBuZXR3b3JrX2lk9xGNkQoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:light_blue_candle", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY2FuZGxlBAkAbmFtZV9oYXNocXGeK0zgrG0DCgBuZXR3b3JrX2lk2m1y8goGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:yellow_candle", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19jYW5kbGUECQBuYW1lX2hhc2i00dtusU3CqQMKAG5ldHdvcmtfaWR9LTmpCgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:lime_candle", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmxpbWVfY2FuZGxlBAkAbmFtZV9oYXNokcmrw5xvz7ADCgBuZXR3b3JrX2lkIAUu6QoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:pink_candle", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfY2FuZGxlBAkAbmFtZV9oYXNoQJdEY4sZ0dwDCgBuZXR3b3JrX2lk23Rn5AoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:gray_candle", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmdyYXlfY2FuZGxlBAkAbmFtZV9oYXNoS5poSo9wBDEDCgBuZXR3b3JrX2lk3trRCAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:light_gray_candle", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY2FuZGxlBAkAbmFtZV9oYXNo9ruTZLBNMasDCgBuZXR3b3JrX2lkb6DOegoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:cyan_candle", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmN5YW5fY2FuZGxlBAkAbmFtZV9oYXNoc/M8PNVcjOwDCgBuZXR3b3JrX2lkZoIQOQoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:purple_candle", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnBsZV9jYW5kbGUECQBuYW1lX2hhc2jaI3xUW0/myQMKAG5ldHdvcmtfaWSnLI2BCgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:blue_candle", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmJsdWVfY2FuZGxlBAkAbmFtZV9oYXNoAASSPW6TgQADCgBuZXR3b3JrX2lkrxrjQAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:brown_candle", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJyb3duX2NhbmRsZQQJAG5hbWVfaGFzaDia0l6s1+WYAwoAbmV0d29ya19pZKSkBXYKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:green_candle", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmdyZWVuX2NhbmRsZQQJAG5hbWVfaGFzaLeFPO1l+fIoAwoAbmV0d29ya19pZBkznDsKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:red_candle", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9jYW5kbGUECQBuYW1lX2hhc2jjAQpGf59ZdwMKAG5ldHdvcmtfaWRbb88GCgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:black_candle", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJsYWNrX2NhbmRsZQQJAG5hbWVfaGFzaB+wRDpOqREKAwoAbmV0d29ya19pZNnOnuEKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:crafting_table", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyYWZ0aW5nX3RhYmxlBAkAbmFtZV9oYXNoe76VAmjvbpYDCgBuZXR3b3JrX2lkwCxwaAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:cartography_table", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmNhcnRvZ3JhcGh5X3RhYmxlBAkAbmFtZV9oYXNomaWiiD/znP8DCgBuZXR3b3JrX2lkI6FzMwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:fletching_table", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmZsZXRjaGluZ190YWJsZQQJAG5hbWVfaGFzaPFibh8unKyUAwoAbmV0d29ya19pZJ2mW0oKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:smithing_table", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnNtaXRoaW5nX3RhYmxlBAkAbmFtZV9oYXNo4tFES2xOXEYDCgBuZXR3b3JrX2lkXWMBzQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:beehive", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmJlZWhpdmUECQBuYW1lX2hhc2hCcqn12UbNpwMKAG5ldHdvcmtfaWR/idcaCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAMLAGhvbmV5X2xldmVsAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:suspicious_sand", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnN1c3BpY2lvdXNfc2FuZAQJAG5hbWVfaGFzaL67QsuvLP00AwoAbmV0d29ya19pZKnkaIAKBgBzdGF0ZXMDEABicnVzaGVkX3Byb2dyZXNzAAAAAAEHAGhhbmdpbmcBAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:suspicious_gravel", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN1c3BpY2lvdXNfZ3JhdmVsBAkAbmFtZV9oYXNoJSVbGNk7C3oDCgBuZXR3b3JrX2lkvIEJAAoGAHN0YXRlcwMQAGJydXNoZWRfcHJvZ3Jlc3MAAAAAAQcAaGFuZ2luZwEAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:campfire" + }, + { + "id": "minecraft:soul_campfire" + }, + { + "id": "minecraft:furnace", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmZ1cm5hY2UECQBuYW1lX2hhc2ioOQrludYY8wMKAG5ldHdvcmtfaWRZxnDOCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:blast_furnace", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmJsYXN0X2Z1cm5hY2UECQBuYW1lX2hhc2ivDbnjkpGm5QMKAG5ldHdvcmtfaWTcEbV/CgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:smoker", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnNtb2tlcgQJAG5hbWVfaGFzaJd1rDMkRWomAwoAbmV0d29ya19pZGWswMwKBgBzdGF0ZXMIHABtaW5lY3JhZnQ6Y2FyZGluYWxfZGlyZWN0aW9uBQBzb3V0aAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:respawn_anchor", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnJlc3Bhd25fYW5jaG9yBAkAbmFtZV9oYXNoZOdcjW05qigDCgBuZXR3b3JrX2lkmhMcaQoGAHN0YXRlcwMVAHJlc3Bhd25fYW5jaG9yX2NoYXJnZQAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:brewing_stand" + }, + { + "id": "minecraft:anvil", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmFudmlsBAkAbmFtZV9oYXNoNqB3fgcUCbwDCgBuZXR3b3JrX2lk8Z3VowoGAHN0YXRlcwgGAGRhbWFnZQkAdW5kYW1hZ2VkCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:anvil", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmFudmlsBAkAbmFtZV9oYXNoNqB3fgcUCbwDCgBuZXR3b3JrX2lkpiv8BAoGAHN0YXRlcwgGAGRhbWFnZRAAc2xpZ2h0bHlfZGFtYWdlZAgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:anvil", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmFudmlsBAkAbmFtZV9oYXNoNqB3fgcUCbwDCgBuZXR3b3JrX2lkFu+pdwoGAHN0YXRlcwgGAGRhbWFnZQwAdmVyeV9kYW1hZ2VkCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:grindstone", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmdyaW5kc3RvbmUECQBuYW1lX2hhc2id56zc0nk99wMKAG5ldHdvcmtfaWS4Es07CgYAc3RhdGVzCAoAYXR0YWNobWVudAgAc3RhbmRpbmcDCQBkaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:enchanting_table", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmVuY2hhbnRpbmdfdGFibGUECQBuYW1lX2hhc2jgIx24VLvMvwMKAG5ldHdvcmtfaWRliFFJCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:bookshelf", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmJvb2tzaGVsZgQJAG5hbWVfaGFzaDU04DrgJCS9AwoAbmV0d29ya19pZBcWwIwKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:chiseled_bookshelf", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmNoaXNlbGVkX2Jvb2tzaGVsZgQJAG5hbWVfaGFzaNXDBnsIsywYAwoAbmV0d29ya19pZIprt5IKBgBzdGF0ZXMDDABib29rc19zdG9yZWQAAAAAAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:lectern", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmxlY3Rlcm4ECQBuYW1lX2hhc2j5Z4Mmi/1QxAMKAG5ldHdvcmtfaWR4JfDHCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgBCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:cauldron" + }, + { + "id": "minecraft:composter", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmNvbXBvc3RlcgQJAG5hbWVfaGFzaPAADHptzeWJAwoAbmV0d29ya19pZHIL6i4KBgBzdGF0ZXMDFABjb21wb3N0ZXJfZmlsbF9sZXZlbAAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:chest", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmNoZXN0BAkAbmFtZV9oYXNog9ozMxlcA88DCgBuZXR3b3JrX2lkcrctxAoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:trapped_chest", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnRyYXBwZWRfY2hlc3QECQBuYW1lX2hhc2g2qpF9stsEjgMKAG5ldHdvcmtfaWSdRfncCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:ender_chest", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmVuZGVyX2NoZXN0BAkAbmFtZV9oYXNohEZzOFdg0WUDCgBuZXR3b3JrX2lkOc75awoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:barrel", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmJhcnJlbAQJAG5hbWVfaGFzaHDkRPGymiRqAwoAbmV0d29ya19pZPnxzgsKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:undyed_shulker_box", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnVuZHllZF9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaOC9mypm/MlBAwoAbmV0d29ya19pZJ8rxp0KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:white_shulker_box", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OndoaXRlX3NodWxrZXJfYm94BAkAbmFtZV9oYXNosK79m1rPUBwDCgBuZXR3b3JrX2lkjrET6goGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:light_gray_shulker_box", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2iBe5zq7PxHmgMKAG5ldHdvcmtfaWSCVJv0CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:gray_shulker_box", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmdyYXlfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2ga2s8ctjHUhgMKAG5ldHdvcmtfaWS3WMsWCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:black_shulker_box", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmJsYWNrX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoPm03OZphrp8DCgBuZXR3b3JrX2lkXHztNAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:brown_shulker_box", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmJyb3duX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoT3DD6qAL9cADCgBuZXR3b3JrX2lkaXxpYQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:red_shulker_box", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnJlZF9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaMIlKSCzqSZoAwoAbmV0d29ya19pZNrf+icKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:orange_shulker_box", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0Om9yYW5nZV9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaG2MAXU67wGrAwoAbmV0d29ya19pZGoO05gKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:yellow_shulker_box", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnllbGxvd19zaHVsa2VyX2JveAQJAG5hbWVfaGFzaIsLwQHYjcIEAwoAbmV0d29ya19pZBCBSiYKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:lime_shulker_box", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmxpbWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2hUwBkg+faUGAMKAG5ldHdvcmtfaWRJeKqqCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:green_shulker_box", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmdyZWVuX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoZgUeT3LupLUDCgBuZXR3b3JrX2lkzJiohQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:cyan_shulker_box", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmN5YW5fc2h1bGtlcl9ib3gECQBuYW1lX2hhc2gSfbjteXg5yAMKAG5ldHdvcmtfaWTHeliECgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:light_blue_shulker_box", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2h0VFCX0qsRxQMKAG5ldHdvcmtfaWQXD8U0CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:blue_shulker_box", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmJsdWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2hn9gS0XIe6rAMKAG5ldHdvcmtfaWTO4PJaCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:purple_shulker_box", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnB1cnBsZV9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaEV/lkNPxRDdAwoAbmV0d29ya19pZFK25GAKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:magenta_shulker_box", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0Om1hZ2VudGFfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2iqWM7IJHxcFgMKAG5ldHdvcmtfaWTyyudTCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:pink_shulker_box", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnBpbmtfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2in1tkJ1GNcZgMKAG5ldHdvcmtfaWQOEGXjCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:armor_stand" + }, + { + "id": "minecraft:noteblock", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0Om5vdGVibG9jawQJAG5hbWVfaGFzaHPA8dBBH0UaAwoAbmV0d29ya19pZH1U5QkKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:jukebox", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0Omp1a2Vib3gECQBuYW1lX2hhc2ieAIPExf/ZfgMKAG5ldHdvcmtfaWSmR7JfCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:music_disc_13" + }, + { + "id": "minecraft:music_disc_cat" + }, + { + "id": "minecraft:music_disc_blocks" + }, + { + "id": "minecraft:music_disc_chirp" + }, + { + "id": "minecraft:music_disc_far" + }, + { + "id": "minecraft:music_disc_mall" + }, + { + "id": "minecraft:music_disc_mellohi" + }, + { + "id": "minecraft:music_disc_stal" + }, + { + "id": "minecraft:music_disc_strad" + }, + { + "id": "minecraft:music_disc_ward" + }, + { + "id": "minecraft:music_disc_11" + }, + { + "id": "minecraft:music_disc_wait" + }, + { + "id": "minecraft:music_disc_otherside" + }, + { + "id": "minecraft:music_disc_5" + }, + { + "id": "minecraft:music_disc_pigstep" + }, + { + "id": "minecraft:music_disc_relic" + }, + { + "id": "minecraft:disc_fragment_5" + }, + { + "id": "minecraft:glowstone_dust" + }, + { + "id": "minecraft:glowstone", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0Omdsb3dzdG9uZQQJAG5hbWVfaGFzaFYqXNkefIlPAwoAbmV0d29ya19pZGT7WYYKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:redstone_lamp", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZHN0b25lX2xhbXAECQBuYW1lX2hhc2hJ9V80caPvEgMKAG5ldHdvcmtfaWRvNPwnCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:sea_lantern", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnNlYV9sYW50ZXJuBAkAbmFtZV9oYXNoLPsv1TX9M+QDCgBuZXR3b3JrX2lk1PPVyAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:oak_sign" + }, + { + "id": "minecraft:spruce_sign" + }, + { + "id": "minecraft:birch_sign" + }, + { + "id": "minecraft:jungle_sign" + }, + { + "id": "minecraft:acacia_sign" + }, + { + "id": "minecraft:dark_oak_sign" + }, + { + "id": "minecraft:mangrove_sign" + }, + { + "id": "minecraft:cherry_sign" + }, + { + "id": "minecraft:bamboo_sign" + }, + { + "id": "minecraft:crimson_sign" + }, + { + "id": "minecraft:warped_sign" + }, + { + "id": "minecraft:oak_hanging_sign" + }, + { + "id": "minecraft:spruce_hanging_sign" + }, + { + "id": "minecraft:birch_hanging_sign" + }, + { + "id": "minecraft:jungle_hanging_sign" + }, + { + "id": "minecraft:acacia_hanging_sign" + }, + { + "id": "minecraft:dark_oak_hanging_sign" + }, + { + "id": "minecraft:mangrove_hanging_sign" + }, + { + "id": "minecraft:cherry_hanging_sign" + }, + { + "id": "minecraft:bamboo_hanging_sign" + }, + { + "id": "minecraft:crimson_hanging_sign" + }, + { + "id": "minecraft:warped_hanging_sign" + }, + { + "id": "minecraft:painting" + }, + { + "id": "minecraft:frame" + }, + { + "id": "minecraft:glow_frame" + }, + { + "id": "minecraft:honey_bottle" + }, + { + "id": "minecraft:flower_pot" + }, + { + "id": "minecraft:bowl" + }, + { + "id": "minecraft:bucket" + }, + { + "id": "minecraft:milk_bucket" + }, + { + "id": "minecraft:water_bucket" + }, + { + "id": "minecraft:lava_bucket" + }, + { + "id": "minecraft:cod_bucket" + }, + { + "id": "minecraft:salmon_bucket" + }, + { + "id": "minecraft:tropical_fish_bucket" + }, + { + "id": "minecraft:pufferfish_bucket" + }, + { + "id": "minecraft:powder_snow_bucket" + }, + { + "id": "minecraft:axolotl_bucket" + }, + { + "id": "minecraft:tadpole_bucket" + }, + { + "id": "minecraft:skull", + "damage": 3 + }, + { + "id": "minecraft:skull", + "damage": 2 + }, + { + "id": "minecraft:skull", + "damage": 4 + }, + { + "id": "minecraft:skull", + "damage": 5 + }, + { + "id": "minecraft:skull" + }, + { + "id": "minecraft:skull", + "damage": 1 + }, + { + "id": "minecraft:skull", + "damage": 6 + }, + { + "id": "minecraft:beacon", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmJlYWNvbgQJAG5hbWVfaGFzaACwhhfSkdkHAwoAbmV0d29ya19pZF8jfiEKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:bell", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OmJlbGwECQBuYW1lX2hhc2iPqsgDXRcsxAMKAG5ldHdvcmtfaWT7zhOoCgYAc3RhdGVzCAoAYXR0YWNobWVudAgAc3RhbmRpbmcDCQBkaXJlY3Rpb24AAAAAAQoAdG9nZ2xlX2JpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:conduit", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmNvbmR1aXQECQBuYW1lX2hhc2jqxKAxq2EaWQMKAG5ldHdvcmtfaWTWcBVnCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:stonecutter_block", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lY3V0dGVyX2Jsb2NrBAkAbmFtZV9oYXNoQAXTbAM3MeYDCgBuZXR3b3JrX2lk18KHygoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:end_portal_frame", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmVuZF9wb3J0YWxfZnJhbWUECQBuYW1lX2hhc2gqofyUIjGOpQMKAG5ldHdvcmtfaWRbGHf8CgYAc3RhdGVzARIAZW5kX3BvcnRhbF9leWVfYml0AAgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:coal" + }, + { + "id": "minecraft:charcoal" + }, + { + "id": "minecraft:diamond" + }, + { + "id": "minecraft:iron_nugget" + }, + { + "id": "minecraft:raw_iron" + }, + { + "id": "minecraft:raw_gold" + }, + { + "id": "minecraft:raw_copper" + }, + { + "id": "minecraft:copper_ingot" + }, + { + "id": "minecraft:iron_ingot" + }, + { + "id": "minecraft:netherite_scrap" + }, + { + "id": "minecraft:netherite_ingot" + }, + { + "id": "minecraft:gold_nugget" + }, + { + "id": "minecraft:gold_ingot" + }, + { + "id": "minecraft:emerald" + }, + { + "id": "minecraft:quartz" + }, + { + "id": "minecraft:clay_ball" + }, + { + "id": "minecraft:brick" + }, + { + "id": "minecraft:netherbrick" + }, + { + "id": "minecraft:prismarine_shard" + }, + { + "id": "minecraft:amethyst_shard" + }, + { + "id": "minecraft:prismarine_crystals" + }, + { + "id": "minecraft:nautilus_shell" + }, + { + "id": "minecraft:heart_of_the_sea" + }, + { + "id": "minecraft:scute" + }, + { + "id": "minecraft:phantom_membrane" + }, + { + "id": "minecraft:string" + }, + { + "id": "minecraft:feather" + }, + { + "id": "minecraft:flint" + }, + { + "id": "minecraft:gunpowder" + }, + { + "id": "minecraft:leather" + }, + { + "id": "minecraft:rabbit_hide" + }, + { + "id": "minecraft:rabbit_foot" + }, + { + "id": "minecraft:fire_charge" + }, + { + "id": "minecraft:blaze_rod" + }, + { + "id": "minecraft:blaze_powder" + }, + { + "id": "minecraft:magma_cream" + }, + { + "id": "minecraft:fermented_spider_eye" + }, + { + "id": "minecraft:echo_shard" + }, + { + "id": "minecraft:dragon_breath" + }, + { + "id": "minecraft:shulker_shell" + }, + { + "id": "minecraft:ghast_tear" + }, + { + "id": "minecraft:slime_ball" + }, + { + "id": "minecraft:ender_pearl" + }, + { + "id": "minecraft:ender_eye" + }, + { + "id": "minecraft:nether_star" + }, + { + "id": "minecraft:end_rod", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmVuZF9yb2QECQBuYW1lX2hhc2jx/q5cEA0hmQMKAG5ldHdvcmtfaWQ2eM8kCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:lightning_rod", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmxpZ2h0bmluZ19yb2QECQBuYW1lX2hhc2ioXQF1xvfHNQMKAG5ldHdvcmtfaWRLuHyACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:end_crystal" + }, + { + "id": "minecraft:paper" + }, + { + "id": "minecraft:book" + }, + { + "id": "minecraft:writable_book" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQFAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQFAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQFAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQGAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQGAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQGAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQHAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQHAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQHAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQIAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAUAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAUAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAUAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQMAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQMAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQNAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQNAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQOAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQOAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQOAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAUAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQQAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQRAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQRAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQRAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQSAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQSAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQSAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAUAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQUAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQUAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQVAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQWAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQXAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQXAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQXAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQYAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQYAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQYAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQZAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQZAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQaAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQbAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQcAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAUAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQeAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQeAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQeAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQfAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQfAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQfAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQgAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQhAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQjAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQjAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQjAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQkAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQkAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQkAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQlAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQlAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQlAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:oak_boat" + }, + { + "id": "minecraft:spruce_boat" + }, + { + "id": "minecraft:birch_boat" + }, + { + "id": "minecraft:jungle_boat" + }, + { + "id": "minecraft:acacia_boat" + }, + { + "id": "minecraft:dark_oak_boat" + }, + { + "id": "minecraft:mangrove_boat" + }, + { + "id": "minecraft:cherry_boat" + }, + { + "id": "minecraft:bamboo_raft" + }, + { + "id": "minecraft:oak_chest_boat" + }, + { + "id": "minecraft:spruce_chest_boat" + }, + { + "id": "minecraft:birch_chest_boat" + }, + { + "id": "minecraft:jungle_chest_boat" + }, + { + "id": "minecraft:acacia_chest_boat" + }, + { + "id": "minecraft:dark_oak_chest_boat" + }, + { + "id": "minecraft:mangrove_chest_boat" + }, + { + "id": "minecraft:cherry_chest_boat" + }, + { + "id": "minecraft:bamboo_chest_raft" + }, + { + "id": "minecraft:rail", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OnJhaWwECQBuYW1lX2hhc2hUzmhUXYJDUQMKAG5ldHdvcmtfaWR+Sp6YCgYAc3RhdGVzAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:golden_rail", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmdvbGRlbl9yYWlsBAkAbmFtZV9oYXNoOoV5MaKipoUDCgBuZXR3b3JrX2lkfAcxLwoGAHN0YXRlcwENAHJhaWxfZGF0YV9iaXQAAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:detector_rail", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmRldGVjdG9yX3JhaWwECQBuYW1lX2hhc2gVUk31qOysUQMKAG5ldHdvcmtfaWRVW/aICgYAc3RhdGVzAQ0AcmFpbF9kYXRhX2JpdAADDgByYWlsX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:activator_rail", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmFjdGl2YXRvcl9yYWlsBAkAbmFtZV9oYXNosIL91qriCRkDCgBuZXR3b3JrX2lkZfckmwoGAHN0YXRlcwENAHJhaWxfZGF0YV9iaXQAAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:minecart" + }, + { + "id": "minecraft:chest_minecart" + }, + { + "id": "minecraft:hopper_minecart" + }, + { + "id": "minecraft:tnt_minecart" + }, + { + "id": "minecraft:redstone" + }, + { + "id": "minecraft:redstone_block", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZHN0b25lX2Jsb2NrBAkAbmFtZV9oYXNoRhULL0r8o0sDCgBuZXR3b3JrX2lklayOHgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:redstone_torch", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZHN0b25lX3RvcmNoBAkAbmFtZV9oYXNoizFRjpYMIDgDCgBuZXR3b3JrX2lkuHz7yAoGAHN0YXRlcwgWAHRvcmNoX2ZhY2luZ19kaXJlY3Rpb24HAHVua25vd24AAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:lever", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmxldmVyBAkAbmFtZV9oYXNoGMJeLJsUMLYDCgBuZXR3b3JrX2lkEF/GuAoGAHN0YXRlcwgPAGxldmVyX2RpcmVjdGlvbg4AZG93bl9lYXN0X3dlc3QBCABvcGVuX2JpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:wooden_button", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Ondvb2Rlbl9idXR0b24ECQBuYW1lX2hhc2hR7PgSTQt0sQMKAG5ldHdvcmtfaWSU07kYCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:spruce_button", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9idXR0b24ECQBuYW1lX2hhc2jBW9Z8aYE7YQMKAG5ldHdvcmtfaWTkUIGuCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:birch_button", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX2J1dHRvbgQJAG5hbWVfaGFzaJXYgGuSHbTwAwoAbmV0d29ya19pZGWp3yoKBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:jungle_button", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9idXR0b24ECQBuYW1lX2hhc2iCgNANcJs+BQMKAG5ldHdvcmtfaWT9fImWCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:acacia_button", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9idXR0b24ECQBuYW1lX2hhc2gVvmcT7LTO0wMKAG5ldHdvcmtfaWRQnxIJCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:dark_oak_button", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX2J1dHRvbgQJAG5hbWVfaGFzaIV10ZGGrCIEAwoAbmV0d29ya19pZN5vAmIKBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:mangrove_button", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX2J1dHRvbgQJAG5hbWVfaGFzaNzeYYKLgOzJAwoAbmV0d29ya19pZAFEGQ0KBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:cherry_button", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9idXR0b24ECQBuYW1lX2hhc2j2/IHjeAbUcwMKAG5ldHdvcmtfaWRJ1irQCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:bamboo_button", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19idXR0b24ECQBuYW1lX2hhc2j7AddMi+6nsgMKAG5ldHdvcmtfaWSa9w4/CgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:stone_button", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnN0b25lX2J1dHRvbgQJAG5hbWVfaGFzaM4ejMctmvohAwoAbmV0d29ya19pZMw+aC0KBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:crimson_button", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fYnV0dG9uBAkAbmFtZV9oYXNofnjYHaYIeWgDCgBuZXR3b3JrX2lk+n1vyQoGAHN0YXRlcwESAGJ1dHRvbl9wcmVzc2VkX2JpdAADEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:warped_button", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9idXR0b24ECQBuYW1lX2hhc2jwkV2EU6Cn1QMKAG5ldHdvcmtfaWTnHnk1CgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:polished_blackstone_button", + "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnV0dG9uBAkAbmFtZV9oYXNojmxzQKS0S/EDCgBuZXR3b3JrX2lkDtQ95woGAHN0YXRlcwESAGJ1dHRvbl9wcmVzc2VkX2JpdAADEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:tripwire_hook", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnRyaXB3aXJlX2hvb2sECQBuYW1lX2hhc2gQdp+oGZLNnAMKAG5ldHdvcmtfaWSy+1KJCgYAc3RhdGVzAQwAYXR0YWNoZWRfYml0AAMJAGRpcmVjdGlvbgAAAAABCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:wooden_pressure_plate", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0Ondvb2Rlbl9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaGkGs5kCuA74AwoAbmV0d29ya19pZDRzPNwKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:spruce_pressure_plate", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnNwcnVjZV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaNmwuq549fJKAwoAbmV0d29ya19pZLQMCw0KBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:birch_pressure_plate", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmJpcmNoX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNorQkT9kDdlTwDCgBuZXR3b3JrX2lkH0G97AoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:jungle_pressure_plate", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0Omp1bmdsZV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaJ7DcteCkb8/AwoAbmV0d29ya19pZLdPBSAKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:acacia_pressure_plate", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmFjYWNpYV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaC2frZtfoYqCAwoAbmV0d29ya19pZIDdI18KBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:dark_oak_pressure_plate", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmRhcmtfb2FrX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoHUCJsTy52pwDCgBuZXR3b3JrX2lkKpi8rAoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:mangrove_pressure_plate", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0Om1hbmdyb3ZlX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoiDsTfJaX100DCgBuZXR3b3JrX2lkuwWDyQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:cherry_pressure_plate", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmNoZXJyeV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaALMqYEZDUQHAwoAbmV0d29ya19pZPNT+r0KBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:bamboo_pressure_plate", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmJhbWJvb19wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaNvxJ7NIAaqlAwoAbmV0d29ya19pZIZ8XnYKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:crimson_pressure_plate", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmNyaW1zb25fcHJlc3N1cmVfcGxhdGUECQBuYW1lX2hhc2hqBDVDAd31/gMKAG5ldHdvcmtfaWRmV18LCgYAc3RhdGVzAw8AcmVkc3RvbmVfc2lnbmFsAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:warped_pressure_plate", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OndhcnBlZF9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaBxFoQksWtYUAwoAbmV0d29ya19pZJVRoIcKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:stone_pressure_plate", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnN0b25lX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNounJuTBUTrU8DCgBuZXR3b3JrX2lkjDydwQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:light_weighted_pressure_plate", + "block_state_b64": "CgAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X3dlaWdodGVkX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoOyOJkNxLtkEDCgBuZXR3b3JrX2lkrr2AjgoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:heavy_weighted_pressure_plate", + "block_state_b64": "CgAACAQAbmFtZScAbWluZWNyYWZ0OmhlYXZ5X3dlaWdodGVkX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoltgDmDvTajUDCgBuZXR3b3JrX2lkFxVKuQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:polished_blackstone_pressure_plate", + "block_state_b64": "CgAACAQAbmFtZSwAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfcHJlc3N1cmVfcGxhdGUECQBuYW1lX2hhc2h65Ci6/CeGqwMKAG5ldHdvcmtfaWTaSW5xCgYAc3RhdGVzAw8AcmVkc3RvbmVfc2lnbmFsAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:observer", + "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0Om9ic2VydmVyBAkAbmFtZV9oYXNoYhlh1lpmHTgDCgBuZXR3b3JrX2lkQEh55goGAHN0YXRlcwgaAG1pbmVjcmFmdDpmYWNpbmdfZGlyZWN0aW9uBABkb3duAQsAcG93ZXJlZF9iaXQAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:daylight_detector", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmRheWxpZ2h0X2RldGVjdG9yBAkAbmFtZV9oYXNoV0F0s7B7PVgDCgBuZXR3b3JrX2lkri5afQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:repeater" + }, + { + "id": "minecraft:comparator" + }, + { + "id": "minecraft:hopper" + }, + { + "id": "minecraft:dropper", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmRyb3BwZXIECQBuYW1lX2hhc2joXP7XqU0l3QMKAG5ldHdvcmtfaWQfQN6zCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgMAAAABDQB0cmlnZ2VyZWRfYml0AAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:dispenser", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmRpc3BlbnNlcgQJAG5hbWVfaGFzaP1RR+zAbYP2AwoAbmV0d29ya19pZGAayD0KBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAwAAAAENAHRyaWdnZXJlZF9iaXQAAAMHAHZlcnNpb24yHhQBAA==" + }, + { + "id": "minecraft:piston", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBpc3RvbgQJAG5hbWVfaGFzaDs3AFh1fL0uAwoAbmV0d29ya19pZLD/5XQKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAQAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:sticky_piston", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnN0aWNreV9waXN0b24ECQBuYW1lX2hhc2hPFJFJSiJ0ZQMKAG5ldHdvcmtfaWT/MzCJCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgEAAAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:tnt", + "block_state_b64": "CgAACAQAbmFtZQ0AbWluZWNyYWZ0OnRudAQJAG5hbWVfaGFzaEYOHwCvJH29AwoAbmV0d29ya19pZCGfjU4KBgBzdGF0ZXMBFABhbGxvd191bmRlcndhdGVyX2JpdAABCwBleHBsb2RlX2JpdAAAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:name_tag" + }, + { + "id": "minecraft:loom", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Omxvb20ECQBuYW1lX2hhc2i7DKjAXNq8TAMKAG5ldHdvcmtfaWR/49HXCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:banner" + }, + { + "id": "minecraft:banner", + "damage": 8 + }, + { + "id": "minecraft:banner", + "damage": 7 + }, + { + "id": "minecraft:banner", + "damage": 15 + }, + { + "id": "minecraft:banner", + "damage": 12 + }, + { + "id": "minecraft:banner", + "damage": 14 + }, + { + "id": "minecraft:banner", + "damage": 1 + }, + { + "id": "minecraft:banner", + "damage": 4 + }, + { + "id": "minecraft:banner", + "damage": 5 + }, + { + "id": "minecraft:banner", + "damage": 13 + }, + { + "id": "minecraft:banner", + "damage": 9 + }, + { + "id": "minecraft:banner", + "damage": 3 + }, + { + "id": "minecraft:banner", + "damage": 11 + }, + { + "id": "minecraft:banner", + "damage": 10 + }, + { + "id": "minecraft:banner", + "damage": 2 + }, + { + "id": "minecraft:banner", + "damage": 6 + }, + { + "id": "minecraft:banner", + "damage": 15, + "nbt_b64": "CgAAAwQAVHlwZQEAAAAA" + }, + { + "id": "minecraft:creeper_banner_pattern" + }, + { + "id": "minecraft:skull_banner_pattern" + }, + { + "id": "minecraft:flower_banner_pattern" + }, + { + "id": "minecraft:mojang_banner_pattern" + }, + { + "id": "minecraft:field_masoned_banner_pattern" + }, + { + "id": "minecraft:bordure_indented_banner_pattern" + }, + { + "id": "minecraft:piglin_banner_pattern" + }, + { + "id": "minecraft:globe_banner_pattern" + }, + { + "id": "minecraft:angler_pottery_sherd" + }, + { + "id": "minecraft:archer_pottery_sherd" + }, + { + "id": "minecraft:arms_up_pottery_sherd" + }, + { + "id": "minecraft:blade_pottery_sherd" + }, + { + "id": "minecraft:brewer_pottery_sherd" + }, + { + "id": "minecraft:burn_pottery_sherd" + }, + { + "id": "minecraft:danger_pottery_sherd" + }, + { + "id": "minecraft:explorer_pottery_sherd" + }, + { + "id": "minecraft:friend_pottery_sherd" + }, + { + "id": "minecraft:heart_pottery_sherd" + }, + { + "id": "minecraft:heartbreak_pottery_sherd" + }, + { + "id": "minecraft:howl_pottery_sherd" + }, + { + "id": "minecraft:miner_pottery_sherd" + }, + { + "id": "minecraft:mourner_pottery_sherd" + }, + { + "id": "minecraft:plenty_pottery_sherd" + }, + { + "id": "minecraft:prize_pottery_sherd" + }, + { + "id": "minecraft:sheaf_pottery_sherd" + }, + { + "id": "minecraft:shelter_pottery_sherd" + }, + { + "id": "minecraft:skull_pottery_sherd" + }, + { + "id": "minecraft:snort_pottery_sherd" + }, + { + "id": "minecraft:netherite_upgrade_smithing_template" + }, + { + "id": "minecraft:sentry_armor_trim_smithing_template" + }, + { + "id": "minecraft:vex_armor_trim_smithing_template" + }, + { + "id": "minecraft:wild_armor_trim_smithing_template" + }, + { + "id": "minecraft:coast_armor_trim_smithing_template" + }, + { + "id": "minecraft:dune_armor_trim_smithing_template" + }, + { + "id": "minecraft:wayfinder_armor_trim_smithing_template" + }, + { + "id": "minecraft:shaper_armor_trim_smithing_template" + }, + { + "id": "minecraft:raiser_armor_trim_smithing_template" + }, + { + "id": "minecraft:host_armor_trim_smithing_template" + }, + { + "id": "minecraft:ward_armor_trim_smithing_template" + }, + { + "id": "minecraft:silence_armor_trim_smithing_template" + }, + { + "id": "minecraft:tide_armor_trim_smithing_template" + }, + { + "id": "minecraft:snout_armor_trim_smithing_template" + }, + { + "id": "minecraft:rib_armor_trim_smithing_template" + }, + { + "id": "minecraft:eye_armor_trim_smithing_template" + }, + { + "id": "minecraft:spire_armor_trim_smithing_template" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwAAAAAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAABwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAIBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAHBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAPBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAMBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAOBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAABBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAEBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAFBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAANBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAJBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAADBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAALBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAKBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAACBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAGBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_star", + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yIR0d/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 8, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yUk9H/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 7, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yl52d/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 15, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9y8PDw/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 12, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9y2rM6/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 14, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yHYD5/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 1, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yJi6w/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 4, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yqkQ8/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 5, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yuDKJ/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 13, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yvU7H/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 9, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yqovz/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 3, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yMlSD/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 11, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yPdj+/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 10, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yH8eA/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 2, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yFnxe/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 6, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9ynJwW/wA=" + }, + { + "id": "minecraft:chain" + }, + { + "id": "minecraft:target", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnRhcmdldAQJAG5hbWVfaGFzaJc66SVbYlaxAwoAbmV0d29ya19pZPBozs0KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" + }, + { + "id": "minecraft:decorated_pot", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmRlY29yYXRlZF9wb3QECQBuYW1lX2hhc2jjQgckn8VTvwMKAG5ldHdvcmtfaWRwvkUUCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" + }, + { + "id": "minecraft:lodestone_compass" + }, + { + "id": "minecraft:wither_spawn_egg" + }, + { + "id": "minecraft:ender_dragon_spawn_egg" + } + ] +} \ No newline at end of file diff --git a/core/src/main/resources/bedrock/runtime_item_states.1_20_30.json b/core/src/main/resources/bedrock/runtime_item_states.1_20_30.json new file mode 100644 index 000000000..861b29c8a --- /dev/null +++ b/core/src/main/resources/bedrock/runtime_item_states.1_20_30.json @@ -0,0 +1,5570 @@ +[ + { + "name": "minecraft:acacia_boat", + "id": 381 + }, + { + "name": "minecraft:acacia_button", + "id": -140 + }, + { + "name": "minecraft:acacia_chest_boat", + "id": 649 + }, + { + "name": "minecraft:acacia_door", + "id": 563 + }, + { + "name": "minecraft:acacia_fence", + "id": -575 + }, + { + "name": "minecraft:acacia_fence_gate", + "id": 187 + }, + { + "name": "minecraft:acacia_hanging_sign", + "id": -504 + }, + { + "name": "minecraft:acacia_log", + "id": 162 + }, + { + "name": "minecraft:acacia_pressure_plate", + "id": -150 + }, + { + "name": "minecraft:acacia_sign", + "id": 586 + }, + { + "name": "minecraft:acacia_stairs", + "id": 163 + }, + { + "name": "minecraft:acacia_standing_sign", + "id": -190 + }, + { + "name": "minecraft:acacia_trapdoor", + "id": -145 + }, + { + "name": "minecraft:acacia_wall_sign", + "id": -191 + }, + { + "name": "minecraft:activator_rail", + "id": 126 + }, + { + "name": "minecraft:agent_spawn_egg", + "id": 489 + }, + { + "name": "minecraft:air", + "id": -158 + }, + { + "name": "minecraft:allay_spawn_egg", + "id": 638 + }, + { + "name": "minecraft:allow", + "id": 210 + }, + { + "name": "minecraft:amethyst_block", + "id": -327 + }, + { + "name": "minecraft:amethyst_cluster", + "id": -329 + }, + { + "name": "minecraft:amethyst_shard", + "id": 631 + }, + { + "name": "minecraft:ancient_debris", + "id": -271 + }, + { + "name": "minecraft:andesite_stairs", + "id": -171 + }, + { + "name": "minecraft:angler_pottery_sherd", + "id": 663 + }, + { + "name": "minecraft:anvil", + "id": 145 + }, + { + "name": "minecraft:apple", + "id": 257 + }, + { + "name": "minecraft:archer_pottery_sherd", + "id": 664 + }, + { + "name": "minecraft:armor_stand", + "id": 559 + }, + { + "name": "minecraft:arms_up_pottery_sherd", + "id": 665 + }, + { + "name": "minecraft:arrow", + "id": 303 + }, + { + "name": "minecraft:axolotl_bucket", + "id": 371 + }, + { + "name": "minecraft:axolotl_spawn_egg", + "id": 503 + }, + { + "name": "minecraft:azalea", + "id": -337 + }, + { + "name": "minecraft:azalea_leaves", + "id": -324 + }, + { + "name": "minecraft:azalea_leaves_flowered", + "id": -325 + }, + { + "name": "minecraft:baked_potato", + "id": 281 + }, + { + "name": "minecraft:balloon", + "id": 605 + }, + { + "name": "minecraft:bamboo", + "id": -163 + }, + { + "name": "minecraft:bamboo_block", + "id": -527 + }, + { + "name": "minecraft:bamboo_button", + "id": -511 + }, + { + "name": "minecraft:bamboo_chest_raft", + "id": 661 + }, + { + "name": "minecraft:bamboo_door", + "id": -517 + }, + { + "name": "minecraft:bamboo_double_slab", + "id": -521 + }, + { + "name": "minecraft:bamboo_fence", + "id": -515 + }, + { + "name": "minecraft:bamboo_fence_gate", + "id": -516 + }, + { + "name": "minecraft:bamboo_hanging_sign", + "id": -522 + }, + { + "name": "minecraft:bamboo_mosaic", + "id": -509 + }, + { + "name": "minecraft:bamboo_mosaic_double_slab", + "id": -525 + }, + { + "name": "minecraft:bamboo_mosaic_slab", + "id": -524 + }, + { + "name": "minecraft:bamboo_mosaic_stairs", + "id": -523 + }, + { + "name": "minecraft:bamboo_planks", + "id": -510 + }, + { + "name": "minecraft:bamboo_pressure_plate", + "id": -514 + }, + { + "name": "minecraft:bamboo_raft", + "id": 660 + }, + { + "name": "minecraft:bamboo_sapling", + "id": -164 + }, + { + "name": "minecraft:bamboo_sign", + "id": 659 + }, + { + "name": "minecraft:bamboo_slab", + "id": -513 + }, + { + "name": "minecraft:bamboo_stairs", + "id": -512 + }, + { + "name": "minecraft:bamboo_standing_sign", + "id": -518 + }, + { + "name": "minecraft:bamboo_trapdoor", + "id": -520 + }, + { + "name": "minecraft:bamboo_wall_sign", + "id": -519 + }, + { + "name": "minecraft:banner", + "id": 574 + }, + { + "name": "minecraft:banner_pattern", + "id": 716 + }, + { + "name": "minecraft:barrel", + "id": -203 + }, + { + "name": "minecraft:barrier", + "id": -161 + }, + { + "name": "minecraft:basalt", + "id": -234 + }, + { + "name": "minecraft:bat_spawn_egg", + "id": 455 + }, + { + "name": "minecraft:beacon", + "id": 138 + }, + { + "name": "minecraft:bed", + "id": 420 + }, + { + "name": "minecraft:bedrock", + "id": 7 + }, + { + "name": "minecraft:bee_nest", + "id": -218 + }, + { + "name": "minecraft:bee_spawn_egg", + "id": 496 + }, + { + "name": "minecraft:beef", + "id": 273 + }, + { + "name": "minecraft:beehive", + "id": -219 + }, + { + "name": "minecraft:beetroot", + "id": 285 + }, + { + "name": "minecraft:beetroot_seeds", + "id": 295 + }, + { + "name": "minecraft:beetroot_soup", + "id": 286 + }, + { + "name": "minecraft:bell", + "id": -206 + }, + { + "name": "minecraft:big_dripleaf", + "id": -323 + }, + { + "name": "minecraft:birch_boat", + "id": 378 + }, + { + "name": "minecraft:birch_button", + "id": -141 + }, + { + "name": "minecraft:birch_chest_boat", + "id": 646 + }, + { + "name": "minecraft:birch_door", + "id": 561 + }, + { + "name": "minecraft:birch_fence", + "id": -576 + }, + { + "name": "minecraft:birch_fence_gate", + "id": 184 + }, + { + "name": "minecraft:birch_hanging_sign", + "id": -502 + }, + { + "name": "minecraft:birch_log", + "id": -570 + }, + { + "name": "minecraft:birch_pressure_plate", + "id": -151 + }, + { + "name": "minecraft:birch_sign", + "id": 584 + }, + { + "name": "minecraft:birch_stairs", + "id": 135 + }, + { + "name": "minecraft:birch_standing_sign", + "id": -186 + }, + { + "name": "minecraft:birch_trapdoor", + "id": -146 + }, + { + "name": "minecraft:birch_wall_sign", + "id": -187 + }, + { + "name": "minecraft:black_candle", + "id": -428 + }, + { + "name": "minecraft:black_candle_cake", + "id": -445 + }, + { + "name": "minecraft:black_carpet", + "id": -611 + }, + { + "name": "minecraft:black_concrete", + "id": -642 + }, + { + "name": "minecraft:black_concrete_powder", + "id": -723 + }, + { + "name": "minecraft:black_dye", + "id": 397 + }, + { + "name": "minecraft:black_glazed_terracotta", + "id": 235 + }, + { + "name": "minecraft:black_shulker_box", + "id": -627 + }, + { + "name": "minecraft:black_stained_glass", + "id": -687 + }, + { + "name": "minecraft:black_stained_glass_pane", + "id": -657 + }, + { + "name": "minecraft:black_terracotta", + "id": -738 + }, + { + "name": "minecraft:black_wool", + "id": -554 + }, + { + "name": "minecraft:blackstone", + "id": -273 + }, + { + "name": "minecraft:blackstone_double_slab", + "id": -283 + }, + { + "name": "minecraft:blackstone_slab", + "id": -282 + }, + { + "name": "minecraft:blackstone_stairs", + "id": -276 + }, + { + "name": "minecraft:blackstone_wall", + "id": -277 + }, + { + "name": "minecraft:blade_pottery_sherd", + "id": 666 + }, + { + "name": "minecraft:blast_furnace", + "id": -196 + }, + { + "name": "minecraft:blaze_powder", + "id": 431 + }, + { + "name": "minecraft:blaze_rod", + "id": 425 + }, + { + "name": "minecraft:blaze_spawn_egg", + "id": 458 + }, + { + "name": "minecraft:bleach", + "id": 603 + }, + { + "name": "minecraft:blue_candle", + "id": -424 + }, + { + "name": "minecraft:blue_candle_cake", + "id": -441 + }, + { + "name": "minecraft:blue_carpet", + "id": -607 + }, + { + "name": "minecraft:blue_concrete", + "id": -638 + }, + { + "name": "minecraft:blue_concrete_powder", + "id": -719 + }, + { + "name": "minecraft:blue_dye", + "id": 401 + }, + { + "name": "minecraft:blue_glazed_terracotta", + "id": 231 + }, + { + "name": "minecraft:blue_ice", + "id": -11 + }, + { + "name": "minecraft:blue_shulker_box", + "id": -623 + }, + { + "name": "minecraft:blue_stained_glass", + "id": -683 + }, + { + "name": "minecraft:blue_stained_glass_pane", + "id": -653 + }, + { + "name": "minecraft:blue_terracotta", + "id": -734 + }, + { + "name": "minecraft:blue_wool", + "id": -563 + }, + { + "name": "minecraft:boat", + "id": 714 + }, + { + "name": "minecraft:bone", + "id": 417 + }, + { + "name": "minecraft:bone_block", + "id": 216 + }, + { + "name": "minecraft:bone_meal", + "id": 413 + }, + { + "name": "minecraft:book", + "id": 389 + }, + { + "name": "minecraft:bookshelf", + "id": 47 + }, + { + "name": "minecraft:border_block", + "id": 212 + }, + { + "name": "minecraft:bordure_indented_banner_pattern", + "id": 593 + }, + { + "name": "minecraft:bow", + "id": 302 + }, + { + "name": "minecraft:bowl", + "id": 323 + }, + { + "name": "minecraft:brain_coral", + "id": -581 + }, + { + "name": "minecraft:bread", + "id": 261 + }, + { + "name": "minecraft:brewer_pottery_sherd", + "id": 667 + }, + { + "name": "minecraft:brewing_stand", + "id": 433 + }, + { + "name": "minecraft:brick", + "id": 385 + }, + { + "name": "minecraft:brick_block", + "id": 45 + }, + { + "name": "minecraft:brick_stairs", + "id": 108 + }, + { + "name": "minecraft:brown_candle", + "id": -425 + }, + { + "name": "minecraft:brown_candle_cake", + "id": -442 + }, + { + "name": "minecraft:brown_carpet", + "id": -608 + }, + { + "name": "minecraft:brown_concrete", + "id": -639 + }, + { + "name": "minecraft:brown_concrete_powder", + "id": -720 + }, + { + "name": "minecraft:brown_dye", + "id": 400 + }, + { + "name": "minecraft:brown_glazed_terracotta", + "id": 232 + }, + { + "name": "minecraft:brown_mushroom", + "id": 39 + }, + { + "name": "minecraft:brown_mushroom_block", + "id": 99 + }, + { + "name": "minecraft:brown_shulker_box", + "id": -624 + }, + { + "name": "minecraft:brown_stained_glass", + "id": -684 + }, + { + "name": "minecraft:brown_stained_glass_pane", + "id": -654 + }, + { + "name": "minecraft:brown_terracotta", + "id": -735 + }, + { + "name": "minecraft:brown_wool", + "id": -555 + }, + { + "name": "minecraft:brush", + "id": 683 + }, + { + "name": "minecraft:bubble_column", + "id": -160 + }, + { + "name": "minecraft:bubble_coral", + "id": -582 + }, + { + "name": "minecraft:bucket", + "id": 362 + }, + { + "name": "minecraft:budding_amethyst", + "id": -328 + }, + { + "name": "minecraft:burn_pottery_sherd", + "id": 668 + }, + { + "name": "minecraft:cactus", + "id": 81 + }, + { + "name": "minecraft:cake", + "id": 419 + }, + { + "name": "minecraft:calcite", + "id": -326 + }, + { + "name": "minecraft:calibrated_sculk_sensor", + "id": -580 + }, + { + "name": "minecraft:camel_spawn_egg", + "id": 662 + }, + { + "name": "minecraft:camera", + "id": 600 + }, + { + "name": "minecraft:campfire", + "id": 596 + }, + { + "name": "minecraft:candle", + "id": -412 + }, + { + "name": "minecraft:candle_cake", + "id": -429 + }, + { + "name": "minecraft:carpet", + "id": 704 + }, + { + "name": "minecraft:carrot", + "id": 279 + }, + { + "name": "minecraft:carrot_on_a_stick", + "id": 524 + }, + { + "name": "minecraft:carrots", + "id": 141 + }, + { + "name": "minecraft:cartography_table", + "id": -200 + }, + { + "name": "minecraft:carved_pumpkin", + "id": -155 + }, + { + "name": "minecraft:cat_spawn_egg", + "id": 490 + }, + { + "name": "minecraft:cauldron", + "id": 434 + }, + { + "name": "minecraft:cave_spider_spawn_egg", + "id": 459 + }, + { + "name": "minecraft:cave_vines", + "id": -322 + }, + { + "name": "minecraft:cave_vines_body_with_berries", + "id": -375 + }, + { + "name": "minecraft:cave_vines_head_with_berries", + "id": -376 + }, + { + "name": "minecraft:chain", + "id": 626 + }, + { + "name": "minecraft:chain_command_block", + "id": 189 + }, + { + "name": "minecraft:chainmail_boots", + "id": 344 + }, + { + "name": "minecraft:chainmail_chestplate", + "id": 342 + }, + { + "name": "minecraft:chainmail_helmet", + "id": 341 + }, + { + "name": "minecraft:chainmail_leggings", + "id": 343 + }, + { + "name": "minecraft:charcoal", + "id": 305 + }, + { + "name": "minecraft:chemical_heat", + "id": 192 + }, + { + "name": "minecraft:chemistry_table", + "id": 238 + }, + { + "name": "minecraft:cherry_boat", + "id": 656 + }, + { + "name": "minecraft:cherry_button", + "id": -530 + }, + { + "name": "minecraft:cherry_chest_boat", + "id": 657 + }, + { + "name": "minecraft:cherry_door", + "id": -531 + }, + { + "name": "minecraft:cherry_double_slab", + "id": -540 + }, + { + "name": "minecraft:cherry_fence", + "id": -532 + }, + { + "name": "minecraft:cherry_fence_gate", + "id": -533 + }, + { + "name": "minecraft:cherry_hanging_sign", + "id": -534 + }, + { + "name": "minecraft:cherry_leaves", + "id": -548 + }, + { + "name": "minecraft:cherry_log", + "id": -536 + }, + { + "name": "minecraft:cherry_planks", + "id": -537 + }, + { + "name": "minecraft:cherry_pressure_plate", + "id": -538 + }, + { + "name": "minecraft:cherry_sapling", + "id": -547 + }, + { + "name": "minecraft:cherry_sign", + "id": 658 + }, + { + "name": "minecraft:cherry_slab", + "id": -539 + }, + { + "name": "minecraft:cherry_stairs", + "id": -541 + }, + { + "name": "minecraft:cherry_standing_sign", + "id": -542 + }, + { + "name": "minecraft:cherry_trapdoor", + "id": -543 + }, + { + "name": "minecraft:cherry_wall_sign", + "id": -544 + }, + { + "name": "minecraft:cherry_wood", + "id": -546 + }, + { + "name": "minecraft:chest", + "id": 54 + }, + { + "name": "minecraft:chest_boat", + "id": 652 + }, + { + "name": "minecraft:chest_minecart", + "id": 391 + }, + { + "name": "minecraft:chicken", + "id": 275 + }, + { + "name": "minecraft:chicken_spawn_egg", + "id": 437 + }, + { + "name": "minecraft:chiseled_bookshelf", + "id": -526 + }, + { + "name": "minecraft:chiseled_deepslate", + "id": -395 + }, + { + "name": "minecraft:chiseled_nether_bricks", + "id": -302 + }, + { + "name": "minecraft:chiseled_polished_blackstone", + "id": -279 + }, + { + "name": "minecraft:chorus_flower", + "id": 200 + }, + { + "name": "minecraft:chorus_fruit", + "id": 565 + }, + { + "name": "minecraft:chorus_plant", + "id": 240 + }, + { + "name": "minecraft:clay", + "id": 82 + }, + { + "name": "minecraft:clay_ball", + "id": 386 + }, + { + "name": "minecraft:client_request_placeholder_block", + "id": -465 + }, + { + "name": "minecraft:clock", + "id": 395 + }, + { + "name": "minecraft:coal", + "id": 304 + }, + { + "name": "minecraft:coal_block", + "id": 173 + }, + { + "name": "minecraft:coal_ore", + "id": 16 + }, + { + "name": "minecraft:coast_armor_trim_smithing_template", + "id": 687 + }, + { + "name": "minecraft:cobbled_deepslate", + "id": -379 + }, + { + "name": "minecraft:cobbled_deepslate_double_slab", + "id": -396 + }, + { + "name": "minecraft:cobbled_deepslate_slab", + "id": -380 + }, + { + "name": "minecraft:cobbled_deepslate_stairs", + "id": -381 + }, + { + "name": "minecraft:cobbled_deepslate_wall", + "id": -382 + }, + { + "name": "minecraft:cobblestone", + "id": 4 + }, + { + "name": "minecraft:cobblestone_wall", + "id": 139 + }, + { + "name": "minecraft:cocoa", + "id": 127 + }, + { + "name": "minecraft:cocoa_beans", + "id": 414 + }, + { + "name": "minecraft:cod", + "id": 264 + }, + { + "name": "minecraft:cod_bucket", + "id": 366 + }, + { + "name": "minecraft:cod_spawn_egg", + "id": 482 + }, + { + "name": "minecraft:colored_torch_bp", + "id": 204 + }, + { + "name": "minecraft:colored_torch_rg", + "id": 202 + }, + { + "name": "minecraft:command_block", + "id": 137 + }, + { + "name": "minecraft:command_block_minecart", + "id": 570 + }, + { + "name": "minecraft:comparator", + "id": 529 + }, + { + "name": "minecraft:compass", + "id": 393 + }, + { + "name": "minecraft:composter", + "id": -213 + }, + { + "name": "minecraft:compound", + "id": 601 + }, + { + "name": "minecraft:concrete", + "id": 709 + }, + { + "name": "minecraft:concrete_powder", + "id": 710 + }, + { + "name": "minecraft:conduit", + "id": -157 + }, + { + "name": "minecraft:cooked_beef", + "id": 274 + }, + { + "name": "minecraft:cooked_chicken", + "id": 276 + }, + { + "name": "minecraft:cooked_cod", + "id": 268 + }, + { + "name": "minecraft:cooked_mutton", + "id": 558 + }, + { + "name": "minecraft:cooked_porkchop", + "id": 263 + }, + { + "name": "minecraft:cooked_rabbit", + "id": 289 + }, + { + "name": "minecraft:cooked_salmon", + "id": 269 + }, + { + "name": "minecraft:cookie", + "id": 271 + }, + { + "name": "minecraft:copper_block", + "id": -340 + }, + { + "name": "minecraft:copper_ingot", + "id": 511 + }, + { + "name": "minecraft:copper_ore", + "id": -311 + }, + { + "name": "minecraft:coral", + "id": 707 + }, + { + "name": "minecraft:coral_block", + "id": -132 + }, + { + "name": "minecraft:coral_fan", + "id": -133 + }, + { + "name": "minecraft:coral_fan_dead", + "id": -134 + }, + { + "name": "minecraft:coral_fan_hang", + "id": -135 + }, + { + "name": "minecraft:coral_fan_hang2", + "id": -136 + }, + { + "name": "minecraft:coral_fan_hang3", + "id": -137 + }, + { + "name": "minecraft:cow_spawn_egg", + "id": 438 + }, + { + "name": "minecraft:cracked_deepslate_bricks", + "id": -410 + }, + { + "name": "minecraft:cracked_deepslate_tiles", + "id": -409 + }, + { + "name": "minecraft:cracked_nether_bricks", + "id": -303 + }, + { + "name": "minecraft:cracked_polished_blackstone_bricks", + "id": -280 + }, + { + "name": "minecraft:crafting_table", + "id": 58 + }, + { + "name": "minecraft:creeper_banner_pattern", + "id": 589 + }, + { + "name": "minecraft:creeper_spawn_egg", + "id": 443 + }, + { + "name": "minecraft:crimson_button", + "id": -260 + }, + { + "name": "minecraft:crimson_door", + "id": 623 + }, + { + "name": "minecraft:crimson_double_slab", + "id": -266 + }, + { + "name": "minecraft:crimson_fence", + "id": -256 + }, + { + "name": "minecraft:crimson_fence_gate", + "id": -258 + }, + { + "name": "minecraft:crimson_fungus", + "id": -228 + }, + { + "name": "minecraft:crimson_hanging_sign", + "id": -506 + }, + { + "name": "minecraft:crimson_hyphae", + "id": -299 + }, + { + "name": "minecraft:crimson_nylium", + "id": -232 + }, + { + "name": "minecraft:crimson_planks", + "id": -242 + }, + { + "name": "minecraft:crimson_pressure_plate", + "id": -262 + }, + { + "name": "minecraft:crimson_roots", + "id": -223 + }, + { + "name": "minecraft:crimson_sign", + "id": 621 + }, + { + "name": "minecraft:crimson_slab", + "id": -264 + }, + { + "name": "minecraft:crimson_stairs", + "id": -254 + }, + { + "name": "minecraft:crimson_standing_sign", + "id": -250 + }, + { + "name": "minecraft:crimson_stem", + "id": -225 + }, + { + "name": "minecraft:crimson_trapdoor", + "id": -246 + }, + { + "name": "minecraft:crimson_wall_sign", + "id": -252 + }, + { + "name": "minecraft:crossbow", + "id": 582 + }, + { + "name": "minecraft:crying_obsidian", + "id": -289 + }, + { + "name": "minecraft:cut_copper", + "id": -347 + }, + { + "name": "minecraft:cut_copper_slab", + "id": -361 + }, + { + "name": "minecraft:cut_copper_stairs", + "id": -354 + }, + { + "name": "minecraft:cyan_candle", + "id": -422 + }, + { + "name": "minecraft:cyan_candle_cake", + "id": -439 + }, + { + "name": "minecraft:cyan_carpet", + "id": -605 + }, + { + "name": "minecraft:cyan_concrete", + "id": -636 + }, + { + "name": "minecraft:cyan_concrete_powder", + "id": -717 + }, + { + "name": "minecraft:cyan_dye", + "id": 403 + }, + { + "name": "minecraft:cyan_glazed_terracotta", + "id": 229 + }, + { + "name": "minecraft:cyan_shulker_box", + "id": -621 + }, + { + "name": "minecraft:cyan_stained_glass", + "id": -681 + }, + { + "name": "minecraft:cyan_stained_glass_pane", + "id": -651 + }, + { + "name": "minecraft:cyan_terracotta", + "id": -732 + }, + { + "name": "minecraft:cyan_wool", + "id": -561 + }, + { + "name": "minecraft:danger_pottery_sherd", + "id": 669 + }, + { + "name": "minecraft:dark_oak_boat", + "id": 382 + }, + { + "name": "minecraft:dark_oak_button", + "id": -142 + }, + { + "name": "minecraft:dark_oak_chest_boat", + "id": 650 + }, + { + "name": "minecraft:dark_oak_door", + "id": 564 + }, + { + "name": "minecraft:dark_oak_fence", + "id": -577 + }, + { + "name": "minecraft:dark_oak_fence_gate", + "id": 186 + }, + { + "name": "minecraft:dark_oak_hanging_sign", + "id": -505 + }, + { + "name": "minecraft:dark_oak_log", + "id": -572 + }, + { + "name": "minecraft:dark_oak_pressure_plate", + "id": -152 + }, + { + "name": "minecraft:dark_oak_sign", + "id": 587 + }, + { + "name": "minecraft:dark_oak_stairs", + "id": 164 + }, + { + "name": "minecraft:dark_oak_trapdoor", + "id": -147 + }, + { + "name": "minecraft:dark_prismarine_stairs", + "id": -3 + }, + { + "name": "minecraft:darkoak_standing_sign", + "id": -192 + }, + { + "name": "minecraft:darkoak_wall_sign", + "id": -193 + }, + { + "name": "minecraft:daylight_detector", + "id": 151 + }, + { + "name": "minecraft:daylight_detector_inverted", + "id": 178 + }, + { + "name": "minecraft:dead_brain_coral", + "id": -586 + }, + { + "name": "minecraft:dead_bubble_coral", + "id": -587 + }, + { + "name": "minecraft:dead_fire_coral", + "id": -588 + }, + { + "name": "minecraft:dead_horn_coral", + "id": -589 + }, + { + "name": "minecraft:dead_tube_coral", + "id": -585 + }, + { + "name": "minecraft:deadbush", + "id": 32 + }, + { + "name": "minecraft:decorated_pot", + "id": -551 + }, + { + "name": "minecraft:deepslate", + "id": -378 + }, + { + "name": "minecraft:deepslate_brick_double_slab", + "id": -399 + }, + { + "name": "minecraft:deepslate_brick_slab", + "id": -392 + }, + { + "name": "minecraft:deepslate_brick_stairs", + "id": -393 + }, + { + "name": "minecraft:deepslate_brick_wall", + "id": -394 + }, + { + "name": "minecraft:deepslate_bricks", + "id": -391 + }, + { + "name": "minecraft:deepslate_coal_ore", + "id": -406 + }, + { + "name": "minecraft:deepslate_copper_ore", + "id": -408 + }, + { + "name": "minecraft:deepslate_diamond_ore", + "id": -405 + }, + { + "name": "minecraft:deepslate_emerald_ore", + "id": -407 + }, + { + "name": "minecraft:deepslate_gold_ore", + "id": -402 + }, + { + "name": "minecraft:deepslate_iron_ore", + "id": -401 + }, + { + "name": "minecraft:deepslate_lapis_ore", + "id": -400 + }, + { + "name": "minecraft:deepslate_redstone_ore", + "id": -403 + }, + { + "name": "minecraft:deepslate_tile_double_slab", + "id": -398 + }, + { + "name": "minecraft:deepslate_tile_slab", + "id": -388 + }, + { + "name": "minecraft:deepslate_tile_stairs", + "id": -389 + }, + { + "name": "minecraft:deepslate_tile_wall", + "id": -390 + }, + { + "name": "minecraft:deepslate_tiles", + "id": -387 + }, + { + "name": "minecraft:deny", + "id": 211 + }, + { + "name": "minecraft:detector_rail", + "id": 28 + }, + { + "name": "minecraft:diamond", + "id": 306 + }, + { + "name": "minecraft:diamond_axe", + "id": 321 + }, + { + "name": "minecraft:diamond_block", + "id": 57 + }, + { + "name": "minecraft:diamond_boots", + "id": 352 + }, + { + "name": "minecraft:diamond_chestplate", + "id": 350 + }, + { + "name": "minecraft:diamond_helmet", + "id": 349 + }, + { + "name": "minecraft:diamond_hoe", + "id": 334 + }, + { + "name": "minecraft:diamond_horse_armor", + "id": 540 + }, + { + "name": "minecraft:diamond_leggings", + "id": 351 + }, + { + "name": "minecraft:diamond_ore", + "id": 56 + }, + { + "name": "minecraft:diamond_pickaxe", + "id": 320 + }, + { + "name": "minecraft:diamond_shovel", + "id": 319 + }, + { + "name": "minecraft:diamond_sword", + "id": 318 + }, + { + "name": "minecraft:diorite_stairs", + "id": -170 + }, + { + "name": "minecraft:dirt", + "id": 3 + }, + { + "name": "minecraft:dirt_with_roots", + "id": -318 + }, + { + "name": "minecraft:disc_fragment_5", + "id": 644 + }, + { + "name": "minecraft:dispenser", + "id": 23 + }, + { + "name": "minecraft:dolphin_spawn_egg", + "id": 486 + }, + { + "name": "minecraft:donkey_spawn_egg", + "id": 467 + }, + { + "name": "minecraft:double_cut_copper_slab", + "id": -368 + }, + { + "name": "minecraft:double_plant", + "id": 175 + }, + { + "name": "minecraft:double_stone_block_slab", + "id": 43 + }, + { + "name": "minecraft:double_stone_block_slab2", + "id": 181 + }, + { + "name": "minecraft:double_stone_block_slab3", + "id": -167 + }, + { + "name": "minecraft:double_stone_block_slab4", + "id": -168 + }, + { + "name": "minecraft:double_wooden_slab", + "id": 157 + }, + { + "name": "minecraft:dragon_breath", + "id": 567 + }, + { + "name": "minecraft:dragon_egg", + "id": 122 + }, + { + "name": "minecraft:dried_kelp", + "id": 270 + }, + { + "name": "minecraft:dried_kelp_block", + "id": -139 + }, + { + "name": "minecraft:dripstone_block", + "id": -317 + }, + { + "name": "minecraft:dropper", + "id": 125 + }, + { + "name": "minecraft:drowned_spawn_egg", + "id": 485 + }, + { + "name": "minecraft:dune_armor_trim_smithing_template", + "id": 686 + }, + { + "name": "minecraft:dye", + "id": 715 + }, + { + "name": "minecraft:echo_shard", + "id": 654 + }, + { + "name": "minecraft:egg", + "id": 392 + }, + { + "name": "minecraft:elder_guardian_spawn_egg", + "id": 473 + }, + { + "name": "minecraft:element_0", + "id": 36 + }, + { + "name": "minecraft:element_1", + "id": -12 + }, + { + "name": "minecraft:element_10", + "id": -21 + }, + { + "name": "minecraft:element_100", + "id": -111 + }, + { + "name": "minecraft:element_101", + "id": -112 + }, + { + "name": "minecraft:element_102", + "id": -113 + }, + { + "name": "minecraft:element_103", + "id": -114 + }, + { + "name": "minecraft:element_104", + "id": -115 + }, + { + "name": "minecraft:element_105", + "id": -116 + }, + { + "name": "minecraft:element_106", + "id": -117 + }, + { + "name": "minecraft:element_107", + "id": -118 + }, + { + "name": "minecraft:element_108", + "id": -119 + }, + { + "name": "minecraft:element_109", + "id": -120 + }, + { + "name": "minecraft:element_11", + "id": -22 + }, + { + "name": "minecraft:element_110", + "id": -121 + }, + { + "name": "minecraft:element_111", + "id": -122 + }, + { + "name": "minecraft:element_112", + "id": -123 + }, + { + "name": "minecraft:element_113", + "id": -124 + }, + { + "name": "minecraft:element_114", + "id": -125 + }, + { + "name": "minecraft:element_115", + "id": -126 + }, + { + "name": "minecraft:element_116", + "id": -127 + }, + { + "name": "minecraft:element_117", + "id": -128 + }, + { + "name": "minecraft:element_118", + "id": -129 + }, + { + "name": "minecraft:element_12", + "id": -23 + }, + { + "name": "minecraft:element_13", + "id": -24 + }, + { + "name": "minecraft:element_14", + "id": -25 + }, + { + "name": "minecraft:element_15", + "id": -26 + }, + { + "name": "minecraft:element_16", + "id": -27 + }, + { + "name": "minecraft:element_17", + "id": -28 + }, + { + "name": "minecraft:element_18", + "id": -29 + }, + { + "name": "minecraft:element_19", + "id": -30 + }, + { + "name": "minecraft:element_2", + "id": -13 + }, + { + "name": "minecraft:element_20", + "id": -31 + }, + { + "name": "minecraft:element_21", + "id": -32 + }, + { + "name": "minecraft:element_22", + "id": -33 + }, + { + "name": "minecraft:element_23", + "id": -34 + }, + { + "name": "minecraft:element_24", + "id": -35 + }, + { + "name": "minecraft:element_25", + "id": -36 + }, + { + "name": "minecraft:element_26", + "id": -37 + }, + { + "name": "minecraft:element_27", + "id": -38 + }, + { + "name": "minecraft:element_28", + "id": -39 + }, + { + "name": "minecraft:element_29", + "id": -40 + }, + { + "name": "minecraft:element_3", + "id": -14 + }, + { + "name": "minecraft:element_30", + "id": -41 + }, + { + "name": "minecraft:element_31", + "id": -42 + }, + { + "name": "minecraft:element_32", + "id": -43 + }, + { + "name": "minecraft:element_33", + "id": -44 + }, + { + "name": "minecraft:element_34", + "id": -45 + }, + { + "name": "minecraft:element_35", + "id": -46 + }, + { + "name": "minecraft:element_36", + "id": -47 + }, + { + "name": "minecraft:element_37", + "id": -48 + }, + { + "name": "minecraft:element_38", + "id": -49 + }, + { + "name": "minecraft:element_39", + "id": -50 + }, + { + "name": "minecraft:element_4", + "id": -15 + }, + { + "name": "minecraft:element_40", + "id": -51 + }, + { + "name": "minecraft:element_41", + "id": -52 + }, + { + "name": "minecraft:element_42", + "id": -53 + }, + { + "name": "minecraft:element_43", + "id": -54 + }, + { + "name": "minecraft:element_44", + "id": -55 + }, + { + "name": "minecraft:element_45", + "id": -56 + }, + { + "name": "minecraft:element_46", + "id": -57 + }, + { + "name": "minecraft:element_47", + "id": -58 + }, + { + "name": "minecraft:element_48", + "id": -59 + }, + { + "name": "minecraft:element_49", + "id": -60 + }, + { + "name": "minecraft:element_5", + "id": -16 + }, + { + "name": "minecraft:element_50", + "id": -61 + }, + { + "name": "minecraft:element_51", + "id": -62 + }, + { + "name": "minecraft:element_52", + "id": -63 + }, + { + "name": "minecraft:element_53", + "id": -64 + }, + { + "name": "minecraft:element_54", + "id": -65 + }, + { + "name": "minecraft:element_55", + "id": -66 + }, + { + "name": "minecraft:element_56", + "id": -67 + }, + { + "name": "minecraft:element_57", + "id": -68 + }, + { + "name": "minecraft:element_58", + "id": -69 + }, + { + "name": "minecraft:element_59", + "id": -70 + }, + { + "name": "minecraft:element_6", + "id": -17 + }, + { + "name": "minecraft:element_60", + "id": -71 + }, + { + "name": "minecraft:element_61", + "id": -72 + }, + { + "name": "minecraft:element_62", + "id": -73 + }, + { + "name": "minecraft:element_63", + "id": -74 + }, + { + "name": "minecraft:element_64", + "id": -75 + }, + { + "name": "minecraft:element_65", + "id": -76 + }, + { + "name": "minecraft:element_66", + "id": -77 + }, + { + "name": "minecraft:element_67", + "id": -78 + }, + { + "name": "minecraft:element_68", + "id": -79 + }, + { + "name": "minecraft:element_69", + "id": -80 + }, + { + "name": "minecraft:element_7", + "id": -18 + }, + { + "name": "minecraft:element_70", + "id": -81 + }, + { + "name": "minecraft:element_71", + "id": -82 + }, + { + "name": "minecraft:element_72", + "id": -83 + }, + { + "name": "minecraft:element_73", + "id": -84 + }, + { + "name": "minecraft:element_74", + "id": -85 + }, + { + "name": "minecraft:element_75", + "id": -86 + }, + { + "name": "minecraft:element_76", + "id": -87 + }, + { + "name": "minecraft:element_77", + "id": -88 + }, + { + "name": "minecraft:element_78", + "id": -89 + }, + { + "name": "minecraft:element_79", + "id": -90 + }, + { + "name": "minecraft:element_8", + "id": -19 + }, + { + "name": "minecraft:element_80", + "id": -91 + }, + { + "name": "minecraft:element_81", + "id": -92 + }, + { + "name": "minecraft:element_82", + "id": -93 + }, + { + "name": "minecraft:element_83", + "id": -94 + }, + { + "name": "minecraft:element_84", + "id": -95 + }, + { + "name": "minecraft:element_85", + "id": -96 + }, + { + "name": "minecraft:element_86", + "id": -97 + }, + { + "name": "minecraft:element_87", + "id": -98 + }, + { + "name": "minecraft:element_88", + "id": -99 + }, + { + "name": "minecraft:element_89", + "id": -100 + }, + { + "name": "minecraft:element_9", + "id": -20 + }, + { + "name": "minecraft:element_90", + "id": -101 + }, + { + "name": "minecraft:element_91", + "id": -102 + }, + { + "name": "minecraft:element_92", + "id": -103 + }, + { + "name": "minecraft:element_93", + "id": -104 + }, + { + "name": "minecraft:element_94", + "id": -105 + }, + { + "name": "minecraft:element_95", + "id": -106 + }, + { + "name": "minecraft:element_96", + "id": -107 + }, + { + "name": "minecraft:element_97", + "id": -108 + }, + { + "name": "minecraft:element_98", + "id": -109 + }, + { + "name": "minecraft:element_99", + "id": -110 + }, + { + "name": "minecraft:elytra", + "id": 571 + }, + { + "name": "minecraft:emerald", + "id": 519 + }, + { + "name": "minecraft:emerald_block", + "id": 133 + }, + { + "name": "minecraft:emerald_ore", + "id": 129 + }, + { + "name": "minecraft:empty_map", + "id": 522 + }, + { + "name": "minecraft:enchanted_book", + "id": 528 + }, + { + "name": "minecraft:enchanted_golden_apple", + "id": 259 + }, + { + "name": "minecraft:enchanting_table", + "id": 116 + }, + { + "name": "minecraft:end_brick_stairs", + "id": -178 + }, + { + "name": "minecraft:end_bricks", + "id": 206 + }, + { + "name": "minecraft:end_crystal", + "id": 718 + }, + { + "name": "minecraft:end_gateway", + "id": 209 + }, + { + "name": "minecraft:end_portal", + "id": 119 + }, + { + "name": "minecraft:end_portal_frame", + "id": 120 + }, + { + "name": "minecraft:end_rod", + "id": 208 + }, + { + "name": "minecraft:end_stone", + "id": 121 + }, + { + "name": "minecraft:ender_chest", + "id": 130 + }, + { + "name": "minecraft:ender_dragon_spawn_egg", + "id": 508 + }, + { + "name": "minecraft:ender_eye", + "id": 435 + }, + { + "name": "minecraft:ender_pearl", + "id": 424 + }, + { + "name": "minecraft:enderman_spawn_egg", + "id": 444 + }, + { + "name": "minecraft:endermite_spawn_egg", + "id": 462 + }, + { + "name": "minecraft:evoker_spawn_egg", + "id": 477 + }, + { + "name": "minecraft:experience_bottle", + "id": 515 + }, + { + "name": "minecraft:explorer_pottery_sherd", + "id": 670 + }, + { + "name": "minecraft:exposed_copper", + "id": -341 + }, + { + "name": "minecraft:exposed_cut_copper", + "id": -348 + }, + { + "name": "minecraft:exposed_cut_copper_slab", + "id": -362 + }, + { + "name": "minecraft:exposed_cut_copper_stairs", + "id": -355 + }, + { + "name": "minecraft:exposed_double_cut_copper_slab", + "id": -369 + }, + { + "name": "minecraft:eye_armor_trim_smithing_template", + "id": 690 + }, + { + "name": "minecraft:farmland", + "id": 60 + }, + { + "name": "minecraft:feather", + "id": 329 + }, + { + "name": "minecraft:fence", + "id": 706 + }, + { + "name": "minecraft:fence_gate", + "id": 107 + }, + { + "name": "minecraft:fermented_spider_eye", + "id": 430 + }, + { + "name": "minecraft:field_masoned_banner_pattern", + "id": 592 + }, + { + "name": "minecraft:filled_map", + "id": 422 + }, + { + "name": "minecraft:fire", + "id": 51 + }, + { + "name": "minecraft:fire_charge", + "id": 516 + }, + { + "name": "minecraft:fire_coral", + "id": -583 + }, + { + "name": "minecraft:firework_rocket", + "id": 526 + }, + { + "name": "minecraft:firework_star", + "id": 527 + }, + { + "name": "minecraft:fishing_rod", + "id": 394 + }, + { + "name": "minecraft:fletching_table", + "id": -201 + }, + { + "name": "minecraft:flint", + "id": 358 + }, + { + "name": "minecraft:flint_and_steel", + "id": 301 + }, + { + "name": "minecraft:flower_banner_pattern", + "id": 588 + }, + { + "name": "minecraft:flower_pot", + "id": 521 + }, + { + "name": "minecraft:flowering_azalea", + "id": -338 + }, + { + "name": "minecraft:flowing_lava", + "id": 10 + }, + { + "name": "minecraft:flowing_water", + "id": 8 + }, + { + "name": "minecraft:fox_spawn_egg", + "id": 492 + }, + { + "name": "minecraft:frame", + "id": 520 + }, + { + "name": "minecraft:friend_pottery_sherd", + "id": 671 + }, + { + "name": "minecraft:frog_spawn", + "id": -468 + }, + { + "name": "minecraft:frog_spawn_egg", + "id": 635 + }, + { + "name": "minecraft:frosted_ice", + "id": 207 + }, + { + "name": "minecraft:furnace", + "id": 61 + }, + { + "name": "minecraft:ghast_spawn_egg", + "id": 456 + }, + { + "name": "minecraft:ghast_tear", + "id": 426 + }, + { + "name": "minecraft:gilded_blackstone", + "id": -281 + }, + { + "name": "minecraft:glass", + "id": 20 + }, + { + "name": "minecraft:glass_bottle", + "id": 429 + }, + { + "name": "minecraft:glass_pane", + "id": 102 + }, + { + "name": "minecraft:glistering_melon_slice", + "id": 436 + }, + { + "name": "minecraft:globe_banner_pattern", + "id": 595 + }, + { + "name": "minecraft:glow_berries", + "id": 719 + }, + { + "name": "minecraft:glow_frame", + "id": 630 + }, + { + "name": "minecraft:glow_ink_sac", + "id": 510 + }, + { + "name": "minecraft:glow_lichen", + "id": -411 + }, + { + "name": "minecraft:glow_squid_spawn_egg", + "id": 505 + }, + { + "name": "minecraft:glow_stick", + "id": 608 + }, + { + "name": "minecraft:glowingobsidian", + "id": 246 + }, + { + "name": "minecraft:glowstone", + "id": 89 + }, + { + "name": "minecraft:glowstone_dust", + "id": 396 + }, + { + "name": "minecraft:goat_horn", + "id": 634 + }, + { + "name": "minecraft:goat_spawn_egg", + "id": 504 + }, + { + "name": "minecraft:gold_block", + "id": 41 + }, + { + "name": "minecraft:gold_ingot", + "id": 308 + }, + { + "name": "minecraft:gold_nugget", + "id": 427 + }, + { + "name": "minecraft:gold_ore", + "id": 14 + }, + { + "name": "minecraft:golden_apple", + "id": 258 + }, + { + "name": "minecraft:golden_axe", + "id": 327 + }, + { + "name": "minecraft:golden_boots", + "id": 356 + }, + { + "name": "minecraft:golden_carrot", + "id": 283 + }, + { + "name": "minecraft:golden_chestplate", + "id": 354 + }, + { + "name": "minecraft:golden_helmet", + "id": 353 + }, + { + "name": "minecraft:golden_hoe", + "id": 335 + }, + { + "name": "minecraft:golden_horse_armor", + "id": 539 + }, + { + "name": "minecraft:golden_leggings", + "id": 355 + }, + { + "name": "minecraft:golden_pickaxe", + "id": 326 + }, + { + "name": "minecraft:golden_rail", + "id": 27 + }, + { + "name": "minecraft:golden_shovel", + "id": 325 + }, + { + "name": "minecraft:golden_sword", + "id": 324 + }, + { + "name": "minecraft:granite_stairs", + "id": -169 + }, + { + "name": "minecraft:grass", + "id": 2 + }, + { + "name": "minecraft:grass_path", + "id": 198 + }, + { + "name": "minecraft:gravel", + "id": 13 + }, + { + "name": "minecraft:gray_candle", + "id": -420 + }, + { + "name": "minecraft:gray_candle_cake", + "id": -437 + }, + { + "name": "minecraft:gray_carpet", + "id": -603 + }, + { + "name": "minecraft:gray_concrete", + "id": -634 + }, + { + "name": "minecraft:gray_concrete_powder", + "id": -715 + }, + { + "name": "minecraft:gray_dye", + "id": 405 + }, + { + "name": "minecraft:gray_glazed_terracotta", + "id": 227 + }, + { + "name": "minecraft:gray_shulker_box", + "id": -619 + }, + { + "name": "minecraft:gray_stained_glass", + "id": -679 + }, + { + "name": "minecraft:gray_stained_glass_pane", + "id": -649 + }, + { + "name": "minecraft:gray_terracotta", + "id": -730 + }, + { + "name": "minecraft:gray_wool", + "id": -553 + }, + { + "name": "minecraft:green_candle", + "id": -426 + }, + { + "name": "minecraft:green_candle_cake", + "id": -443 + }, + { + "name": "minecraft:green_carpet", + "id": -609 + }, + { + "name": "minecraft:green_concrete", + "id": -640 + }, + { + "name": "minecraft:green_concrete_powder", + "id": -721 + }, + { + "name": "minecraft:green_dye", + "id": 399 + }, + { + "name": "minecraft:green_glazed_terracotta", + "id": 233 + }, + { + "name": "minecraft:green_shulker_box", + "id": -625 + }, + { + "name": "minecraft:green_stained_glass", + "id": -685 + }, + { + "name": "minecraft:green_stained_glass_pane", + "id": -655 + }, + { + "name": "minecraft:green_terracotta", + "id": -736 + }, + { + "name": "minecraft:green_wool", + "id": -560 + }, + { + "name": "minecraft:grindstone", + "id": -195 + }, + { + "name": "minecraft:guardian_spawn_egg", + "id": 463 + }, + { + "name": "minecraft:gunpowder", + "id": 330 + }, + { + "name": "minecraft:hanging_roots", + "id": -319 + }, + { + "name": "minecraft:hard_glass", + "id": 253 + }, + { + "name": "minecraft:hard_glass_pane", + "id": 190 + }, + { + "name": "minecraft:hard_stained_glass", + "id": 254 + }, + { + "name": "minecraft:hard_stained_glass_pane", + "id": 191 + }, + { + "name": "minecraft:hardened_clay", + "id": 172 + }, + { + "name": "minecraft:hay_block", + "id": 170 + }, + { + "name": "minecraft:heart_of_the_sea", + "id": 578 + }, + { + "name": "minecraft:heart_pottery_sherd", + "id": 672 + }, + { + "name": "minecraft:heartbreak_pottery_sherd", + "id": 673 + }, + { + "name": "minecraft:heavy_weighted_pressure_plate", + "id": 148 + }, + { + "name": "minecraft:hoglin_spawn_egg", + "id": 498 + }, + { + "name": "minecraft:honey_block", + "id": -220 + }, + { + "name": "minecraft:honey_bottle", + "id": 599 + }, + { + "name": "minecraft:honeycomb", + "id": 598 + }, + { + "name": "minecraft:honeycomb_block", + "id": -221 + }, + { + "name": "minecraft:hopper", + "id": 534 + }, + { + "name": "minecraft:hopper_minecart", + "id": 533 + }, + { + "name": "minecraft:horn_coral", + "id": -584 + }, + { + "name": "minecraft:horse_spawn_egg", + "id": 460 + }, + { + "name": "minecraft:host_armor_trim_smithing_template", + "id": 700 + }, + { + "name": "minecraft:howl_pottery_sherd", + "id": 674 + }, + { + "name": "minecraft:husk_spawn_egg", + "id": 465 + }, + { + "name": "minecraft:ice", + "id": 79 + }, + { + "name": "minecraft:ice_bomb", + "id": 602 + }, + { + "name": "minecraft:infested_deepslate", + "id": -454 + }, + { + "name": "minecraft:info_update", + "id": 248 + }, + { + "name": "minecraft:info_update2", + "id": 249 + }, + { + "name": "minecraft:ink_sac", + "id": 415 + }, + { + "name": "minecraft:invisible_bedrock", + "id": 95 + }, + { + "name": "minecraft:iron_axe", + "id": 300 + }, + { + "name": "minecraft:iron_bars", + "id": 101 + }, + { + "name": "minecraft:iron_block", + "id": 42 + }, + { + "name": "minecraft:iron_boots", + "id": 348 + }, + { + "name": "minecraft:iron_chestplate", + "id": 346 + }, + { + "name": "minecraft:iron_door", + "id": 374 + }, + { + "name": "minecraft:iron_golem_spawn_egg", + "id": 506 + }, + { + "name": "minecraft:iron_helmet", + "id": 345 + }, + { + "name": "minecraft:iron_hoe", + "id": 333 + }, + { + "name": "minecraft:iron_horse_armor", + "id": 538 + }, + { + "name": "minecraft:iron_ingot", + "id": 307 + }, + { + "name": "minecraft:iron_leggings", + "id": 347 + }, + { + "name": "minecraft:iron_nugget", + "id": 576 + }, + { + "name": "minecraft:iron_ore", + "id": 15 + }, + { + "name": "minecraft:iron_pickaxe", + "id": 299 + }, + { + "name": "minecraft:iron_shovel", + "id": 298 + }, + { + "name": "minecraft:iron_sword", + "id": 309 + }, + { + "name": "minecraft:iron_trapdoor", + "id": 167 + }, + { + "name": "minecraft:item.acacia_door", + "id": 196 + }, + { + "name": "minecraft:item.bed", + "id": 26 + }, + { + "name": "minecraft:item.beetroot", + "id": 244 + }, + { + "name": "minecraft:item.birch_door", + "id": 194 + }, + { + "name": "minecraft:item.brewing_stand", + "id": 117 + }, + { + "name": "minecraft:item.cake", + "id": 92 + }, + { + "name": "minecraft:item.camera", + "id": 242 + }, + { + "name": "minecraft:item.campfire", + "id": -209 + }, + { + "name": "minecraft:item.cauldron", + "id": 118 + }, + { + "name": "minecraft:item.chain", + "id": -286 + }, + { + "name": "minecraft:item.crimson_door", + "id": -244 + }, + { + "name": "minecraft:item.dark_oak_door", + "id": 197 + }, + { + "name": "minecraft:item.flower_pot", + "id": 140 + }, + { + "name": "minecraft:item.frame", + "id": 199 + }, + { + "name": "minecraft:item.glow_frame", + "id": -339 + }, + { + "name": "minecraft:item.hopper", + "id": 154 + }, + { + "name": "minecraft:item.iron_door", + "id": 71 + }, + { + "name": "minecraft:item.jungle_door", + "id": 195 + }, + { + "name": "minecraft:item.kelp", + "id": -138 + }, + { + "name": "minecraft:item.mangrove_door", + "id": -493 + }, + { + "name": "minecraft:item.nether_sprouts", + "id": -238 + }, + { + "name": "minecraft:item.nether_wart", + "id": 115 + }, + { + "name": "minecraft:item.reeds", + "id": 83 + }, + { + "name": "minecraft:item.skull", + "id": 144 + }, + { + "name": "minecraft:item.soul_campfire", + "id": -290 + }, + { + "name": "minecraft:item.spruce_door", + "id": 193 + }, + { + "name": "minecraft:item.warped_door", + "id": -245 + }, + { + "name": "minecraft:item.wheat", + "id": 59 + }, + { + "name": "minecraft:item.wooden_door", + "id": 64 + }, + { + "name": "minecraft:jigsaw", + "id": -211 + }, + { + "name": "minecraft:jukebox", + "id": 84 + }, + { + "name": "minecraft:jungle_boat", + "id": 379 + }, + { + "name": "minecraft:jungle_button", + "id": -143 + }, + { + "name": "minecraft:jungle_chest_boat", + "id": 647 + }, + { + "name": "minecraft:jungle_door", + "id": 562 + }, + { + "name": "minecraft:jungle_fence", + "id": -578 + }, + { + "name": "minecraft:jungle_fence_gate", + "id": 185 + }, + { + "name": "minecraft:jungle_hanging_sign", + "id": -503 + }, + { + "name": "minecraft:jungle_log", + "id": -571 + }, + { + "name": "minecraft:jungle_pressure_plate", + "id": -153 + }, + { + "name": "minecraft:jungle_sign", + "id": 585 + }, + { + "name": "minecraft:jungle_stairs", + "id": 136 + }, + { + "name": "minecraft:jungle_standing_sign", + "id": -188 + }, + { + "name": "minecraft:jungle_trapdoor", + "id": -148 + }, + { + "name": "minecraft:jungle_wall_sign", + "id": -189 + }, + { + "name": "minecraft:kelp", + "id": 384 + }, + { + "name": "minecraft:ladder", + "id": 65 + }, + { + "name": "minecraft:lantern", + "id": -208 + }, + { + "name": "minecraft:lapis_block", + "id": 22 + }, + { + "name": "minecraft:lapis_lazuli", + "id": 416 + }, + { + "name": "minecraft:lapis_ore", + "id": 21 + }, + { + "name": "minecraft:large_amethyst_bud", + "id": -330 + }, + { + "name": "minecraft:lava", + "id": 11 + }, + { + "name": "minecraft:lava_bucket", + "id": 365 + }, + { + "name": "minecraft:lead", + "id": 554 + }, + { + "name": "minecraft:leather", + "id": 383 + }, + { + "name": "minecraft:leather_boots", + "id": 340 + }, + { + "name": "minecraft:leather_chestplate", + "id": 338 + }, + { + "name": "minecraft:leather_helmet", + "id": 337 + }, + { + "name": "minecraft:leather_horse_armor", + "id": 537 + }, + { + "name": "minecraft:leather_leggings", + "id": 339 + }, + { + "name": "minecraft:leaves", + "id": 18 + }, + { + "name": "minecraft:leaves2", + "id": 161 + }, + { + "name": "minecraft:lectern", + "id": -194 + }, + { + "name": "minecraft:lever", + "id": 69 + }, + { + "name": "minecraft:light_block", + "id": -215 + }, + { + "name": "minecraft:light_blue_candle", + "id": -416 + }, + { + "name": "minecraft:light_blue_candle_cake", + "id": -433 + }, + { + "name": "minecraft:light_blue_carpet", + "id": -599 + }, + { + "name": "minecraft:light_blue_concrete", + "id": -630 + }, + { + "name": "minecraft:light_blue_concrete_powder", + "id": -711 + }, + { + "name": "minecraft:light_blue_dye", + "id": 409 + }, + { + "name": "minecraft:light_blue_glazed_terracotta", + "id": 223 + }, + { + "name": "minecraft:light_blue_shulker_box", + "id": -615 + }, + { + "name": "minecraft:light_blue_stained_glass", + "id": -675 + }, + { + "name": "minecraft:light_blue_stained_glass_pane", + "id": -645 + }, + { + "name": "minecraft:light_blue_terracotta", + "id": -726 + }, + { + "name": "minecraft:light_blue_wool", + "id": -562 + }, + { + "name": "minecraft:light_gray_candle", + "id": -421 + }, + { + "name": "minecraft:light_gray_candle_cake", + "id": -438 + }, + { + "name": "minecraft:light_gray_carpet", + "id": -604 + }, + { + "name": "minecraft:light_gray_concrete", + "id": -635 + }, + { + "name": "minecraft:light_gray_concrete_powder", + "id": -716 + }, + { + "name": "minecraft:light_gray_dye", + "id": 404 + }, + { + "name": "minecraft:light_gray_shulker_box", + "id": -620 + }, + { + "name": "minecraft:light_gray_stained_glass", + "id": -680 + }, + { + "name": "minecraft:light_gray_stained_glass_pane", + "id": -650 + }, + { + "name": "minecraft:light_gray_terracotta", + "id": -731 + }, + { + "name": "minecraft:light_gray_wool", + "id": -552 + }, + { + "name": "minecraft:light_weighted_pressure_plate", + "id": 147 + }, + { + "name": "minecraft:lightning_rod", + "id": -312 + }, + { + "name": "minecraft:lime_candle", + "id": -418 + }, + { + "name": "minecraft:lime_candle_cake", + "id": -435 + }, + { + "name": "minecraft:lime_carpet", + "id": -601 + }, + { + "name": "minecraft:lime_concrete", + "id": -632 + }, + { + "name": "minecraft:lime_concrete_powder", + "id": -713 + }, + { + "name": "minecraft:lime_dye", + "id": 407 + }, + { + "name": "minecraft:lime_glazed_terracotta", + "id": 225 + }, + { + "name": "minecraft:lime_shulker_box", + "id": -617 + }, + { + "name": "minecraft:lime_stained_glass", + "id": -677 + }, + { + "name": "minecraft:lime_stained_glass_pane", + "id": -647 + }, + { + "name": "minecraft:lime_terracotta", + "id": -728 + }, + { + "name": "minecraft:lime_wool", + "id": -559 + }, + { + "name": "minecraft:lingering_potion", + "id": 569 + }, + { + "name": "minecraft:lit_blast_furnace", + "id": -214 + }, + { + "name": "minecraft:lit_deepslate_redstone_ore", + "id": -404 + }, + { + "name": "minecraft:lit_furnace", + "id": 62 + }, + { + "name": "minecraft:lit_pumpkin", + "id": 91 + }, + { + "name": "minecraft:lit_redstone_lamp", + "id": 124 + }, + { + "name": "minecraft:lit_redstone_ore", + "id": 74 + }, + { + "name": "minecraft:lit_smoker", + "id": -199 + }, + { + "name": "minecraft:llama_spawn_egg", + "id": 475 + }, + { + "name": "minecraft:lodestone", + "id": -222 + }, + { + "name": "minecraft:lodestone_compass", + "id": 609 + }, + { + "name": "minecraft:log", + "id": 705 + }, + { + "name": "minecraft:log2", + "id": 708 + }, + { + "name": "minecraft:loom", + "id": -204 + }, + { + "name": "minecraft:magenta_candle", + "id": -415 + }, + { + "name": "minecraft:magenta_candle_cake", + "id": -432 + }, + { + "name": "minecraft:magenta_carpet", + "id": -598 + }, + { + "name": "minecraft:magenta_concrete", + "id": -629 + }, + { + "name": "minecraft:magenta_concrete_powder", + "id": -710 + }, + { + "name": "minecraft:magenta_dye", + "id": 410 + }, + { + "name": "minecraft:magenta_glazed_terracotta", + "id": 222 + }, + { + "name": "minecraft:magenta_shulker_box", + "id": -614 + }, + { + "name": "minecraft:magenta_stained_glass", + "id": -674 + }, + { + "name": "minecraft:magenta_stained_glass_pane", + "id": -644 + }, + { + "name": "minecraft:magenta_terracotta", + "id": -725 + }, + { + "name": "minecraft:magenta_wool", + "id": -565 + }, + { + "name": "minecraft:magma", + "id": 213 + }, + { + "name": "minecraft:magma_cream", + "id": 432 + }, + { + "name": "minecraft:magma_cube_spawn_egg", + "id": 457 + }, + { + "name": "minecraft:mangrove_boat", + "id": 642 + }, + { + "name": "minecraft:mangrove_button", + "id": -487 + }, + { + "name": "minecraft:mangrove_chest_boat", + "id": 651 + }, + { + "name": "minecraft:mangrove_door", + "id": 640 + }, + { + "name": "minecraft:mangrove_double_slab", + "id": -499 + }, + { + "name": "minecraft:mangrove_fence", + "id": -491 + }, + { + "name": "minecraft:mangrove_fence_gate", + "id": -492 + }, + { + "name": "minecraft:mangrove_hanging_sign", + "id": -508 + }, + { + "name": "minecraft:mangrove_leaves", + "id": -472 + }, + { + "name": "minecraft:mangrove_log", + "id": -484 + }, + { + "name": "minecraft:mangrove_planks", + "id": -486 + }, + { + "name": "minecraft:mangrove_pressure_plate", + "id": -490 + }, + { + "name": "minecraft:mangrove_propagule", + "id": -474 + }, + { + "name": "minecraft:mangrove_roots", + "id": -482 + }, + { + "name": "minecraft:mangrove_sign", + "id": 641 + }, + { + "name": "minecraft:mangrove_slab", + "id": -489 + }, + { + "name": "minecraft:mangrove_stairs", + "id": -488 + }, + { + "name": "minecraft:mangrove_standing_sign", + "id": -494 + }, + { + "name": "minecraft:mangrove_trapdoor", + "id": -496 + }, + { + "name": "minecraft:mangrove_wall_sign", + "id": -495 + }, + { + "name": "minecraft:mangrove_wood", + "id": -497 + }, + { + "name": "minecraft:medicine", + "id": 606 + }, + { + "name": "minecraft:medium_amethyst_bud", + "id": -331 + }, + { + "name": "minecraft:melon_block", + "id": 103 + }, + { + "name": "minecraft:melon_seeds", + "id": 293 + }, + { + "name": "minecraft:melon_slice", + "id": 272 + }, + { + "name": "minecraft:melon_stem", + "id": 105 + }, + { + "name": "minecraft:milk_bucket", + "id": 363 + }, + { + "name": "minecraft:minecart", + "id": 372 + }, + { + "name": "minecraft:miner_pottery_sherd", + "id": 675 + }, + { + "name": "minecraft:mob_spawner", + "id": 52 + }, + { + "name": "minecraft:mojang_banner_pattern", + "id": 591 + }, + { + "name": "minecraft:monster_egg", + "id": 97 + }, + { + "name": "minecraft:mooshroom_spawn_egg", + "id": 442 + }, + { + "name": "minecraft:moss_block", + "id": -320 + }, + { + "name": "minecraft:moss_carpet", + "id": -335 + }, + { + "name": "minecraft:mossy_cobblestone", + "id": 48 + }, + { + "name": "minecraft:mossy_cobblestone_stairs", + "id": -179 + }, + { + "name": "minecraft:mossy_stone_brick_stairs", + "id": -175 + }, + { + "name": "minecraft:mourner_pottery_sherd", + "id": 676 + }, + { + "name": "minecraft:moving_block", + "id": 250 + }, + { + "name": "minecraft:mud", + "id": -473 + }, + { + "name": "minecraft:mud_brick_double_slab", + "id": -479 + }, + { + "name": "minecraft:mud_brick_slab", + "id": -478 + }, + { + "name": "minecraft:mud_brick_stairs", + "id": -480 + }, + { + "name": "minecraft:mud_brick_wall", + "id": -481 + }, + { + "name": "minecraft:mud_bricks", + "id": -475 + }, + { + "name": "minecraft:muddy_mangrove_roots", + "id": -483 + }, + { + "name": "minecraft:mule_spawn_egg", + "id": 468 + }, + { + "name": "minecraft:mushroom_stew", + "id": 260 + }, + { + "name": "minecraft:music_disc_11", + "id": 551 + }, + { + "name": "minecraft:music_disc_13", + "id": 541 + }, + { + "name": "minecraft:music_disc_5", + "id": 643 + }, + { + "name": "minecraft:music_disc_blocks", + "id": 543 + }, + { + "name": "minecraft:music_disc_cat", + "id": 542 + }, + { + "name": "minecraft:music_disc_chirp", + "id": 544 + }, + { + "name": "minecraft:music_disc_far", + "id": 545 + }, + { + "name": "minecraft:music_disc_mall", + "id": 546 + }, + { + "name": "minecraft:music_disc_mellohi", + "id": 547 + }, + { + "name": "minecraft:music_disc_otherside", + "id": 633 + }, + { + "name": "minecraft:music_disc_pigstep", + "id": 627 + }, + { + "name": "minecraft:music_disc_relic", + "id": 701 + }, + { + "name": "minecraft:music_disc_stal", + "id": 548 + }, + { + "name": "minecraft:music_disc_strad", + "id": 549 + }, + { + "name": "minecraft:music_disc_wait", + "id": 552 + }, + { + "name": "minecraft:music_disc_ward", + "id": 550 + }, + { + "name": "minecraft:mutton", + "id": 557 + }, + { + "name": "minecraft:mycelium", + "id": 110 + }, + { + "name": "minecraft:name_tag", + "id": 555 + }, + { + "name": "minecraft:nautilus_shell", + "id": 577 + }, + { + "name": "minecraft:nether_brick", + "id": 112 + }, + { + "name": "minecraft:nether_brick_fence", + "id": 113 + }, + { + "name": "minecraft:nether_brick_stairs", + "id": 114 + }, + { + "name": "minecraft:nether_gold_ore", + "id": -288 + }, + { + "name": "minecraft:nether_sprouts", + "id": 628 + }, + { + "name": "minecraft:nether_star", + "id": 525 + }, + { + "name": "minecraft:nether_wart", + "id": 294 + }, + { + "name": "minecraft:nether_wart_block", + "id": 214 + }, + { + "name": "minecraft:netherbrick", + "id": 530 + }, + { + "name": "minecraft:netherite_axe", + "id": 613 + }, + { + "name": "minecraft:netherite_block", + "id": -270 + }, + { + "name": "minecraft:netherite_boots", + "id": 619 + }, + { + "name": "minecraft:netherite_chestplate", + "id": 617 + }, + { + "name": "minecraft:netherite_helmet", + "id": 616 + }, + { + "name": "minecraft:netherite_hoe", + "id": 614 + }, + { + "name": "minecraft:netherite_ingot", + "id": 615 + }, + { + "name": "minecraft:netherite_leggings", + "id": 618 + }, + { + "name": "minecraft:netherite_pickaxe", + "id": 612 + }, + { + "name": "minecraft:netherite_scrap", + "id": 620 + }, + { + "name": "minecraft:netherite_shovel", + "id": 611 + }, + { + "name": "minecraft:netherite_sword", + "id": 610 + }, + { + "name": "minecraft:netherite_upgrade_smithing_template", + "id": 684 + }, + { + "name": "minecraft:netherrack", + "id": 87 + }, + { + "name": "minecraft:netherreactor", + "id": 247 + }, + { + "name": "minecraft:normal_stone_stairs", + "id": -180 + }, + { + "name": "minecraft:noteblock", + "id": 25 + }, + { + "name": "minecraft:npc_spawn_egg", + "id": 472 + }, + { + "name": "minecraft:oak_boat", + "id": 377 + }, + { + "name": "minecraft:oak_chest_boat", + "id": 645 + }, + { + "name": "minecraft:oak_fence", + "id": 85 + }, + { + "name": "minecraft:oak_hanging_sign", + "id": -500 + }, + { + "name": "minecraft:oak_log", + "id": 17 + }, + { + "name": "minecraft:oak_sign", + "id": 360 + }, + { + "name": "minecraft:oak_stairs", + "id": 53 + }, + { + "name": "minecraft:observer", + "id": 251 + }, + { + "name": "minecraft:obsidian", + "id": 49 + }, + { + "name": "minecraft:ocelot_spawn_egg", + "id": 453 + }, + { + "name": "minecraft:ochre_froglight", + "id": -471 + }, + { + "name": "minecraft:orange_candle", + "id": -414 + }, + { + "name": "minecraft:orange_candle_cake", + "id": -431 + }, + { + "name": "minecraft:orange_carpet", + "id": -597 + }, + { + "name": "minecraft:orange_concrete", + "id": -628 + }, + { + "name": "minecraft:orange_concrete_powder", + "id": -709 + }, + { + "name": "minecraft:orange_dye", + "id": 411 + }, + { + "name": "minecraft:orange_glazed_terracotta", + "id": 221 + }, + { + "name": "minecraft:orange_shulker_box", + "id": -613 + }, + { + "name": "minecraft:orange_stained_glass", + "id": -673 + }, + { + "name": "minecraft:orange_stained_glass_pane", + "id": -643 + }, + { + "name": "minecraft:orange_terracotta", + "id": -724 + }, + { + "name": "minecraft:orange_wool", + "id": -557 + }, + { + "name": "minecraft:oxidized_copper", + "id": -343 + }, + { + "name": "minecraft:oxidized_cut_copper", + "id": -350 + }, + { + "name": "minecraft:oxidized_cut_copper_slab", + "id": -364 + }, + { + "name": "minecraft:oxidized_cut_copper_stairs", + "id": -357 + }, + { + "name": "minecraft:oxidized_double_cut_copper_slab", + "id": -371 + }, + { + "name": "minecraft:packed_ice", + "id": 174 + }, + { + "name": "minecraft:packed_mud", + "id": -477 + }, + { + "name": "minecraft:painting", + "id": 359 + }, + { + "name": "minecraft:panda_spawn_egg", + "id": 491 + }, + { + "name": "minecraft:paper", + "id": 388 + }, + { + "name": "minecraft:parrot_spawn_egg", + "id": 480 + }, + { + "name": "minecraft:pearlescent_froglight", + "id": -469 + }, + { + "name": "minecraft:phantom_membrane", + "id": 581 + }, + { + "name": "minecraft:phantom_spawn_egg", + "id": 488 + }, + { + "name": "minecraft:pig_spawn_egg", + "id": 439 + }, + { + "name": "minecraft:piglin_banner_pattern", + "id": 594 + }, + { + "name": "minecraft:piglin_brute_spawn_egg", + "id": 501 + }, + { + "name": "minecraft:piglin_spawn_egg", + "id": 499 + }, + { + "name": "minecraft:pillager_spawn_egg", + "id": 493 + }, + { + "name": "minecraft:pink_candle", + "id": -419 + }, + { + "name": "minecraft:pink_candle_cake", + "id": -436 + }, + { + "name": "minecraft:pink_carpet", + "id": -602 + }, + { + "name": "minecraft:pink_concrete", + "id": -633 + }, + { + "name": "minecraft:pink_concrete_powder", + "id": -714 + }, + { + "name": "minecraft:pink_dye", + "id": 406 + }, + { + "name": "minecraft:pink_glazed_terracotta", + "id": 226 + }, + { + "name": "minecraft:pink_petals", + "id": -549 + }, + { + "name": "minecraft:pink_shulker_box", + "id": -618 + }, + { + "name": "minecraft:pink_stained_glass", + "id": -678 + }, + { + "name": "minecraft:pink_stained_glass_pane", + "id": -648 + }, + { + "name": "minecraft:pink_terracotta", + "id": -729 + }, + { + "name": "minecraft:pink_wool", + "id": -566 + }, + { + "name": "minecraft:piston", + "id": 33 + }, + { + "name": "minecraft:piston_arm_collision", + "id": 34 + }, + { + "name": "minecraft:pitcher_crop", + "id": -574 + }, + { + "name": "minecraft:pitcher_plant", + "id": -612 + }, + { + "name": "minecraft:pitcher_pod", + "id": 297 + }, + { + "name": "minecraft:planks", + "id": 5 + }, + { + "name": "minecraft:plenty_pottery_sherd", + "id": 677 + }, + { + "name": "minecraft:podzol", + "id": 243 + }, + { + "name": "minecraft:pointed_dripstone", + "id": -308 + }, + { + "name": "minecraft:poisonous_potato", + "id": 282 + }, + { + "name": "minecraft:polar_bear_spawn_egg", + "id": 474 + }, + { + "name": "minecraft:polished_andesite_stairs", + "id": -174 + }, + { + "name": "minecraft:polished_basalt", + "id": -235 + }, + { + "name": "minecraft:polished_blackstone", + "id": -291 + }, + { + "name": "minecraft:polished_blackstone_brick_double_slab", + "id": -285 + }, + { + "name": "minecraft:polished_blackstone_brick_slab", + "id": -284 + }, + { + "name": "minecraft:polished_blackstone_brick_stairs", + "id": -275 + }, + { + "name": "minecraft:polished_blackstone_brick_wall", + "id": -278 + }, + { + "name": "minecraft:polished_blackstone_bricks", + "id": -274 + }, + { + "name": "minecraft:polished_blackstone_button", + "id": -296 + }, + { + "name": "minecraft:polished_blackstone_double_slab", + "id": -294 + }, + { + "name": "minecraft:polished_blackstone_pressure_plate", + "id": -295 + }, + { + "name": "minecraft:polished_blackstone_slab", + "id": -293 + }, + { + "name": "minecraft:polished_blackstone_stairs", + "id": -292 + }, + { + "name": "minecraft:polished_blackstone_wall", + "id": -297 + }, + { + "name": "minecraft:polished_deepslate", + "id": -383 + }, + { + "name": "minecraft:polished_deepslate_double_slab", + "id": -397 + }, + { + "name": "minecraft:polished_deepslate_slab", + "id": -384 + }, + { + "name": "minecraft:polished_deepslate_stairs", + "id": -385 + }, + { + "name": "minecraft:polished_deepslate_wall", + "id": -386 + }, + { + "name": "minecraft:polished_diorite_stairs", + "id": -173 + }, + { + "name": "minecraft:polished_granite_stairs", + "id": -172 + }, + { + "name": "minecraft:popped_chorus_fruit", + "id": 566 + }, + { + "name": "minecraft:porkchop", + "id": 262 + }, + { + "name": "minecraft:portal", + "id": 90 + }, + { + "name": "minecraft:potato", + "id": 280 + }, + { + "name": "minecraft:potatoes", + "id": 142 + }, + { + "name": "minecraft:potion", + "id": 428 + }, + { + "name": "minecraft:powder_snow", + "id": -306 + }, + { + "name": "minecraft:powder_snow_bucket", + "id": 370 + }, + { + "name": "minecraft:powered_comparator", + "id": 150 + }, + { + "name": "minecraft:powered_repeater", + "id": 94 + }, + { + "name": "minecraft:prismarine", + "id": 168 + }, + { + "name": "minecraft:prismarine_bricks_stairs", + "id": -4 + }, + { + "name": "minecraft:prismarine_crystals", + "id": 556 + }, + { + "name": "minecraft:prismarine_shard", + "id": 572 + }, + { + "name": "minecraft:prismarine_stairs", + "id": -2 + }, + { + "name": "minecraft:prize_pottery_sherd", + "id": 678 + }, + { + "name": "minecraft:pufferfish", + "id": 267 + }, + { + "name": "minecraft:pufferfish_bucket", + "id": 369 + }, + { + "name": "minecraft:pufferfish_spawn_egg", + "id": 483 + }, + { + "name": "minecraft:pumpkin", + "id": 86 + }, + { + "name": "minecraft:pumpkin_pie", + "id": 284 + }, + { + "name": "minecraft:pumpkin_seeds", + "id": 292 + }, + { + "name": "minecraft:pumpkin_stem", + "id": 104 + }, + { + "name": "minecraft:purple_candle", + "id": -423 + }, + { + "name": "minecraft:purple_candle_cake", + "id": -440 + }, + { + "name": "minecraft:purple_carpet", + "id": -606 + }, + { + "name": "minecraft:purple_concrete", + "id": -637 + }, + { + "name": "minecraft:purple_concrete_powder", + "id": -718 + }, + { + "name": "minecraft:purple_dye", + "id": 402 + }, + { + "name": "minecraft:purple_glazed_terracotta", + "id": 219 + }, + { + "name": "minecraft:purple_shulker_box", + "id": -622 + }, + { + "name": "minecraft:purple_stained_glass", + "id": -682 + }, + { + "name": "minecraft:purple_stained_glass_pane", + "id": -652 + }, + { + "name": "minecraft:purple_terracotta", + "id": -733 + }, + { + "name": "minecraft:purple_wool", + "id": -564 + }, + { + "name": "minecraft:purpur_block", + "id": 201 + }, + { + "name": "minecraft:purpur_stairs", + "id": 203 + }, + { + "name": "minecraft:quartz", + "id": 531 + }, + { + "name": "minecraft:quartz_block", + "id": 155 + }, + { + "name": "minecraft:quartz_bricks", + "id": -304 + }, + { + "name": "minecraft:quartz_ore", + "id": 153 + }, + { + "name": "minecraft:quartz_stairs", + "id": 156 + }, + { + "name": "minecraft:rabbit", + "id": 288 + }, + { + "name": "minecraft:rabbit_foot", + "id": 535 + }, + { + "name": "minecraft:rabbit_hide", + "id": 536 + }, + { + "name": "minecraft:rabbit_spawn_egg", + "id": 461 + }, + { + "name": "minecraft:rabbit_stew", + "id": 290 + }, + { + "name": "minecraft:rail", + "id": 66 + }, + { + "name": "minecraft:raiser_armor_trim_smithing_template", + "id": 698 + }, + { + "name": "minecraft:rapid_fertilizer", + "id": 604 + }, + { + "name": "minecraft:ravager_spawn_egg", + "id": 495 + }, + { + "name": "minecraft:raw_copper", + "id": 514 + }, + { + "name": "minecraft:raw_copper_block", + "id": -452 + }, + { + "name": "minecraft:raw_gold", + "id": 513 + }, + { + "name": "minecraft:raw_gold_block", + "id": -453 + }, + { + "name": "minecraft:raw_iron", + "id": 512 + }, + { + "name": "minecraft:raw_iron_block", + "id": -451 + }, + { + "name": "minecraft:recovery_compass", + "id": 653 + }, + { + "name": "minecraft:red_candle", + "id": -427 + }, + { + "name": "minecraft:red_candle_cake", + "id": -444 + }, + { + "name": "minecraft:red_carpet", + "id": -610 + }, + { + "name": "minecraft:red_concrete", + "id": -641 + }, + { + "name": "minecraft:red_concrete_powder", + "id": -722 + }, + { + "name": "minecraft:red_dye", + "id": 398 + }, + { + "name": "minecraft:red_flower", + "id": 38 + }, + { + "name": "minecraft:red_glazed_terracotta", + "id": 234 + }, + { + "name": "minecraft:red_mushroom", + "id": 40 + }, + { + "name": "minecraft:red_mushroom_block", + "id": 100 + }, + { + "name": "minecraft:red_nether_brick", + "id": 215 + }, + { + "name": "minecraft:red_nether_brick_stairs", + "id": -184 + }, + { + "name": "minecraft:red_sandstone", + "id": 179 + }, + { + "name": "minecraft:red_sandstone_stairs", + "id": 180 + }, + { + "name": "minecraft:red_shulker_box", + "id": -626 + }, + { + "name": "minecraft:red_stained_glass", + "id": -686 + }, + { + "name": "minecraft:red_stained_glass_pane", + "id": -656 + }, + { + "name": "minecraft:red_terracotta", + "id": -737 + }, + { + "name": "minecraft:red_wool", + "id": -556 + }, + { + "name": "minecraft:redstone", + "id": 375 + }, + { + "name": "minecraft:redstone_block", + "id": 152 + }, + { + "name": "minecraft:redstone_lamp", + "id": 123 + }, + { + "name": "minecraft:redstone_ore", + "id": 73 + }, + { + "name": "minecraft:redstone_torch", + "id": 76 + }, + { + "name": "minecraft:redstone_wire", + "id": 55 + }, + { + "name": "minecraft:reinforced_deepslate", + "id": -466 + }, + { + "name": "minecraft:repeater", + "id": 421 + }, + { + "name": "minecraft:repeating_command_block", + "id": 188 + }, + { + "name": "minecraft:reserved6", + "id": 255 + }, + { + "name": "minecraft:respawn_anchor", + "id": -272 + }, + { + "name": "minecraft:rib_armor_trim_smithing_template", + "id": 694 + }, + { + "name": "minecraft:rotten_flesh", + "id": 277 + }, + { + "name": "minecraft:saddle", + "id": 373 + }, + { + "name": "minecraft:salmon", + "id": 265 + }, + { + "name": "minecraft:salmon_bucket", + "id": 367 + }, + { + "name": "minecraft:salmon_spawn_egg", + "id": 484 + }, + { + "name": "minecraft:sand", + "id": 12 + }, + { + "name": "minecraft:sandstone", + "id": 24 + }, + { + "name": "minecraft:sandstone_stairs", + "id": 128 + }, + { + "name": "minecraft:sapling", + "id": 6 + }, + { + "name": "minecraft:scaffolding", + "id": -165 + }, + { + "name": "minecraft:sculk", + "id": -458 + }, + { + "name": "minecraft:sculk_catalyst", + "id": -460 + }, + { + "name": "minecraft:sculk_sensor", + "id": -307 + }, + { + "name": "minecraft:sculk_shrieker", + "id": -461 + }, + { + "name": "minecraft:sculk_vein", + "id": -459 + }, + { + "name": "minecraft:scute", + "id": 579 + }, + { + "name": "minecraft:sea_lantern", + "id": 169 + }, + { + "name": "minecraft:sea_pickle", + "id": -156 + }, + { + "name": "minecraft:seagrass", + "id": -130 + }, + { + "name": "minecraft:sentry_armor_trim_smithing_template", + "id": 685 + }, + { + "name": "minecraft:shaper_armor_trim_smithing_template", + "id": 699 + }, + { + "name": "minecraft:sheaf_pottery_sherd", + "id": 679 + }, + { + "name": "minecraft:shears", + "id": 423 + }, + { + "name": "minecraft:sheep_spawn_egg", + "id": 440 + }, + { + "name": "minecraft:shelter_pottery_sherd", + "id": 680 + }, + { + "name": "minecraft:shield", + "id": 357 + }, + { + "name": "minecraft:shroomlight", + "id": -230 + }, + { + "name": "minecraft:shulker_box", + "id": 713 + }, + { + "name": "minecraft:shulker_shell", + "id": 573 + }, + { + "name": "minecraft:shulker_spawn_egg", + "id": 471 + }, + { + "name": "minecraft:silence_armor_trim_smithing_template", + "id": 696 + }, + { + "name": "minecraft:silver_glazed_terracotta", + "id": 228 + }, + { + "name": "minecraft:silverfish_spawn_egg", + "id": 445 + }, + { + "name": "minecraft:skeleton_horse_spawn_egg", + "id": 469 + }, + { + "name": "minecraft:skeleton_spawn_egg", + "id": 446 + }, + { + "name": "minecraft:skull", + "id": 523 + }, + { + "name": "minecraft:skull_banner_pattern", + "id": 590 + }, + { + "name": "minecraft:skull_pottery_sherd", + "id": 681 + }, + { + "name": "minecraft:slime", + "id": 165 + }, + { + "name": "minecraft:slime_ball", + "id": 390 + }, + { + "name": "minecraft:slime_spawn_egg", + "id": 447 + }, + { + "name": "minecraft:small_amethyst_bud", + "id": -332 + }, + { + "name": "minecraft:small_dripleaf_block", + "id": -336 + }, + { + "name": "minecraft:smithing_table", + "id": -202 + }, + { + "name": "minecraft:smoker", + "id": -198 + }, + { + "name": "minecraft:smooth_basalt", + "id": -377 + }, + { + "name": "minecraft:smooth_quartz_stairs", + "id": -185 + }, + { + "name": "minecraft:smooth_red_sandstone_stairs", + "id": -176 + }, + { + "name": "minecraft:smooth_sandstone_stairs", + "id": -177 + }, + { + "name": "minecraft:smooth_stone", + "id": -183 + }, + { + "name": "minecraft:sniffer_egg", + "id": -596 + }, + { + "name": "minecraft:sniffer_spawn_egg", + "id": 502 + }, + { + "name": "minecraft:snort_pottery_sherd", + "id": 682 + }, + { + "name": "minecraft:snout_armor_trim_smithing_template", + "id": 693 + }, + { + "name": "minecraft:snow", + "id": 80 + }, + { + "name": "minecraft:snow_golem_spawn_egg", + "id": 507 + }, + { + "name": "minecraft:snow_layer", + "id": 78 + }, + { + "name": "minecraft:snowball", + "id": 376 + }, + { + "name": "minecraft:soul_campfire", + "id": 629 + }, + { + "name": "minecraft:soul_fire", + "id": -237 + }, + { + "name": "minecraft:soul_lantern", + "id": -269 + }, + { + "name": "minecraft:soul_sand", + "id": 88 + }, + { + "name": "minecraft:soul_soil", + "id": -236 + }, + { + "name": "minecraft:soul_torch", + "id": -268 + }, + { + "name": "minecraft:sparkler", + "id": 607 + }, + { + "name": "minecraft:spawn_egg", + "id": 717 + }, + { + "name": "minecraft:spider_eye", + "id": 278 + }, + { + "name": "minecraft:spider_spawn_egg", + "id": 448 + }, + { + "name": "minecraft:spire_armor_trim_smithing_template", + "id": 695 + }, + { + "name": "minecraft:splash_potion", + "id": 568 + }, + { + "name": "minecraft:sponge", + "id": 19 + }, + { + "name": "minecraft:spore_blossom", + "id": -321 + }, + { + "name": "minecraft:spruce_boat", + "id": 380 + }, + { + "name": "minecraft:spruce_button", + "id": -144 + }, + { + "name": "minecraft:spruce_chest_boat", + "id": 648 + }, + { + "name": "minecraft:spruce_door", + "id": 560 + }, + { + "name": "minecraft:spruce_fence", + "id": -579 + }, + { + "name": "minecraft:spruce_fence_gate", + "id": 183 + }, + { + "name": "minecraft:spruce_hanging_sign", + "id": -501 + }, + { + "name": "minecraft:spruce_log", + "id": -569 + }, + { + "name": "minecraft:spruce_pressure_plate", + "id": -154 + }, + { + "name": "minecraft:spruce_sign", + "id": 583 + }, + { + "name": "minecraft:spruce_stairs", + "id": 134 + }, + { + "name": "minecraft:spruce_standing_sign", + "id": -181 + }, + { + "name": "minecraft:spruce_trapdoor", + "id": -149 + }, + { + "name": "minecraft:spruce_wall_sign", + "id": -182 + }, + { + "name": "minecraft:spyglass", + "id": 632 + }, + { + "name": "minecraft:squid_spawn_egg", + "id": 452 + }, + { + "name": "minecraft:stained_glass", + "id": 711 + }, + { + "name": "minecraft:stained_glass_pane", + "id": 712 + }, + { + "name": "minecraft:stained_hardened_clay", + "id": 702 + }, + { + "name": "minecraft:standing_banner", + "id": 176 + }, + { + "name": "minecraft:standing_sign", + "id": 63 + }, + { + "name": "minecraft:stick", + "id": 322 + }, + { + "name": "minecraft:sticky_piston", + "id": 29 + }, + { + "name": "minecraft:sticky_piston_arm_collision", + "id": -217 + }, + { + "name": "minecraft:stone", + "id": 1 + }, + { + "name": "minecraft:stone_axe", + "id": 317 + }, + { + "name": "minecraft:stone_block_slab", + "id": 44 + }, + { + "name": "minecraft:stone_block_slab2", + "id": 182 + }, + { + "name": "minecraft:stone_block_slab3", + "id": -162 + }, + { + "name": "minecraft:stone_block_slab4", + "id": -166 + }, + { + "name": "minecraft:stone_brick_stairs", + "id": 109 + }, + { + "name": "minecraft:stone_button", + "id": 77 + }, + { + "name": "minecraft:stone_hoe", + "id": 332 + }, + { + "name": "minecraft:stone_pickaxe", + "id": 316 + }, + { + "name": "minecraft:stone_pressure_plate", + "id": 70 + }, + { + "name": "minecraft:stone_shovel", + "id": 315 + }, + { + "name": "minecraft:stone_stairs", + "id": 67 + }, + { + "name": "minecraft:stone_sword", + "id": 314 + }, + { + "name": "minecraft:stonebrick", + "id": 98 + }, + { + "name": "minecraft:stonecutter", + "id": 245 + }, + { + "name": "minecraft:stonecutter_block", + "id": -197 + }, + { + "name": "minecraft:stray_spawn_egg", + "id": 464 + }, + { + "name": "minecraft:strider_spawn_egg", + "id": 497 + }, + { + "name": "minecraft:string", + "id": 328 + }, + { + "name": "minecraft:stripped_acacia_log", + "id": -8 + }, + { + "name": "minecraft:stripped_bamboo_block", + "id": -528 + }, + { + "name": "minecraft:stripped_birch_log", + "id": -6 + }, + { + "name": "minecraft:stripped_cherry_log", + "id": -535 + }, + { + "name": "minecraft:stripped_cherry_wood", + "id": -545 + }, + { + "name": "minecraft:stripped_crimson_hyphae", + "id": -300 + }, + { + "name": "minecraft:stripped_crimson_stem", + "id": -240 + }, + { + "name": "minecraft:stripped_dark_oak_log", + "id": -9 + }, + { + "name": "minecraft:stripped_jungle_log", + "id": -7 + }, + { + "name": "minecraft:stripped_mangrove_log", + "id": -485 + }, + { + "name": "minecraft:stripped_mangrove_wood", + "id": -498 + }, + { + "name": "minecraft:stripped_oak_log", + "id": -10 + }, + { + "name": "minecraft:stripped_spruce_log", + "id": -5 + }, + { + "name": "minecraft:stripped_warped_hyphae", + "id": -301 + }, + { + "name": "minecraft:stripped_warped_stem", + "id": -241 + }, + { + "name": "minecraft:structure_block", + "id": 252 + }, + { + "name": "minecraft:structure_void", + "id": 217 + }, + { + "name": "minecraft:sugar", + "id": 418 + }, + { + "name": "minecraft:sugar_cane", + "id": 387 + }, + { + "name": "minecraft:suspicious_gravel", + "id": -573 + }, + { + "name": "minecraft:suspicious_sand", + "id": -529 + }, + { + "name": "minecraft:suspicious_stew", + "id": 597 + }, + { + "name": "minecraft:sweet_berries", + "id": 287 + }, + { + "name": "minecraft:sweet_berry_bush", + "id": -207 + }, + { + "name": "minecraft:tadpole_bucket", + "id": 637 + }, + { + "name": "minecraft:tadpole_spawn_egg", + "id": 636 + }, + { + "name": "minecraft:tallgrass", + "id": 31 + }, + { + "name": "minecraft:target", + "id": -239 + }, + { + "name": "minecraft:tide_armor_trim_smithing_template", + "id": 692 + }, + { + "name": "minecraft:tinted_glass", + "id": -334 + }, + { + "name": "minecraft:tnt", + "id": 46 + }, + { + "name": "minecraft:tnt_minecart", + "id": 532 + }, + { + "name": "minecraft:torch", + "id": 50 + }, + { + "name": "minecraft:torchflower", + "id": -568 + }, + { + "name": "minecraft:torchflower_crop", + "id": -567 + }, + { + "name": "minecraft:torchflower_seeds", + "id": 296 + }, + { + "name": "minecraft:totem_of_undying", + "id": 575 + }, + { + "name": "minecraft:trader_llama_spawn_egg", + "id": 655 + }, + { + "name": "minecraft:trapdoor", + "id": 96 + }, + { + "name": "minecraft:trapped_chest", + "id": 146 + }, + { + "name": "minecraft:trident", + "id": 553 + }, + { + "name": "minecraft:trip_wire", + "id": 132 + }, + { + "name": "minecraft:tripwire_hook", + "id": 131 + }, + { + "name": "minecraft:tropical_fish", + "id": 266 + }, + { + "name": "minecraft:tropical_fish_bucket", + "id": 368 + }, + { + "name": "minecraft:tropical_fish_spawn_egg", + "id": 481 + }, + { + "name": "minecraft:tube_coral", + "id": -131 + }, + { + "name": "minecraft:tuff", + "id": -333 + }, + { + "name": "minecraft:turtle_egg", + "id": -159 + }, + { + "name": "minecraft:turtle_helmet", + "id": 580 + }, + { + "name": "minecraft:turtle_spawn_egg", + "id": 487 + }, + { + "name": "minecraft:twisting_vines", + "id": -287 + }, + { + "name": "minecraft:underwater_torch", + "id": 239 + }, + { + "name": "minecraft:undyed_shulker_box", + "id": 205 + }, + { + "name": "minecraft:unknown", + "id": -305 + }, + { + "name": "minecraft:unlit_redstone_torch", + "id": 75 + }, + { + "name": "minecraft:unpowered_comparator", + "id": 149 + }, + { + "name": "minecraft:unpowered_repeater", + "id": 93 + }, + { + "name": "minecraft:verdant_froglight", + "id": -470 + }, + { + "name": "minecraft:vex_armor_trim_smithing_template", + "id": 691 + }, + { + "name": "minecraft:vex_spawn_egg", + "id": 478 + }, + { + "name": "minecraft:villager_spawn_egg", + "id": 451 + }, + { + "name": "minecraft:vindicator_spawn_egg", + "id": 476 + }, + { + "name": "minecraft:vine", + "id": 106 + }, + { + "name": "minecraft:wall_banner", + "id": 177 + }, + { + "name": "minecraft:wall_sign", + "id": 68 + }, + { + "name": "minecraft:wandering_trader_spawn_egg", + "id": 494 + }, + { + "name": "minecraft:ward_armor_trim_smithing_template", + "id": 689 + }, + { + "name": "minecraft:warden_spawn_egg", + "id": 639 + }, + { + "name": "minecraft:warped_button", + "id": -261 + }, + { + "name": "minecraft:warped_door", + "id": 624 + }, + { + "name": "minecraft:warped_double_slab", + "id": -267 + }, + { + "name": "minecraft:warped_fence", + "id": -257 + }, + { + "name": "minecraft:warped_fence_gate", + "id": -259 + }, + { + "name": "minecraft:warped_fungus", + "id": -229 + }, + { + "name": "minecraft:warped_fungus_on_a_stick", + "id": 625 + }, + { + "name": "minecraft:warped_hanging_sign", + "id": -507 + }, + { + "name": "minecraft:warped_hyphae", + "id": -298 + }, + { + "name": "minecraft:warped_nylium", + "id": -233 + }, + { + "name": "minecraft:warped_planks", + "id": -243 + }, + { + "name": "minecraft:warped_pressure_plate", + "id": -263 + }, + { + "name": "minecraft:warped_roots", + "id": -224 + }, + { + "name": "minecraft:warped_sign", + "id": 622 + }, + { + "name": "minecraft:warped_slab", + "id": -265 + }, + { + "name": "minecraft:warped_stairs", + "id": -255 + }, + { + "name": "minecraft:warped_standing_sign", + "id": -251 + }, + { + "name": "minecraft:warped_stem", + "id": -226 + }, + { + "name": "minecraft:warped_trapdoor", + "id": -247 + }, + { + "name": "minecraft:warped_wall_sign", + "id": -253 + }, + { + "name": "minecraft:warped_wart_block", + "id": -227 + }, + { + "name": "minecraft:water", + "id": 9 + }, + { + "name": "minecraft:water_bucket", + "id": 364 + }, + { + "name": "minecraft:waterlily", + "id": 111 + }, + { + "name": "minecraft:waxed_copper", + "id": -344 + }, + { + "name": "minecraft:waxed_cut_copper", + "id": -351 + }, + { + "name": "minecraft:waxed_cut_copper_slab", + "id": -365 + }, + { + "name": "minecraft:waxed_cut_copper_stairs", + "id": -358 + }, + { + "name": "minecraft:waxed_double_cut_copper_slab", + "id": -372 + }, + { + "name": "minecraft:waxed_exposed_copper", + "id": -345 + }, + { + "name": "minecraft:waxed_exposed_cut_copper", + "id": -352 + }, + { + "name": "minecraft:waxed_exposed_cut_copper_slab", + "id": -366 + }, + { + "name": "minecraft:waxed_exposed_cut_copper_stairs", + "id": -359 + }, + { + "name": "minecraft:waxed_exposed_double_cut_copper_slab", + "id": -373 + }, + { + "name": "minecraft:waxed_oxidized_copper", + "id": -446 + }, + { + "name": "minecraft:waxed_oxidized_cut_copper", + "id": -447 + }, + { + "name": "minecraft:waxed_oxidized_cut_copper_slab", + "id": -449 + }, + { + "name": "minecraft:waxed_oxidized_cut_copper_stairs", + "id": -448 + }, + { + "name": "minecraft:waxed_oxidized_double_cut_copper_slab", + "id": -450 + }, + { + "name": "minecraft:waxed_weathered_copper", + "id": -346 + }, + { + "name": "minecraft:waxed_weathered_cut_copper", + "id": -353 + }, + { + "name": "minecraft:waxed_weathered_cut_copper_slab", + "id": -367 + }, + { + "name": "minecraft:waxed_weathered_cut_copper_stairs", + "id": -360 + }, + { + "name": "minecraft:waxed_weathered_double_cut_copper_slab", + "id": -374 + }, + { + "name": "minecraft:wayfinder_armor_trim_smithing_template", + "id": 697 + }, + { + "name": "minecraft:weathered_copper", + "id": -342 + }, + { + "name": "minecraft:weathered_cut_copper", + "id": -349 + }, + { + "name": "minecraft:weathered_cut_copper_slab", + "id": -363 + }, + { + "name": "minecraft:weathered_cut_copper_stairs", + "id": -356 + }, + { + "name": "minecraft:weathered_double_cut_copper_slab", + "id": -370 + }, + { + "name": "minecraft:web", + "id": 30 + }, + { + "name": "minecraft:weeping_vines", + "id": -231 + }, + { + "name": "minecraft:wheat", + "id": 336 + }, + { + "name": "minecraft:wheat_seeds", + "id": 291 + }, + { + "name": "minecraft:white_candle", + "id": -413 + }, + { + "name": "minecraft:white_candle_cake", + "id": -430 + }, + { + "name": "minecraft:white_carpet", + "id": 171 + }, + { + "name": "minecraft:white_concrete", + "id": 236 + }, + { + "name": "minecraft:white_concrete_powder", + "id": 237 + }, + { + "name": "minecraft:white_dye", + "id": 412 + }, + { + "name": "minecraft:white_glazed_terracotta", + "id": 220 + }, + { + "name": "minecraft:white_shulker_box", + "id": 218 + }, + { + "name": "minecraft:white_stained_glass", + "id": 241 + }, + { + "name": "minecraft:white_stained_glass_pane", + "id": 160 + }, + { + "name": "minecraft:white_terracotta", + "id": 159 + }, + { + "name": "minecraft:white_wool", + "id": 35 + }, + { + "name": "minecraft:wild_armor_trim_smithing_template", + "id": 688 + }, + { + "name": "minecraft:witch_spawn_egg", + "id": 454 + }, + { + "name": "minecraft:wither_rose", + "id": -216 + }, + { + "name": "minecraft:wither_skeleton_spawn_egg", + "id": 466 + }, + { + "name": "minecraft:wither_spawn_egg", + "id": 509 + }, + { + "name": "minecraft:wolf_spawn_egg", + "id": 441 + }, + { + "name": "minecraft:wood", + "id": -212 + }, + { + "name": "minecraft:wooden_axe", + "id": 313 + }, + { + "name": "minecraft:wooden_button", + "id": 143 + }, + { + "name": "minecraft:wooden_door", + "id": 361 + }, + { + "name": "minecraft:wooden_hoe", + "id": 331 + }, + { + "name": "minecraft:wooden_pickaxe", + "id": 312 + }, + { + "name": "minecraft:wooden_pressure_plate", + "id": 72 + }, + { + "name": "minecraft:wooden_shovel", + "id": 311 + }, + { + "name": "minecraft:wooden_slab", + "id": 158 + }, + { + "name": "minecraft:wooden_sword", + "id": 310 + }, + { + "name": "minecraft:wool", + "id": 703 + }, + { + "name": "minecraft:writable_book", + "id": 517 + }, + { + "name": "minecraft:written_book", + "id": 518 + }, + { + "name": "minecraft:yellow_candle", + "id": -417 + }, + { + "name": "minecraft:yellow_candle_cake", + "id": -434 + }, + { + "name": "minecraft:yellow_carpet", + "id": -600 + }, + { + "name": "minecraft:yellow_concrete", + "id": -631 + }, + { + "name": "minecraft:yellow_concrete_powder", + "id": -712 + }, + { + "name": "minecraft:yellow_dye", + "id": 408 + }, + { + "name": "minecraft:yellow_flower", + "id": 37 + }, + { + "name": "minecraft:yellow_glazed_terracotta", + "id": 224 + }, + { + "name": "minecraft:yellow_shulker_box", + "id": -616 + }, + { + "name": "minecraft:yellow_stained_glass", + "id": -676 + }, + { + "name": "minecraft:yellow_stained_glass_pane", + "id": -646 + }, + { + "name": "minecraft:yellow_terracotta", + "id": -727 + }, + { + "name": "minecraft:yellow_wool", + "id": -558 + }, + { + "name": "minecraft:zoglin_spawn_egg", + "id": 500 + }, + { + "name": "minecraft:zombie_horse_spawn_egg", + "id": 470 + }, + { + "name": "minecraft:zombie_pigman_spawn_egg", + "id": 450 + }, + { + "name": "minecraft:zombie_spawn_egg", + "id": 449 + }, + { + "name": "minecraft:zombie_villager_spawn_egg", + "id": 479 + } +] \ No newline at end of file diff --git a/core/src/main/resources/mappings b/core/src/main/resources/mappings index d44a1e360..587220aaf 160000 --- a/core/src/main/resources/mappings +++ b/core/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit d44a1e36059aba666b66e6c545b054c86c1fadac +Subproject commit 587220aafb55e80f2a70d6eac2d4b89dc0a005bd diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 74ac6d22a..36b09dfae 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,9 +9,10 @@ netty = "4.1.80.Final" guava = "29.0-jre" gson = "2.3.1" # Provided by Spigot 1.8.8 websocket = "1.5.1" -protocol = "3.0.0.Beta1-20230718.000033-102" -protocol-connection = "3.0.0.Beta1-20230718.000033-101" +protocol = "3.0.0.Beta1-20230908.171156-106" +protocol-connection = "3.0.0.Beta1-20230908.171156-105" raknet = "1.0.0.CR1-20230703.195238-9" +blockstateupdater="1.20.30-20230911.121922-2" mcauthlib = "d9d773e" mcprotocollib = "1.20-2-20230827.192136-1" adventure = "4.14.0" @@ -97,6 +98,8 @@ protocol-common = { group = "org.cloudburstmc.protocol", name = "common", versio protocol-codec = { group = "org.cloudburstmc.protocol", name = "bedrock-codec", version.ref = "protocol" } protocol-connection = { group = "org.cloudburstmc.protocol", name = "bedrock-connection", version.ref = "protocol-connection" } +blockstateupdater = { group = "org.cloudburstmc", name = "block-state-updater", version.ref = "blockstateupdater"} + [bundles] jackson = [ "jackson-annotations", "jackson-core", "jackson-dataformat-yaml" ] fastutil = [ "fastutil-int-int-maps", "fastutil-int-long-maps", "fastutil-int-byte-maps", "fastutil-int-boolean-maps", "fastutil-object-int-maps", "fastutil-object-object-maps" ] From 8a12878effed5cedc54b20dba91d91a7680f5cbf Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Tue, 12 Sep 2023 10:46:27 -0400 Subject: [PATCH 074/344] Fix jackson dependency for velocity launch (#4118) --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 36b09dfae..37bc0d6c3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,7 +3,7 @@ base-api = "1.0.0-SNAPSHOT" cumulus = "1.1.2" erosion = "1.0-20230406.174837-8" events = "1.1-SNAPSHOT" -jackson = "2.14.0" +jackson = { strictly = "2.14.0" } # Don't let other dependencies override fastutil = "8.5.2" netty = "4.1.80.Final" guava = "29.0-jre" From 69f89edb91ebd3cb60d1a5b3dd553d71ea52e382 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Wed, 13 Sep 2023 07:46:45 -0700 Subject: [PATCH 075/344] Pin all actions to sha commit hash (#4120) * Pin all actions to sha commit hash * Wrapper validation after checkoud for PR action --- .github/workflows/build.yml | 30 ++++++++++++++++++------------ .github/workflows/pullrequest.yml | 27 ++++++++++++++++++--------- 2 files changed, 36 insertions(+), 21 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cfbfd4ca6..6c5c15248 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,54 +19,59 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository and submodules - uses: actions/checkout@v3 + # See https://github.com/actions/checkout/commits + uses: actions/checkout@72f2cec99f417b1a1c5e2e88945068983b7965f9 with: submodules: recursive - name: Validate Gradle Wrapper - uses: gradle/wrapper-validation-action@v1 + # See https://github.com/gradle/wrapper-validation-action/commits + uses: gradle/wrapper-validation-action@56b90f209b02bf6d1deae490e9ef18b21a389cd4 - - uses: actions/setup-java@v3 + # See https://github.com/actions/setup-java/commits + - uses: actions/setup-java@4075bfc1b51bf22876335ae1cd589602d60d8758 with: java-version: 17 distribution: temurin - name: Build - uses: gradle/gradle-build-action@v2 + # See https://github.com/gradle/gradle-build-action/commits + uses: gradle/gradle-build-action@3bfe3a46584a206fb8361cdedd0647b0c4204232 with: arguments: build gradle-home-cache-cleanup: true - name: Archive artifacts (Geyser Fabric) - uses: actions/upload-artifact@v3 + # See https://github.com/actions/upload-artifact/commits + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 if: success() with: name: Geyser Fabric path: bootstrap/fabric/build/libs/Geyser-Fabric.jar if-no-files-found: error - name: Archive artifacts (Geyser Standalone) - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 if: success() with: name: Geyser Standalone path: bootstrap/standalone/build/libs/Geyser-Standalone.jar if-no-files-found: error - name: Archive artifacts (Geyser Spigot) - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 if: success() with: name: Geyser Spigot path: bootstrap/spigot/build/libs/Geyser-Spigot.jar if-no-files-found: error - name: Archive artifacts (Geyser BungeeCord) - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 if: success() with: name: Geyser BungeeCord path: bootstrap/bungeecord/build/libs/Geyser-BungeeCord.jar if-no-files-found: error - name: Archive artifacts (Geyser Velocity) - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 if: success() with: name: Geyser Velocity @@ -75,7 +80,7 @@ jobs: - name: Publish to Maven Repository if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@3bfe3a46584a206fb8361cdedd0647b0c4204232 env: ORG_GRADLE_PROJECT_geysermcUsername: ${{ vars.DEPLOY_USER }} ORG_GRADLE_PROJECT_geysermcPassword: ${{ secrets.DEPLOY_PASS }} @@ -107,7 +112,7 @@ jobs: rsync -P -e "ssh -o StrictHostKeyChecking=no -i id_ecdsa" metadata.json $DOWNLOADS_USERNAME@$DOWNLOADS_SERVER_IP:~/uploads/$project/$GITHUB_RUN_NUMBER/ - name: Publish to Modrinth - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@3bfe3a46584a206fb8361cdedd0647b0c4204232 if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} env: MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }} @@ -117,7 +122,8 @@ jobs: - name: Notify Discord if: ${{ (success() || failure()) && github.repository == 'GeyserMC/Geyser' }} - uses: Tim203/actions-git-discord-webhook@main + # See https://github.com/Tim203/actions-git-discord-webhook/commits + uses: Tim203/actions-git-discord-webhook@70f38ded3aca51635ec978ab4e1a58cd4cd0c2ff with: webhook_url: ${{ secrets.DISCORD_WEBHOOK }} status: ${{ job.status }} diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 925f19052..72f50ff97 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -17,13 +17,15 @@ jobs: runs-on: ubuntu-latest steps: - name: Set up JDK 17 - uses: actions/setup-java@v3 + # See https://github.com/actions/setup-java/commits + uses: actions/setup-java@4075bfc1b51bf22876335ae1cd589602d60d8758 with: java-version: 17 distribution: temurin - name: Check if the author has forked the API repo - uses: Kas-tle/find-forks-action@v1.0.1 + # See https://github.com/Kas-tle/find-forks-action/commits + uses: Kas-tle/find-forks-action@1b5447d1e3c7a8ed79583dd817cc5399686eed3a id: find_forks with: owner: GeyserMC @@ -41,47 +43,54 @@ jobs: ./gradlew publishToMavenLocal - name: Checkout repository and submodules - uses: actions/checkout@v3 + # See https://github.com/actions/checkout/commits + uses: actions/checkout@72f2cec99f417b1a1c5e2e88945068983b7965f9 with: submodules: recursive path: geyser + - name: Validate Gradle Wrapper + # See https://github.com/gradle/wrapper-validation-action/commits + uses: gradle/wrapper-validation-action@56b90f209b02bf6d1deae490e9ef18b21a389cd4 + - name: Build Geyser - uses: gradle/gradle-build-action@v2 + # See https://github.com/gradle/gradle-build-action/commits + uses: gradle/gradle-build-action@3bfe3a46584a206fb8361cdedd0647b0c4204232 with: arguments: build build-root-directory: geyser - name: Archive artifacts (Geyser Fabric) - uses: actions/upload-artifact@v3 + # See https://github.com/actions/upload-artifact/commits + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 if: success() with: name: Geyser Fabric path: geyser/bootstrap/fabric/build/libs/Geyser-Fabric.jar if-no-files-found: error - name: Archive artifacts (Geyser Standalone) - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 if: success() with: name: Geyser Standalone path: geyser/bootstrap/standalone/build/libs/Geyser-Standalone.jar if-no-files-found: error - name: Archive artifacts (Geyser Spigot) - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 if: success() with: name: Geyser Spigot path: geyser/bootstrap/spigot/build/libs/Geyser-Spigot.jar if-no-files-found: error - name: Archive artifacts (Geyser BungeeCord) - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 if: success() with: name: Geyser BungeeCord path: geyser/bootstrap/bungeecord/build/libs/Geyser-BungeeCord.jar if-no-files-found: error - name: Archive artifacts (Geyser Velocity) - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 if: success() with: name: Geyser Velocity From a443265e1d9984ea78ea6ed7e5038ef69c2a2e52 Mon Sep 17 00:00:00 2001 From: chris Date: Mon, 18 Sep 2023 22:56:20 +0200 Subject: [PATCH 076/344] Don't block chunk loading if an invalid skull is found (#4129) * Add null check in case skull texture value is null * Use variable for future result --- .../level/block/entity/SkullBlockEntityTranslator.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java index ace4d77b8..76cdbb5a4 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java @@ -107,7 +107,12 @@ public class SkullBlockEntityTranslator extends BlockEntityTranslator implements CompletableFuture texturesFuture = getTextures(owner, uuid); if (texturesFuture.isDone()) { try { - SkullCache.Skull skull = session.getSkullCache().putSkull(blockPosition, uuid, texturesFuture.get(), blockState); + String texture = texturesFuture.get(); + if (texture == null) { + session.getGeyser().getLogger().debug("Custom skull with invalid SkullOwner tag: " + blockPosition + " " + tag); + return null; + } + SkullCache.Skull skull = session.getSkullCache().putSkull(blockPosition, uuid, texture, blockState); return skull.getBlockDefinition(); } catch (InterruptedException | ExecutionException e) { session.getGeyser().getLogger().debug("Failed to acquire textures for custom skull: " + blockPosition + " " + tag); From 7a28ef5c5f98ea4b5603f1a3b3404bef2d2047b5 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Mon, 18 Sep 2023 23:01:43 -0400 Subject: [PATCH 077/344] Fix observer directions for 1.20.10+ (#4132) --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 37bc0d6c3..3e19eea95 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -12,7 +12,7 @@ websocket = "1.5.1" protocol = "3.0.0.Beta1-20230908.171156-106" protocol-connection = "3.0.0.Beta1-20230908.171156-105" raknet = "1.0.0.CR1-20230703.195238-9" -blockstateupdater="1.20.30-20230911.121922-2" +blockstateupdater="1.20.30-20230918.203831-4" mcauthlib = "d9d773e" mcprotocollib = "1.20-2-20230827.192136-1" adventure = "4.14.0" From dead91b929817aff6a4113bba26099f2318db271 Mon Sep 17 00:00:00 2001 From: Valaphee The Meerkat <32491319+valaphee@users.noreply.github.com> Date: Wed, 20 Sep 2023 15:52:37 +0200 Subject: [PATCH 078/344] Set BlockMapping.AIR (#4135) * Set BlockMapping.AIR, id is always 0, but this also ensures that the palette always has air * Rename BlockMapping.AIR to DEFAULT, as it does not have to represent AIR, and statically set it --- .../geyser/entity/type/living/merchant/VillagerEntity.java | 2 +- .../geyser/inventory/holder/BlockInventoryHolder.java | 2 +- .../org/geysermc/geyser/level/block/BlockStateValues.java | 6 +++--- .../org/geysermc/geyser/registry/type/BlockMapping.java | 2 +- .../inventory/chest/DoubleChestInventoryTranslator.java | 2 +- .../protocol/bedrock/BedrockBlockPickRequestTranslator.java | 2 +- .../bedrock/entity/player/BedrockActionTranslator.java | 2 +- .../protocol/java/level/JavaBlockUpdateTranslator.java | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/VillagerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/VillagerEntity.java index 84b8b5143..84fa7d1bd 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/VillagerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/VillagerEntity.java @@ -118,7 +118,7 @@ public class VillagerEntity extends AbstractMerchantEntity { // The bed block int blockId = session.getGeyser().getWorldManager().getBlockAt(session, bedPosition); - String fullIdentifier = BlockRegistries.JAVA_BLOCKS.getOrDefault(blockId, BlockMapping.AIR).getJavaIdentifier(); + String fullIdentifier = BlockRegistries.JAVA_BLOCKS.getOrDefault(blockId, BlockMapping.DEFAULT).getJavaIdentifier(); // Set the correct position offset and rotation when sleeping int bedRotation = 0; 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 c81fe6598..135e1057f 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 @@ -80,7 +80,7 @@ public class BlockInventoryHolder extends InventoryHolder { // and the bedrock block is vanilla int javaBlockId = session.getGeyser().getWorldManager().getBlockAt(session, session.getLastInteractionBlockPosition()); if (!BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.get().containsKey(javaBlockId)) { - String[] javaBlockString = BlockRegistries.JAVA_BLOCKS.getOrDefault(javaBlockId, BlockMapping.AIR).getJavaIdentifier().split("\\["); + String[] javaBlockString = BlockRegistries.JAVA_BLOCKS.getOrDefault(javaBlockId, BlockMapping.DEFAULT).getJavaIdentifier().split("\\["); if (isValidBlock(javaBlockString)) { // We can safely use this block inventory.setHolderPosition(session.getLastInteractionBlockPosition()); 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 6b09881bb..a686ba552 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 @@ -403,7 +403,7 @@ public final class BlockStateValues { * @return true if a piston can break the block */ public static boolean canPistonDestroyBlock(int state) { - return BlockRegistries.JAVA_BLOCKS.getOrDefault(state, BlockMapping.AIR).getPistonBehavior() == PistonBehavior.DESTROY; + return BlockRegistries.JAVA_BLOCKS.getOrDefault(state, BlockMapping.DEFAULT).getPistonBehavior() == PistonBehavior.DESTROY; } public static boolean canPistonMoveBlock(int javaId, boolean isPushing) { @@ -414,7 +414,7 @@ public final class BlockStateValues { if (PistonBlockEntityTranslator.isBlock(javaId)) { return !PISTON_VALUES.get(javaId); } - BlockMapping block = BlockRegistries.JAVA_BLOCKS.getOrDefault(javaId, BlockMapping.AIR); + BlockMapping block = BlockRegistries.JAVA_BLOCKS.getOrDefault(javaId, BlockMapping.DEFAULT); // Bedrock, End portal frames, etc. can't be moved if (block.getHardness() == -1.0d) { return false; @@ -511,7 +511,7 @@ public final class BlockStateValues { * @return The block's slipperiness */ public static float getSlipperiness(int state) { - String blockIdentifier = BlockRegistries.JAVA_BLOCKS.getOrDefault(state, BlockMapping.AIR).getJavaIdentifier(); + String blockIdentifier = BlockRegistries.JAVA_BLOCKS.getOrDefault(state, BlockMapping.DEFAULT).getJavaIdentifier(); return switch (blockIdentifier) { case "minecraft:slime_block" -> 0.8f; case "minecraft:ice", "minecraft:packed_ice" -> 0.98f; diff --git a/core/src/main/java/org/geysermc/geyser/registry/type/BlockMapping.java b/core/src/main/java/org/geysermc/geyser/registry/type/BlockMapping.java index 528999158..9745a8859 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/type/BlockMapping.java +++ b/core/src/main/java/org/geysermc/geyser/registry/type/BlockMapping.java @@ -36,7 +36,7 @@ import javax.annotation.Nullable; @Builder @Value public class BlockMapping { - public static BlockMapping AIR; + public static BlockMapping DEFAULT = BlockMapping.builder().javaIdentifier("minecraft:air").pistonBehavior(PistonBehavior.NORMAL).build();; String javaIdentifier; /** 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 23961694d..498bd418b 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 @@ -58,7 +58,7 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator { if (session.getLastInteractionPlayerPosition().equals(session.getPlayerEntity().getPosition())) { int javaBlockId = session.getGeyser().getWorldManager().getBlockAt(session, session.getLastInteractionBlockPosition()); if (!BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.get().containsKey(javaBlockId)) { - String[] javaBlockString = BlockRegistries.JAVA_BLOCKS.getOrDefault(javaBlockId, BlockMapping.AIR).getJavaIdentifier().split("\\["); + String[] javaBlockString = BlockRegistries.JAVA_BLOCKS.getOrDefault(javaBlockId, BlockMapping.DEFAULT).getJavaIdentifier().split("\\["); if (javaBlockString.length > 1 && (javaBlockString[0].equals("minecraft:chest") || javaBlockString[0].equals("minecraft:trapped_chest")) && !javaBlockString[1].contains("type=single")) { inventory.setHolderPosition(session.getLastInteractionBlockPosition()); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java index 19d15c04d..dd1a259fd 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java @@ -67,7 +67,7 @@ public class BedrockBlockPickRequestTranslator extends PacketTranslator Date: Mon, 25 Sep 2023 22:54:23 +0200 Subject: [PATCH 079/344] Fix: Don't allow client side gamemode changes even if rogue plugins send a level 4 op permission... (#4148) --- .../registry/PacketTranslatorRegistry.java | 2 - .../BedrockRequestPermissionsPacket.java | 43 +++++++++++++++++++ .../BedrockSetDefaultGameTypeTranslator.java | 2 +- .../BedrockSetDifficultyTranslator.java | 2 +- .../BedrockSetPlayerGameTypeTranslator.java | 2 +- 5 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockRequestPermissionsPacket.java diff --git a/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java b/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java index dbc8e2e26..61999d4f6 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java +++ b/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java @@ -29,7 +29,6 @@ import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundDe import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundTabListPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundLightUpdatePacket; import io.netty.channel.EventLoop; -import org.cloudburstmc.protocol.bedrock.packet.RequestPermissionsPacket; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.registry.loader.RegistryLoaders; import org.geysermc.geyser.session.GeyserSession; @@ -47,7 +46,6 @@ public class PacketTranslatorRegistry extends AbstractMappedRegistry { + + @Override + public void translate(GeyserSession session, RequestPermissionsPacket packet) { + session.sendAdventureSettings(); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetDefaultGameTypeTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetDefaultGameTypeTranslator.java index c818cc910..df28f7ca7 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetDefaultGameTypeTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetDefaultGameTypeTranslator.java @@ -41,7 +41,7 @@ public class BedrockSetDefaultGameTypeTranslator extends PacketTranslator= 2 || session.hasPermission("geyser.settings.server")) { + if (session.getOpPermissionLevel() >= 2 && session.hasPermission("geyser.settings.server")) { session.getGeyser().getWorldManager().setDefaultGameMode(session, GameMode.byId(packet.getGamemode())); } // Stop the client from updating their own Gamemode without telling the server diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetDifficultyTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetDifficultyTranslator.java index a36aa77df..b996a96b1 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetDifficultyTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetDifficultyTranslator.java @@ -39,7 +39,7 @@ public class BedrockSetDifficultyTranslator extends PacketTranslator= 2 || session.hasPermission("geyser.settings.server")) { + if (session.getOpPermissionLevel() >= 2 && session.hasPermission("geyser.settings.server")) { if (packet.getDifficulty() != session.getWorldCache().getDifficulty().ordinal()) { session.getGeyser().getWorldManager().setDifficulty(session, Difficulty.from(packet.getDifficulty())); } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetPlayerGameTypeTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetPlayerGameTypeTranslator.java index a1c2c2987..2d8d420f8 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetPlayerGameTypeTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetPlayerGameTypeTranslator.java @@ -45,7 +45,7 @@ public class BedrockSetPlayerGameTypeTranslator extends PacketTranslator= 2 || session.hasPermission("geyser.settings.server")) { + if (session.getOpPermissionLevel() >= 2 && session.hasPermission("geyser.settings.server")) { if (packet.getGamemode() != session.getGameMode().ordinal()) { // Bedrock has more Gamemodes than Java, leading to cases 5 (for "default") and 6 (for "spectator") being sent // https://github.com/CloudburstMC/Protocol/blob/3.0/bedrock-codec/src/main/java/org/cloudburstmc/protocol/bedrock/data/GameType.java From 5276a1e2ba7a32ed47b8fcea64f13f12323b3ecd Mon Sep 17 00:00:00 2001 From: Spongecade Date: Wed, 27 Sep 2023 09:55:54 -0500 Subject: [PATCH 080/344] Update Minecraft Wiki links to new domain (#4151) --- .../org/geysermc/geyser/inventory/item/TippedArrowPotion.java | 2 +- .../main/java/org/geysermc/geyser/text/MinecraftLocale.java | 2 +- .../protocol/java/entity/JavaEntityEventTranslator.java | 2 +- .../translator/protocol/java/level/JavaSetTimeTranslator.java | 2 +- .../main/java/org/geysermc/geyser/util/AttributeUtils.java | 2 +- core/src/main/java/org/geysermc/geyser/util/BlockUtils.java | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/TippedArrowPotion.java b/core/src/main/java/org/geysermc/geyser/inventory/item/TippedArrowPotion.java index ddc44fbc4..e45667fe2 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/item/TippedArrowPotion.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/item/TippedArrowPotion.java @@ -31,7 +31,7 @@ import java.util.Locale; /** * Potion identifiers and their respective Bedrock IDs used with arrows. - * https://minecraft.gamepedia.com/Arrow#Item_Data + * https://minecraft.wiki/w/Arrow#Data_values */ @Getter public enum TippedArrowPotion { diff --git a/core/src/main/java/org/geysermc/geyser/text/MinecraftLocale.java b/core/src/main/java/org/geysermc/geyser/text/MinecraftLocale.java index 260b45136..00866eda3 100644 --- a/core/src/main/java/org/geysermc/geyser/text/MinecraftLocale.java +++ b/core/src/main/java/org/geysermc/geyser/text/MinecraftLocale.java @@ -76,7 +76,7 @@ public class MinecraftLocale { public static void downloadAndLoadLocale(String locale) { locale = locale.toLowerCase(Locale.ROOT); if (locale.equals("nb_no")) { - // Different locale code - https://minecraft.fandom.com/wiki/Language + // Different locale code - https://minecraft.wiki/w/Language locale = "no_no"; } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaEntityEventTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaEntityEventTranslator.java index 50582974d..4b1483bbf 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaEntityEventTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaEntityEventTranslator.java @@ -120,7 +120,7 @@ public class JavaEntityEventTranslator extends PacketTranslator 2.0; case "stone" -> 4.0; case "iron" -> 6.0; @@ -100,7 +100,7 @@ public final class BlockUtils { return true; } - // https://minecraft.gamepedia.com/Breaking + // https://minecraft.wiki/w/Breaking private static double calculateBreakTime(double blockHardness, String toolTier, boolean canHarvestWithHand, boolean correctTool, boolean canTierMineBlock, String toolType, boolean isShearsEffective, int toolEfficiencyLevel, int hasteLevel, int miningFatigueLevel, boolean insideOfWaterWithoutAquaAffinity, boolean onGround) { From c2cd99c82939f19ffaf6310e4b84458b70c550fc Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Fri, 29 Sep 2023 17:14:49 -0400 Subject: [PATCH 081/344] Support Java 1.20.2 (#4112) * Initial pass for 1.20.2, compiling * Remove unused level events * handle null GameProfile in ClientboundPlayerInfoUpdatePacket * Handle level events BRUSH_BLOCK_COMPLETE and EGG_CRACK * Account for null tag in DecoratedPotBlockEntityTranslator * Explicitly show that 1.20.31 is supported --- README.md | 2 +- .../java/org/geysermc/geyser/GeyserImpl.java | 1 - .../geyser/level/GeyserAdvancement.java | 5 -- .../geysermc/geyser/network/GameProtocol.java | 8 ++- .../registry/PacketTranslatorRegistry.java | 4 +- .../geyser/session/GeyserSession.java | 14 ++-- .../geyser/session/cache/TagCache.java | 5 +- .../DecoratedPotBlockEntityTranslator.java | 4 ++ .../BedrockNetworkStackLatencyTranslator.java | 2 +- .../java/JavaCustomPayloadTranslator.java | 4 +- .../java/JavaCustomQueryTranslator.java | 4 +- .../java/JavaDisconnectTranslator.java | 2 +- .../java/JavaGameProfileTranslator.java | 9 +++ .../java/JavaKeepAliveTranslator.java | 2 +- .../protocol/java/JavaLoginTranslator.java | 57 +++------------ .../protocol/java/JavaPingTranslator.java | 4 +- .../java/JavaRegistryDataTranslator.java | 67 +++++++++++++++++ .../protocol/java/JavaRespawnTranslator.java | 14 ++-- .../java/JavaUpdateTagsTranslator.java | 2 +- .../entity/JavaUpdateMobEffectTranslator.java | 3 +- .../JavaPlayerInfoUpdateTranslator.java | 31 +++++--- .../entity/spawn/JavaAddEntityTranslator.java | 38 +++++++++- .../entity/spawn/JavaAddPlayerTranslator.java | 72 ------------------- .../JavaChunkBatchFinishedTranslator.java | 44 ++++++++++++ .../java/level/JavaLevelEventTranslator.java | 6 ++ .../geyser/util/PluginMessageUtils.java | 2 +- core/src/main/resources/mappings | 2 +- gradle/libs.versions.toml | 2 +- 28 files changed, 243 insertions(+), 167 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaRegistryDataTranslator.java delete mode 100644 core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/spawn/JavaAddPlayerTranslator.java create mode 100644 core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaChunkBatchFinishedTranslator.java diff --git a/README.md b/README.md index 7f9f6fe9e..d78386687 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,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.20.0 - 1.20.30 and Minecraft Java 1.20/1.20.1. +### Currently supporting Minecraft Bedrock 1.20.0 - 1.20.31 and Minecraft Java 1.20/1.20.1. ## 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/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index d13836e9a..4a5f16bfa 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -71,7 +71,6 @@ import org.geysermc.geyser.level.WorldManager; import org.geysermc.geyser.network.netty.GeyserServer; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.Registries; -import org.geysermc.geyser.registry.loader.RegistryLoaders; import org.geysermc.geyser.scoreboard.ScoreboardUpdater; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.PendingMicrosoftAuthentication; diff --git a/core/src/main/java/org/geysermc/geyser/level/GeyserAdvancement.java b/core/src/main/java/org/geysermc/geyser/level/GeyserAdvancement.java index fc3c86dd4..936248afe 100644 --- a/core/src/main/java/org/geysermc/geyser/level/GeyserAdvancement.java +++ b/core/src/main/java/org/geysermc/geyser/level/GeyserAdvancement.java @@ -52,11 +52,6 @@ public class GeyserAdvancement { return this.advancement.getId(); } - @NonNull - public List getCriteria() { - return this.advancement.getCriteria(); - } - @NonNull public List> getRequirements() { return this.advancement.getRequirements(); diff --git a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java index 63cce329c..fb9684f77 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java @@ -46,7 +46,9 @@ public final class GameProtocol { * Default Bedrock codec that should act as a fallback. Should represent the latest available * release of the game that Geyser supports. */ - public static final BedrockCodec DEFAULT_BEDROCK_CODEC = Bedrock_v618.CODEC; + public static final BedrockCodec DEFAULT_BEDROCK_CODEC = Bedrock_v618.CODEC.toBuilder() + .minecraftVersion("1.20.31") + .build(); /** * A list of all supported Bedrock versions that can join Geyser @@ -66,7 +68,9 @@ public final class GameProtocol { SUPPORTED_BEDROCK_CODECS.add(Bedrock_v594.CODEC.toBuilder() .minecraftVersion("1.20.10/1.20.15") .build()); - SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC); + SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC.toBuilder() + .minecraftVersion("1.20.30/1.20.31") + .build()); } /** diff --git a/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java b/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java index 61999d4f6..e37f8aa64 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java +++ b/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java @@ -27,6 +27,7 @@ package org.geysermc.geyser.registry; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundDelimiterPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundTabListPacket; +import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundChunkBatchStartPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundLightUpdatePacket; import io.netty.channel.EventLoop; import org.geysermc.geyser.GeyserImpl; @@ -43,9 +44,10 @@ public class PacketTranslatorRegistry extends AbstractMappedRegistry> IGNORED_PACKETS = Collections.newSetFromMap(new IdentityHashMap<>()); static { + IGNORED_PACKETS.add(ClientboundChunkBatchStartPacket.class); // we don't track chunk batch sizes/periods + IGNORED_PACKETS.add(ClientboundDelimiterPacket.class); // Not implemented, spams logs IGNORED_PACKETS.add(ClientboundLightUpdatePacket.class); // Light is handled on Bedrock for us IGNORED_PACKETS.add(ClientboundTabListPacket.class); // Cant be implemented in Bedrock - IGNORED_PACKETS.add(ClientboundDelimiterPacket.class); // Not implemented, spams logs } protected PacketTranslatorRegistry() { diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index f7d362e0d..5c9725fae 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -45,15 +45,15 @@ import com.github.steveice10.mc.protocol.data.game.setting.ChatVisibility; import com.github.steveice10.mc.protocol.data.game.setting.SkinPart; import com.github.steveice10.mc.protocol.data.game.statistic.CustomStatistic; import com.github.steveice10.mc.protocol.data.game.statistic.Statistic; +import com.github.steveice10.mc.protocol.packet.common.serverbound.ServerboundClientInformationPacket; import com.github.steveice10.mc.protocol.packet.handshake.serverbound.ClientIntentionPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatCommandPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundClientInformationPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundPlayerAbilitiesPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundPlayerActionPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundUseItemPacket; -import com.github.steveice10.mc.protocol.packet.login.serverbound.ServerboundCustomQueryPacket; +import com.github.steveice10.mc.protocol.packet.login.serverbound.ServerboundCustomQueryAnswerPacket; import com.github.steveice10.packetlib.BuiltinFlags; import com.github.steveice10.packetlib.Session; import com.github.steveice10.packetlib.event.session.ConnectedEvent; @@ -292,7 +292,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { private Vector2i lastChunkPosition = null; @Setter private int clientRenderDistance = -1; - private int serverRenderDistance; + private int serverRenderDistance = -1; // Exposed for GeyserConnect usage protected boolean sentSpawnPacket; @@ -1665,7 +1665,8 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { } private void sendDownstreamPacket0(Packet packet) { - if (protocol.getState().equals(ProtocolState.GAME) || packet.getClass() == ServerboundCustomQueryPacket.class) { + ProtocolState state = protocol.getState(); + if (state == ProtocolState.GAME || state == ProtocolState.CONFIGURATION || packet.getClass() == ServerboundCustomQueryAnswerPacket.class) { downstream.sendPacket(packet); } else { geyser.getLogger().debug("Tried to send downstream packet " + packet.getClass().getSimpleName() + " before connected to the server"); @@ -1824,8 +1825,11 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { if (clientRenderDistance != -1) { // The client has sent a render distance return clientRenderDistance; + } else if (serverRenderDistance != -1) { + // only known once ClientboundLoginPacket is received + return serverRenderDistance; } - return serverRenderDistance; + return 2; // unfortunate default until we got more info } // We need to send our skin parts to the server otherwise java sees us with no hat, jacket etc diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java index ab1dfbe2b..5acfc1f09 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java @@ -25,9 +25,10 @@ package org.geysermc.geyser.session.cache; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundUpdateTagsPacket; +import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundUpdateTagsPacket; import it.unimi.dsi.fastutil.ints.IntList; import it.unimi.dsi.fastutil.ints.IntLists; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.GeyserLogger; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.type.Item; @@ -112,7 +113,7 @@ public class TagCache { } } - private IntList load(int[] tags) { + private IntList load(int @Nullable[] tags) { if (tags == null) { return IntLists.EMPTY_LIST; } diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DecoratedPotBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DecoratedPotBlockEntityTranslator.java index e60342b27..1774d9c76 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DecoratedPotBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DecoratedPotBlockEntityTranslator.java @@ -41,6 +41,10 @@ public class DecoratedPotBlockEntityTranslator extends BlockEntityTranslator { @Override public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) { + if (tag == null) { + return; + } + // exact same format if (tag.get("sherds") instanceof ListTag sherds) { List translated = new ArrayList<>(4); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockNetworkStackLatencyTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockNetworkStackLatencyTranslator.java index 1ccd5ced9..412a97e3a 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockNetworkStackLatencyTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockNetworkStackLatencyTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.bedrock; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundKeepAlivePacket; +import com.github.steveice10.mc.protocol.packet.common.serverbound.ServerboundKeepAlivePacket; import org.cloudburstmc.protocol.bedrock.data.AttributeData; import org.cloudburstmc.protocol.bedrock.packet.NetworkStackLatencyPacket; import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCustomPayloadTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCustomPayloadTranslator.java index cf5cfa198..2a7202b0c 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCustomPayloadTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCustomPayloadTranslator.java @@ -25,8 +25,8 @@ package org.geysermc.geyser.translator.protocol.java; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundCustomPayloadPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundCustomPayloadPacket; +import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundCustomPayloadPacket; +import com.github.steveice10.mc.protocol.packet.common.serverbound.ServerboundCustomPayloadPacket; import com.google.common.base.Charsets; import org.cloudburstmc.protocol.bedrock.packet.TransferPacket; import org.cloudburstmc.protocol.bedrock.packet.UnknownPacket; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCustomQueryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCustomQueryTranslator.java index 89df63898..0eaef91f1 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCustomQueryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCustomQueryTranslator.java @@ -26,7 +26,7 @@ package org.geysermc.geyser.translator.protocol.java; import com.github.steveice10.mc.protocol.packet.login.clientbound.ClientboundCustomQueryPacket; -import com.github.steveice10.mc.protocol.packet.login.serverbound.ServerboundCustomQueryPacket; +import com.github.steveice10.mc.protocol.packet.login.serverbound.ServerboundCustomQueryAnswerPacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; @@ -41,7 +41,7 @@ public class JavaCustomQueryTranslator extends PacketTranslator CONFIGURATION + */ @Translator(packet = ClientboundGameProfilePacket.class) public class JavaGameProfileTranslator extends PacketTranslator { @@ -65,5 +70,9 @@ public class JavaGameProfileTranslator extends PacketTranslator { @@ -64,42 +55,22 @@ public class JavaLoginTranslator extends PacketTranslator dimensions = session.getDimensions(); - dimensions.clear(); - - JavaDimension.load(packet.getRegistry(), dimensions); - - Int2ObjectMap chatTypes = session.getChatTypes(); - chatTypes.clear(); - for (CompoundTag tag : JavaCodecUtil.iterateAsTag(packet.getRegistry().get("minecraft:chat_type"))) { - // The ID is NOT ALWAYS THE SAME! ViaVersion as of 1.19 adds two registry entries that do NOT match vanilla. - int id = ((IntTag) tag.get("id")).getValue(); - CompoundTag element = tag.get("element"); - CompoundTag chat = element.get("chat"); - TextDecoration textDecoration = null; - if (chat != null) { - textDecoration = new TextDecoration(chat); - } - chatTypes.put(id, textDecoration); - } + PlayerSpawnInfo spawnInfo = packet.getCommonPlayerSpawnInfo(); // If the player is already initialized and a join game packet is sent, they // are swapping servers if (session.isSpawned()) { - String fakeDim = DimensionUtils.getTemporaryDimension(session.getDimension(), packet.getDimension()); + String fakeDim = DimensionUtils.getTemporaryDimension(session.getDimension(), spawnInfo.getDimension()); DimensionUtils.switchDimension(session, fakeDim); session.getWorldCache().removeScoreboard(); } - session.setWorldName(packet.getWorldName()); + session.setWorldName(spawnInfo.getWorldName()); session.setLevels(packet.getWorldNames()); - BiomeTranslator.loadServerBiomes(session, packet.getRegistry()); - session.getTagCache().clear(); + session.setGameMode(spawnInfo.getGameMode()); - session.setGameMode(packet.getGameMode()); - - String newDimension = packet.getDimension(); + String newDimension = spawnInfo.getDimension(); boolean needsSpawnPacket = !session.isSentSpawnPacket(); if (needsSpawnPacket) { @@ -114,11 +85,11 @@ public class JavaLoginTranslator extends PacketTranslator { + + @Override + public void translate(GeyserSession session, ClientboundRegistryDataPacket packet) { + Map dimensions = session.getDimensions(); + dimensions.clear(); + JavaDimension.load(packet.getRegistry(), dimensions); + + Int2ObjectMap chatTypes = session.getChatTypes(); + chatTypes.clear(); + for (CompoundTag tag : JavaCodecUtil.iterateAsTag(packet.getRegistry().get("minecraft:chat_type"))) { + // The ID is NOT ALWAYS THE SAME! ViaVersion as of 1.19 adds two registry entries that do NOT match vanilla. + int id = ((IntTag) tag.get("id")).getValue(); + CompoundTag element = tag.get("element"); + CompoundTag chat = element.get("chat"); + TextDecoration textDecoration = null; + if (chat != null) { + textDecoration = new TextDecoration(chat); + } + chatTypes.put(id, textDecoration); + } + + BiomeTranslator.loadServerBiomes(session, packet.getRegistry()); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaRespawnTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaRespawnTranslator.java index 71f5dc8fc..fb7536b19 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaRespawnTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaRespawnTranslator.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.translator.protocol.java; +import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerSpawnInfo; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundRespawnPacket; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.LevelEvent; @@ -46,6 +47,7 @@ public class JavaRespawnTranslator extends PacketTranslator { @@ -50,13 +52,24 @@ public class JavaPlayerInfoUpdateTranslator extends PacketTranslator definition = Registries.ENTITY_DEFINITIONS.get(packet.getType()); + if (definition == null) { + session.getGeyser().getLogger().warning("Could not find an entity definition with type " + packet.getType()); + return; + } + Vector3f position = Vector3f.from(packet.getX(), packet.getY(), packet.getZ()); Vector3f motion = Vector3f.from(packet.getMotionX(), packet.getMotionY(), packet.getMotionZ()); float yaw = packet.getYaw(); float pitch = packet.getPitch(); float headYaw = packet.getHeadYaw(); - EntityDefinition definition = Registries.ENTITY_DEFINITIONS.get(packet.getType()); - if (definition == null) { - session.getGeyser().getLogger().warning("Could not find an entity definition with type " + packet.getType()); + if (packet.getType() == EntityType.PLAYER) { + + PlayerEntity entity; + if (packet.getUuid().equals(session.getPlayerEntity().getUuid())) { + // Server is sending a fake version of the current player + entity = new PlayerEntity(session, packet.getEntityId(), session.getEntityCache().getNextEntityId().incrementAndGet(), + session.getPlayerEntity().getUuid(), position, motion, yaw, pitch, headYaw, session.getPlayerEntity().getUsername(), + session.getPlayerEntity().getTexturesProperty()); + } else { + entity = session.getEntityCache().getPlayerEntity(packet.getUuid()); + if (entity == null) { + GeyserImpl.getInstance().getLogger().error(GeyserLocale.getLocaleStringLog("geyser.entity.player.failed_list", packet.getUuid())); + return; + } + + entity.setEntityId(packet.getEntityId()); + entity.setPosition(position); + entity.setYaw(yaw); + entity.setPitch(pitch); + entity.setHeadYaw(headYaw); + entity.setMotion(motion); + } + session.getEntityCache().cacheEntity(entity); + + entity.sendPlayer(); + SkinManager.requestAndHandleSkinAndCape(entity, session, null); return; } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/spawn/JavaAddPlayerTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/spawn/JavaAddPlayerTranslator.java deleted file mode 100644 index 20a5f8213..000000000 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/spawn/JavaAddPlayerTranslator.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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.translator.protocol.java.entity.spawn; - -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.spawn.ClientboundAddPlayerPacket; -import org.cloudburstmc.math.vector.Vector3f; -import org.geysermc.geyser.GeyserImpl; -import org.geysermc.geyser.entity.type.player.PlayerEntity; -import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.skin.SkinManager; -import org.geysermc.geyser.text.GeyserLocale; -import org.geysermc.geyser.translator.protocol.PacketTranslator; -import org.geysermc.geyser.translator.protocol.Translator; - -@Translator(packet = ClientboundAddPlayerPacket.class) -public class JavaAddPlayerTranslator extends PacketTranslator { - - @Override - public void translate(GeyserSession session, ClientboundAddPlayerPacket packet) { - Vector3f position = Vector3f.from(packet.getX(), packet.getY(), packet.getZ()); - float yaw = packet.getYaw(); - float pitch = packet.getPitch(); - float headYaw = packet.getYaw(); - - PlayerEntity entity; - if (packet.getUuid().equals(session.getPlayerEntity().getUuid())) { - // Server is sending a fake version of the current player - entity = new PlayerEntity(session, packet.getEntityId(), session.getEntityCache().getNextEntityId().incrementAndGet(), - session.getPlayerEntity().getUuid(), position, Vector3f.ZERO, yaw, pitch, headYaw, session.getPlayerEntity().getUsername(), - session.getPlayerEntity().getTexturesProperty()); - } else { - entity = session.getEntityCache().getPlayerEntity(packet.getUuid()); - if (entity == null) { - GeyserImpl.getInstance().getLogger().error(GeyserLocale.getLocaleStringLog("geyser.entity.player.failed_list", packet.getUuid())); - return; - } - - entity.setEntityId(packet.getEntityId()); - entity.setPosition(position); - entity.setYaw(yaw); - entity.setPitch(pitch); - entity.setHeadYaw(headYaw); - } - session.getEntityCache().cacheEntity(entity); - - entity.sendPlayer(); - SkinManager.requestAndHandleSkinAndCape(entity, session, null); - } -} diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaChunkBatchFinishedTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaChunkBatchFinishedTranslator.java new file mode 100644 index 000000000..67f56111a --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaChunkBatchFinishedTranslator.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2019-2023 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.translator.protocol.java.level; + +import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundChunkBatchFinishedPacket; +import com.github.steveice10.mc.protocol.packet.ingame.serverbound.level.ServerboundChunkBatchReceivedPacket; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.protocol.PacketTranslator; +import org.geysermc.geyser.translator.protocol.Translator; + +@Translator(packet = ClientboundChunkBatchFinishedPacket.class) +public class JavaChunkBatchFinishedTranslator extends PacketTranslator { + + @Override + public void translate(GeyserSession session, ClientboundChunkBatchFinishedPacket packet) { + // server just sent a batch of LevelChunkWithLightPackets + // the vanilla client uses a ChunkBatchSizeCalculator to calculate the desiredChunksPerTick, + // but currently we just send an arbitrary value. server clamps the value between 0.01 and 64. + session.sendDownstreamPacket(new ServerboundChunkBatchReceivedPacket(20)); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelEventTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelEventTranslator.java index d59b40b8f..aecb304db 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelEventTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelEventTranslator.java @@ -31,6 +31,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.Clientb import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.protocol.bedrock.data.ParticleType; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.cloudburstmc.protocol.bedrock.packet.LevelEventGenericPacket; import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket; @@ -103,6 +104,10 @@ public class JavaLevelEventTranslator extends PacketTranslator { + effectPacket.setType(ParticleType.BRUSH_DUST); + session.playSoundEvent(SoundEvent.BRUSH_COMPLETED, pos); // todo 1.20.2 verify this + } case COMPOSTER -> { effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_CROP_GROWTH); @@ -224,6 +229,7 @@ public class JavaLevelEventTranslator extends PacketTranslator effectPacket.setType(ParticleType.VILLAGER_HAPPY); // both the lil green sparkle case ENDERDRAGON_FIREBALL_EXPLODE -> { effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_EYE_OF_ENDER_DEATH); // TODO diff --git a/core/src/main/java/org/geysermc/geyser/util/PluginMessageUtils.java b/core/src/main/java/org/geysermc/geyser/util/PluginMessageUtils.java index 032dd2af7..f6b91388f 100644 --- a/core/src/main/java/org/geysermc/geyser/util/PluginMessageUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/PluginMessageUtils.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.util; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundCustomPayloadPacket; +import com.github.steveice10.mc.protocol.packet.common.serverbound.ServerboundCustomPayloadPacket; import com.google.common.base.Charsets; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.session.GeyserSession; diff --git a/core/src/main/resources/mappings b/core/src/main/resources/mappings index 587220aaf..31ce17e12 160000 --- a/core/src/main/resources/mappings +++ b/core/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit 587220aafb55e80f2a70d6eac2d4b89dc0a005bd +Subproject commit 31ce17e12e991bd841270b99f461641093f42564 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3e19eea95..f654255fa 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,7 +14,7 @@ protocol-connection = "3.0.0.Beta1-20230908.171156-105" raknet = "1.0.0.CR1-20230703.195238-9" blockstateupdater="1.20.30-20230918.203831-4" mcauthlib = "d9d773e" -mcprotocollib = "1.20-2-20230827.192136-1" +mcprotocollib = "1.20.2-1-20230926.224810-3" adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" From 5d30019bc78a860df8e9bc1cd31d3650a411c1eb Mon Sep 17 00:00:00 2001 From: Hasan <52300558+hasankayra04@users.noreply.github.com> Date: Sat, 30 Sep 2023 22:46:21 +0300 Subject: [PATCH 082/344] Change supported java version - Update README.md (#4163) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d78386687..6c26f3744 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,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.20.0 - 1.20.31 and Minecraft Java 1.20/1.20.1. +### Currently supporting Minecraft Bedrock 1.20.0 - 1.20.31 and Minecraft Java 1.20.2 ## Setting Up Take a look [here](https://wiki.geysermc.org/geyser/setup/) for how to set up Geyser. From 1d75d084a787e7c3577ab144447f1e3c9d38084c Mon Sep 17 00:00:00 2001 From: rtm516 Date: Sat, 30 Sep 2023 22:18:57 +0100 Subject: [PATCH 083/344] Force loading help-text using utf-8 to fix encoding errors (#4165) --- core/src/main/java/org/geysermc/geyser/GeyserMain.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/GeyserMain.java b/core/src/main/java/org/geysermc/geyser/GeyserMain.java index 8726c1b24..4e60a79b8 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserMain.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserMain.java @@ -28,6 +28,7 @@ package org.geysermc.geyser; import javax.swing.*; import java.io.InputStream; import java.lang.reflect.Method; +import java.nio.charset.StandardCharsets; import java.util.Locale; import java.util.Scanner; @@ -60,7 +61,7 @@ public class GeyserMain { helpStream = GeyserMain.class.getClassLoader().getResourceAsStream("languages/run-help/en_US.txt"); } - Scanner help = new Scanner(helpStream).useDelimiter("\\Z"); + Scanner help = new Scanner(helpStream, StandardCharsets.UTF_8).useDelimiter("\\Z"); String line = ""; while (help.hasNext()) { line = help.next(); From 34ff8c121740a57665765bbcee6e643ebfd89a1d Mon Sep 17 00:00:00 2001 From: chris Date: Sun, 1 Oct 2023 07:17:53 +0200 Subject: [PATCH 084/344] Allow extensions to load other extension's classes, and store extensions by IDs instead of name (#3946) - the extensionmanagers `extension` method now takes in a extension id instead of name - extension folders are now created using extension id's - Extensions can load classes from other extensions now - Added warning about external class loading - Wherever applicable: store extensions internally by id instead of name --- .../api/extension/ExtensionManager.java | 8 ++--- .../platform/spigot/GeyserSpigotPlugin.java | 2 +- .../extension/GeyserExtensionClassLoader.java | 36 +++++++++++++------ .../extension/GeyserExtensionLoader.java | 29 ++++++++++----- .../extension/GeyserExtensionManager.java | 10 +++--- 5 files changed, 56 insertions(+), 29 deletions(-) diff --git a/api/src/main/java/org/geysermc/geyser/api/extension/ExtensionManager.java b/api/src/main/java/org/geysermc/geyser/api/extension/ExtensionManager.java index a9d0d7376..5226221df 100644 --- a/api/src/main/java/org/geysermc/geyser/api/extension/ExtensionManager.java +++ b/api/src/main/java/org/geysermc/geyser/api/extension/ExtensionManager.java @@ -36,13 +36,13 @@ import java.util.Collection; public abstract class ExtensionManager { /** - * Gets an extension with the given name. + * Gets an extension by the given ID. * - * @param name the name of the extension - * @return an extension with the given name + * @param id the ID of the extension + * @return an extension with the given ID */ @Nullable - public abstract Extension extension(@NonNull String name); + public abstract Extension extension(@NonNull String id); /** * Enables the given {@link Extension}. diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java index b932962a0..cfb6ff5ae 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java @@ -194,7 +194,7 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { commandMap.register(extension.description().id(), "geyserext", pluginCommand); } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException ex) { - this.geyserLogger.error("Failed to construct PluginCommand for extension " + extension.description().name(), ex); + this.geyserLogger.error("Failed to construct PluginCommand for extension " + extension.name(), ex); } } } diff --git a/core/src/main/java/org/geysermc/geyser/extension/GeyserExtensionClassLoader.java b/core/src/main/java/org/geysermc/geyser/extension/GeyserExtensionClassLoader.java index 30d6ac856..dca11dfcd 100644 --- a/core/src/main/java/org/geysermc/geyser/extension/GeyserExtensionClassLoader.java +++ b/core/src/main/java/org/geysermc/geyser/extension/GeyserExtensionClassLoader.java @@ -27,6 +27,7 @@ package org.geysermc.geyser.extension; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.extension.Extension; import org.geysermc.geyser.api.extension.ExtensionDescription; import org.geysermc.geyser.api.extension.exception.InvalidExtensionException; @@ -39,14 +40,17 @@ import java.nio.file.Path; public class GeyserExtensionClassLoader extends URLClassLoader { private final GeyserExtensionLoader loader; + private final ExtensionDescription description; private final Object2ObjectMap> classes = new Object2ObjectOpenHashMap<>(); + private boolean warnedForExternalClassAccess; - public GeyserExtensionClassLoader(GeyserExtensionLoader loader, ClassLoader parent, Path path) throws MalformedURLException { + public GeyserExtensionClassLoader(GeyserExtensionLoader loader, ClassLoader parent, Path path, ExtensionDescription description) throws MalformedURLException { super(new URL[] { path.toUri().toURL() }, parent); this.loader = loader; + this.description = description; } - public Extension load(ExtensionDescription description) throws InvalidExtensionException { + public Extension load() throws InvalidExtensionException { try { Class jarClass; try { @@ -76,22 +80,32 @@ public class GeyserExtensionClassLoader extends URLClassLoader { } protected Class findClass(String name, boolean checkGlobal) throws ClassNotFoundException { - if (name.startsWith("org.geysermc.geyser.") || name.startsWith("net.minecraft.")) { - throw new ClassNotFoundException(name); - } - Class result = this.classes.get(name); if (result == null) { - result = super.findClass(name); - if (result == null && checkGlobal) { - result = this.loader.classByName(name); + // Try to find class in current extension + try { + result = super.findClass(name); + } catch (ClassNotFoundException ignored) { + // If class is not found in current extension, check in the global class loader + // This is used for classes that are not in the extension, but are in other extensions + if (checkGlobal) { + if (!warnedForExternalClassAccess) { + GeyserImpl.getInstance().getLogger().warning("Extension " + this.description.name() + " loads class " + name + " from an external source. " + + "This can change at any time and break the extension, additionally to potentially causing unexpected behaviour!"); + warnedForExternalClassAccess = true; + } + result = this.loader.classByName(name); + } } if (result != null) { + // If class is found, cache it this.loader.setClass(name, result); + this.classes.put(name, result); + } else { + // If class is not found, throw exception + throw new ClassNotFoundException(name); } - - this.classes.put(name, result); } return result; } diff --git a/core/src/main/java/org/geysermc/geyser/extension/GeyserExtensionLoader.java b/core/src/main/java/org/geysermc/geyser/extension/GeyserExtensionLoader.java index 7e998e413..dac5ee802 100644 --- a/core/src/main/java/org/geysermc/geyser/extension/GeyserExtensionLoader.java +++ b/core/src/main/java/org/geysermc/geyser/extension/GeyserExtensionLoader.java @@ -66,26 +66,38 @@ public class GeyserExtensionLoader extends ExtensionLoader { } Path parentFile = path.getParent(); - Path dataFolder = parentFile.resolve(description.name()); + + // Extension folders used to be created by name; this changes them to the ID + Path oldDataFolder = parentFile.resolve(description.name()); + Path dataFolder = parentFile.resolve(description.id()); + + if (Files.exists(oldDataFolder) && Files.isDirectory(oldDataFolder) && !oldDataFolder.equals(dataFolder)) { + try { + Files.move(oldDataFolder, dataFolder, StandardCopyOption.REPLACE_EXISTING); + } catch (IOException e) { + throw new InvalidExtensionException("Failed to move data folder for extension " + description.name(), e); + } + } + if (Files.exists(dataFolder) && !Files.isDirectory(dataFolder)) { throw new InvalidExtensionException("The folder " + dataFolder + " is not a directory and is the data folder for the extension " + description.name() + "!"); } final GeyserExtensionClassLoader loader; try { - loader = new GeyserExtensionClassLoader(this, getClass().getClassLoader(), path); + loader = new GeyserExtensionClassLoader(this, getClass().getClassLoader(), path, description); } catch (Throwable e) { throw new InvalidExtensionException(e); } - this.classLoaders.put(description.name(), loader); + this.classLoaders.put(description.id(), loader); - final Extension extension = loader.load(description); + final Extension extension = loader.load(); return this.setup(extension, description, dataFolder, new GeyserExtensionEventBus(GeyserImpl.getInstance().eventBus(), extension)); } private GeyserExtensionContainer setup(Extension extension, GeyserExtensionDescription description, Path dataFolder, ExtensionEventBus eventBus) { - GeyserExtensionLogger logger = new GeyserExtensionLogger(GeyserImpl.getInstance().getLogger(), description.name()); + GeyserExtensionLogger logger = new GeyserExtensionLogger(GeyserImpl.getInstance().getLogger(), description.id()); return new GeyserExtensionContainer(extension, dataFolder, description, this, logger, eventBus); } @@ -152,7 +164,8 @@ public class GeyserExtensionLoader extends ExtensionLoader { GeyserExtensionDescription description = this.extensionDescription(path); String name = description.name(); - if (extensions.containsKey(name) || extensionManager.extension(name) != null) { + String id = description.id(); + if (extensions.containsKey(id) || extensionManager.extension(id) != null) { GeyserImpl.getInstance().getLogger().warning(GeyserLocale.getLocaleStringLog("geyser.extensions.load.duplicate", name, path.toString())); return; } @@ -169,8 +182,8 @@ public class GeyserExtensionLoader extends ExtensionLoader { return; } - extensions.put(name, path); - loadedExtensions.put(name, this.loadExtension(path, description)); + extensions.put(id, path); + loadedExtensions.put(id, this.loadExtension(path, description)); } catch (Exception e) { GeyserImpl.getInstance().getLogger().error(GeyserLocale.getLocaleStringLog("geyser.extensions.load.failed_with_name", path.getFileName(), path.toAbsolutePath()), e); } diff --git a/core/src/main/java/org/geysermc/geyser/extension/GeyserExtensionManager.java b/core/src/main/java/org/geysermc/geyser/extension/GeyserExtensionManager.java index 5dd924301..3c41c4329 100644 --- a/core/src/main/java/org/geysermc/geyser/extension/GeyserExtensionManager.java +++ b/core/src/main/java/org/geysermc/geyser/extension/GeyserExtensionManager.java @@ -52,8 +52,8 @@ public class GeyserExtensionManager extends ExtensionManager { } @Override - public Extension extension(@NonNull String name) { - return this.extensions.get(name); + public Extension extension(@NonNull String id) { + return this.extensions.get(id); } @Override @@ -83,7 +83,7 @@ public class GeyserExtensionManager extends ExtensionManager { if (!extension.isEnabled()) { extension.setEnabled(true); GeyserImpl.getInstance().eventBus().register(extension, extension); - GeyserImpl.getInstance().getLogger().info(GeyserLocale.getLocaleStringLog("geyser.extensions.enable.success", extension.description().name())); + GeyserImpl.getInstance().getLogger().info(GeyserLocale.getLocaleStringLog("geyser.extensions.enable.success", extension.name())); } } @@ -98,7 +98,7 @@ public class GeyserExtensionManager extends ExtensionManager { GeyserImpl.getInstance().eventBus().unregisterAll(extension); extension.setEnabled(false); - GeyserImpl.getInstance().getLogger().info(GeyserLocale.getLocaleStringLog("geyser.extensions.disable.success", extension.description().name())); + GeyserImpl.getInstance().getLogger().info(GeyserLocale.getLocaleStringLog("geyser.extensions.disable.success", extension.name())); } } @@ -121,6 +121,6 @@ public class GeyserExtensionManager extends ExtensionManager { @Override public void register(@NonNull Extension extension) { - this.extensions.put(extension.name(), extension); + this.extensions.put(extension.description().id(), extension); } } From 71bef08ef6e6edfcc6242076ebdcf1091fc8f6d9 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Sun, 1 Oct 2023 14:41:04 -0400 Subject: [PATCH 085/344] Fix CustomQueryTranslator (#4169) --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f654255fa..d21bf5e33 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,7 +14,7 @@ protocol-connection = "3.0.0.Beta1-20230908.171156-105" raknet = "1.0.0.CR1-20230703.195238-9" blockstateupdater="1.20.30-20230918.203831-4" mcauthlib = "d9d773e" -mcprotocollib = "1.20.2-1-20230926.224810-3" +mcprotocollib = "1.20.2-1-20231001.173210-4" adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" From be5b437e5f9bfdefe5e0a5440ac5a178871ce31a Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Sun, 1 Oct 2023 15:06:57 -0400 Subject: [PATCH 086/344] Add spigot world adapter for 1.20.2 (#4170) --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d21bf5e33..85f42ea0d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -24,7 +24,7 @@ jline = "3.21.0" terminalconsoleappender = "1.2.0" folia = "1.19.4-R0.1-SNAPSHOT" viaversion = "4.0.0" -adapters = "1.9-SNAPSHOT" +adapters = "1.10-SNAPSHOT" commodore = "2.2" bungeecord = "a7c6ede" velocity = "3.1.1" From 7d489c7354b4888b02b5a49c651a9f45249ba170 Mon Sep 17 00:00:00 2001 From: petersv5 <88165842+petersv5@users.noreply.github.com> Date: Mon, 2 Oct 2023 00:15:44 +0200 Subject: [PATCH 087/344] Close threads at server shutdown (#4029) Co-authored-by: Peter Svensson Co-authored-by: Konicai <71294714+Konicai@users.noreply.github.com> --- .../network/GeyserServerInitializer.java | 6 ++- .../geyser/network/netty/GeyserServer.java | 38 +++++++++++++++---- .../geysermc/geyser/skin/SkinProvider.java | 28 ++++++++++---- gradle/libs.versions.toml | 2 +- 4 files changed, 57 insertions(+), 17 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/network/GeyserServerInitializer.java b/core/src/main/java/org/geysermc/geyser/network/GeyserServerInitializer.java index 35d2d7f33..f19a46e6a 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GeyserServerInitializer.java +++ b/core/src/main/java/org/geysermc/geyser/network/GeyserServerInitializer.java @@ -47,6 +47,10 @@ public class GeyserServerInitializer extends BedrockServerInitializer { this.geyser = geyser; } + public DefaultEventLoopGroup getEventLoopGroup() { + return eventLoopGroup; + } + @Override public void initSession(@Nonnull BedrockServerSession bedrockServerSession) { try { @@ -72,4 +76,4 @@ public class GeyserServerInitializer extends BedrockServerInitializer { protected BedrockPeer createPeer(Channel channel) { return new GeyserBedrockPeer(channel, this::createSession); } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java b/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java index df9e1e9d9..6fbb29157 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java @@ -39,6 +39,7 @@ import io.netty.channel.kqueue.KQueueEventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.DatagramChannel; import io.netty.channel.socket.nio.NioDatagramChannel; +import io.netty.util.concurrent.Future; import lombok.Getter; import net.jodah.expiringmap.ExpirationPolicy; import net.jodah.expiringmap.ExpiringMap; @@ -58,6 +59,7 @@ import org.geysermc.geyser.network.netty.handler.RakPingHandler; import org.geysermc.geyser.network.netty.proxy.ProxyServerHandler; import org.geysermc.geyser.ping.GeyserPingInfo; import org.geysermc.geyser.ping.IGeyserPingPassthrough; +import org.geysermc.geyser.skin.SkinProvider; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.translator.text.MessageTranslator; @@ -83,14 +85,21 @@ public final class GeyserServer { private static final Transport TRANSPORT = compatibleTransport(); + /** + * See {@link EventLoopGroup#shutdownGracefully(long, long, TimeUnit)} + */ + private static final int SHUTDOWN_QUIET_PERIOD_MS = 100; + private static final int SHUTDOWN_TIMEOUT_MS = 500; + private final GeyserImpl geyser; - private final EventLoopGroup group; + private EventLoopGroup group; private final ServerBootstrap bootstrap; + private EventLoopGroup playerGroup; @Getter private final ExpiringMap proxiedAddresses; - private ChannelFuture future; + private ChannelFuture bootstrapFuture; public GeyserServer(GeyserImpl geyser, int threadCount) { this.geyser = geyser; @@ -109,7 +118,7 @@ public final class GeyserServer { public CompletableFuture bind(InetSocketAddress address) { CompletableFuture future = new CompletableFuture<>(); - this.future = this.bootstrap.bind(address).addListener(bindResult -> { + this.bootstrapFuture = this.bootstrap.bind(address).addListener(bindResult -> { if (bindResult.cause() != null) { future.completeExceptionally(bindResult.cause()); return; @@ -117,7 +126,7 @@ public final class GeyserServer { future.complete(null); }); - Channel channel = this.future.channel(); + Channel channel = this.bootstrapFuture.channel(); // Add our ping handler channel.pipeline() @@ -132,8 +141,19 @@ public final class GeyserServer { } public void shutdown() { - this.group.shutdownGracefully(); - this.future.channel().closeFuture().syncUninterruptibly(); + try { + Future future1 = this.group.shutdownGracefully(SHUTDOWN_QUIET_PERIOD_MS, SHUTDOWN_TIMEOUT_MS, TimeUnit.MILLISECONDS); + this.group = null; + Future future2 = this.playerGroup.shutdownGracefully(SHUTDOWN_QUIET_PERIOD_MS, SHUTDOWN_TIMEOUT_MS, TimeUnit.MILLISECONDS); + this.playerGroup = null; + future1.sync(); + future2.sync(); + + SkinProvider.shutdown(); + } catch (InterruptedException e) { + GeyserImpl.getInstance().getLogger().severe("Exception in shutdown process", e); + } + this.bootstrapFuture.channel().closeFuture().syncUninterruptibly(); } private ServerBootstrap createBootstrap(EventLoopGroup group) { @@ -149,11 +169,13 @@ public final class GeyserServer { } } + GeyserServerInitializer serverInitializer = new GeyserServerInitializer(this.geyser); + playerGroup = serverInitializer.getEventLoopGroup(); return new ServerBootstrap() .channelFactory(RakChannelFactory.server(TRANSPORT.datagramChannel())) .group(group) .option(RakChannelOption.RAK_HANDLE_PING, true) - .childHandler(new GeyserServerInitializer(this.geyser)); + .childHandler(serverInitializer); } public boolean onConnectionRequest(InetSocketAddress inetSocketAddress) { @@ -217,7 +239,7 @@ public final class GeyserServer { .version(GameProtocol.DEFAULT_BEDROCK_CODEC.getMinecraftVersion()) // Required to not be empty as of 1.16.210.59. Can only contain . and numbers. .ipv4Port(this.geyser.getConfig().getBedrock().port()) .ipv6Port(this.geyser.getConfig().getBedrock().port()) - .serverId(future.channel().config().getOption(RakChannelOption.RAK_GUID)); + .serverId(bootstrapFuture.channel().config().getOption(RakChannelOption.RAK_GUID)); if (config.isPassthroughMotd() && pingInfo != null && pingInfo.getDescription() != null) { String[] motd = MessageTranslator.convertMessageLenient(pingInfo.getDescription()).split("\n"); diff --git a/core/src/main/java/org/geysermc/geyser/skin/SkinProvider.java b/core/src/main/java/org/geysermc/geyser/skin/SkinProvider.java index 41f750990..f491473be 100644 --- a/core/src/main/java/org/geysermc/geyser/skin/SkinProvider.java +++ b/core/src/main/java/org/geysermc/geyser/skin/SkinProvider.java @@ -58,7 +58,7 @@ import java.util.function.Predicate; public class SkinProvider { private static final boolean ALLOW_THIRD_PARTY_CAPES = GeyserImpl.getInstance().getConfig().isAllowThirdPartyCapes(); - static final ExecutorService EXECUTOR_SERVICE = Executors.newFixedThreadPool(ALLOW_THIRD_PARTY_CAPES ? 21 : 14); + static ExecutorService EXECUTOR_SERVICE; static final Skin EMPTY_SKIN; static final Cape EMPTY_CAPE = new Cape("", "no-cape", ByteArrays.EMPTY_ARRAY, -1, true); @@ -133,6 +133,20 @@ public class SkinProvider { WEARING_CUSTOM_SKULL_SLIM = new SkinGeometry("{\"geometry\" :{\"default\" :\"geometry.humanoid.wearingCustomSkullSlim\"}}", wearingCustomSkullSlim, false); } + private static ExecutorService getExecutorService() { + if (EXECUTOR_SERVICE == null) { + EXECUTOR_SERVICE = Executors.newFixedThreadPool(ALLOW_THIRD_PARTY_CAPES ? 21 : 14); + } + return EXECUTOR_SERVICE; + } + + public static void shutdown() { + if (EXECUTOR_SERVICE != null) { + EXECUTOR_SERVICE.shutdown(); + EXECUTOR_SERVICE = null; + } + } + public static void registerCacheImageTask(GeyserImpl geyser) { // Schedule Daily Image Expiry if we are caching them if (geyser.getConfig().getCacheImages() > 0) { @@ -302,7 +316,7 @@ public class SkinProvider { GeyserImpl.getInstance().getLogger().debug("Took " + (System.currentTimeMillis() - time) + "ms for " + playerId); return skinAndCape; - }, EXECUTOR_SERVICE); + }, getExecutorService()); } static CompletableFuture requestSkin(UUID playerId, String textureUrl, boolean newThread) { @@ -320,7 +334,7 @@ public class SkinProvider { CompletableFuture future; if (newThread) { - future = CompletableFuture.supplyAsync(() -> supplySkin(playerId, textureUrl), EXECUTOR_SERVICE) + future = CompletableFuture.supplyAsync(() -> supplySkin(playerId, textureUrl), getExecutorService()) .whenCompleteAsync((skin, throwable) -> { skin.updated = true; CACHED_JAVA_SKINS.put(textureUrl, skin); @@ -349,7 +363,7 @@ public class SkinProvider { CompletableFuture future; if (newThread) { - future = CompletableFuture.supplyAsync(() -> supplyCape(capeUrl, provider), EXECUTOR_SERVICE) + future = CompletableFuture.supplyAsync(() -> supplyCape(capeUrl, provider), getExecutorService()) .whenCompleteAsync((cape, throwable) -> { CACHED_JAVA_CAPES.put(capeUrl, cape); requestedCapes.remove(capeUrl); @@ -388,7 +402,7 @@ public class SkinProvider { CompletableFuture future; if (newThread) { - future = CompletableFuture.supplyAsync(() -> supplyEars(skin, earsUrl), EXECUTOR_SERVICE) + future = CompletableFuture.supplyAsync(() -> supplyEars(skin, earsUrl), getExecutorService()) .whenCompleteAsync((outSkin, throwable) -> { }); } else { Skin ears = supplyEars(skin, earsUrl); // blocking @@ -620,7 +634,7 @@ public class SkinProvider { } return null; } - }, EXECUTOR_SERVICE); + }, getExecutorService()); } /** @@ -646,7 +660,7 @@ public class SkinProvider { } return null; } - }, EXECUTOR_SERVICE).thenCompose(uuid -> { + }, getExecutorService()).thenCompose(uuid -> { if (uuid == null) { return CompletableFuture.completedFuture(null); } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 85f42ea0d..46106f490 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,7 +14,7 @@ protocol-connection = "3.0.0.Beta1-20230908.171156-105" raknet = "1.0.0.CR1-20230703.195238-9" blockstateupdater="1.20.30-20230918.203831-4" mcauthlib = "d9d773e" -mcprotocollib = "1.20.2-1-20231001.173210-4" +mcprotocollib = "1.20.2-1-20231001.201013-5" adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" From 7983448ce637656db1fca95eb65344a8c6d90de3 Mon Sep 17 00:00:00 2001 From: chris Date: Tue, 3 Oct 2023 01:12:54 +0200 Subject: [PATCH 088/344] Remove Mojang account sign-in option (#4147) * Remove Mojang auth * Yeet Connector wrapper, ensure that empty config arrays (e.g. saved user logins) are empty lists instead of null to avoid NPE exceptions --- .../geysermc/connector/GeyserConnector.java | 91 ---------- .../network/session/GeyserSession.java | 161 ------------------ .../network/session/auth/AuthData.java | 55 ------ .../java/org/geysermc/geyser/GeyserImpl.java | 8 +- .../configuration/GeyserConfiguration.java | 18 -- .../GeyserJacksonConfiguration.java | 20 --- .../geyser/network/UpstreamPacketHandler.java | 15 +- .../geyser/session/GeyserSession.java | 77 +-------- .../org/geysermc/geyser/util/FileUtils.java | 5 +- .../geyser/util/LoginEncryptionUtils.java | 25 --- 10 files changed, 13 insertions(+), 462 deletions(-) delete mode 100644 core/src/main/java/org/geysermc/connector/GeyserConnector.java delete mode 100644 core/src/main/java/org/geysermc/connector/network/session/GeyserSession.java delete mode 100644 core/src/main/java/org/geysermc/connector/network/session/auth/AuthData.java diff --git a/core/src/main/java/org/geysermc/connector/GeyserConnector.java b/core/src/main/java/org/geysermc/connector/GeyserConnector.java deleted file mode 100644 index 381282a2a..000000000 --- a/core/src/main/java/org/geysermc/connector/GeyserConnector.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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.connector; - -import org.geysermc.api.Geyser; -import org.geysermc.geyser.api.util.PlatformType; -import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.geyser.GeyserImpl; - -import java.util.UUID; - -/** - * Deprecated, please use {@link Geyser} or {@link GeyserImpl}. - * - * @deprecated legacy code - */ -@Deprecated -public class GeyserConnector { - public static final String NAME = GeyserImpl.NAME; - public static final String GIT_VERSION = GeyserImpl.GIT_VERSION; // A fallback for running in IDEs - public static final String VERSION = GeyserImpl.VERSION; // A fallback for running in IDEs - - public static final String OAUTH_CLIENT_ID = GeyserImpl.OAUTH_CLIENT_ID; - - private static final GeyserConnector INSTANCE = new GeyserConnector(); - - public static GeyserConnector getInstance() { - return INSTANCE; - } - - public boolean isShuttingDown() { - return GeyserImpl.getInstance().isShuttingDown(); - } - - public PlatformType getPlatformType() { - return GeyserImpl.getInstance().getPlatformType(); - } - - public void shutdown() { - GeyserImpl.getInstance().shutdown(); - } - - public void reload() { - GeyserImpl.getInstance().reload(); - } - - public GeyserSession getPlayerByXuid(String xuid) { - org.geysermc.geyser.session.GeyserSession session = GeyserImpl.getInstance().connectionByXuid(xuid); - if (session != null) { - return new GeyserSession(session); - } else { - return null; - } - } - - public GeyserSession getPlayerByUuid(UUID uuid) { - org.geysermc.geyser.session.GeyserSession session = GeyserImpl.getInstance().connectionByUuid(uuid); - if (session != null) { - return new GeyserSession(session); - } else { - return null; - } - } - - public boolean isProductionEnvironment() { - return GeyserImpl.getInstance().isProductionEnvironment(); - } -} diff --git a/core/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/core/src/main/java/org/geysermc/connector/network/session/GeyserSession.java deleted file mode 100644 index 6298a41f6..000000000 --- a/core/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * 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.connector.network.session; - -import com.github.steveice10.packetlib.packet.Packet; -import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket; -import org.geysermc.connector.network.session.auth.AuthData; - -/** - * Deprecated, legacy code. Serves as a wrapper around - * the class used now. - * - * @deprecated legacy code - */ -@Deprecated -public class GeyserSession { - private final org.geysermc.geyser.session.GeyserSession handle; - - public GeyserSession(org.geysermc.geyser.session.GeyserSession handle) { - this.handle = handle; - } - - public AuthData getAuthData() { - return new AuthData(this.handle.getAuthData()); - } - - public boolean isMicrosoftAccount() { - return this.handle.isMicrosoftAccount(); - } - - public boolean isClosed() { - return this.handle.isClosed(); - } - - public String getRemoteAddress() { - return this.handle.remoteServer().address(); - } - - public int getRemotePort() { - return this.handle.remoteServer().port(); - } - - public int getRenderDistance() { - return this.handle.getServerRenderDistance(); - } - - public boolean isSentSpawnPacket() { - return this.handle.isSentSpawnPacket(); - } - - public boolean isLoggedIn() { - return this.handle.isLoggedIn(); - } - - public boolean isLoggingIn() { - return this.handle.isLoggingIn(); - } - - public boolean isSpawned() { - return this.handle.isSpawned(); - } - - public boolean isInteracting() { - return this.handle.isInteracting(); - } - - public boolean isCanFly() { - return this.handle.isCanFly(); - } - - public boolean isFlying() { - return this.handle.isFlying(); - } - - public void connect() { - this.handle.connect(); - } - - public void login() { - throw new UnsupportedOperationException(); - } - - public void authenticate(String username) { - this.handle.authenticate(username); - } - - public void authenticate(String username, String password) { - this.handle.authenticate(username, password); - } - - public void authenticateWithMicrosoftCode() { - this.handle.authenticateWithMicrosoftCode(); - } - - public void disconnect(String reason) { - this.handle.disconnect(reason); - } - - public void close() { - throw new UnsupportedOperationException(); - } - - public void executeInEventLoop(Runnable runnable) { - this.handle.executeInEventLoop(runnable); - } - - public String getName() { - return this.handle.bedrockUsername(); - } - - public boolean isConsole() { - return this.handle.isConsole(); - } - - public String getLocale() { - return this.handle.locale(); - } - - public void sendUpstreamPacket(BedrockPacket packet) { - this.handle.sendUpstreamPacket(packet); - } - - public void sendUpstreamPacketImmediately(BedrockPacket packet) { - this.handle.sendUpstreamPacketImmediately(packet); - } - - public void sendDownstreamPacket(Packet packet) { - this.handle.sendDownstreamPacket(packet); - } - - public boolean hasPermission(String permission) { - return this.handle.hasPermission(permission); - } - - public void sendAdventureSettings() { - this.handle.sendAdventureSettings(); - } -} diff --git a/core/src/main/java/org/geysermc/connector/network/session/auth/AuthData.java b/core/src/main/java/org/geysermc/connector/network/session/auth/AuthData.java deleted file mode 100644 index cca7aa48c..000000000 --- a/core/src/main/java/org/geysermc/connector/network/session/auth/AuthData.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.connector.network.session.auth; - -import java.util.UUID; - -/** - * Deprecated, legacy code. Serves as a wrapper around - * the class used now. - * - * @deprecated legacy code - */ -@Deprecated -public class AuthData { - private final org.geysermc.geyser.session.auth.AuthData handle; - - public AuthData(org.geysermc.geyser.session.auth.AuthData handle) { - this.handle = handle; - } - - public String getName() { - return this.handle.name(); - } - - public UUID getUUID() { - return this.handle.uuid(); - } - - public String getXboxUUID() { - return this.handle.xuid(); - } -} diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index 4a5f16bfa..185ab7c2a 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -43,7 +43,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.api.Geyser; -import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.cumulus.form.Form; import org.geysermc.cumulus.form.util.FormBuilder; import org.geysermc.erosion.packet.Packets; @@ -61,6 +60,7 @@ import org.geysermc.geyser.api.event.lifecycle.GeyserShutdownEvent; import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.api.network.BedrockListener; import org.geysermc.geyser.api.network.RemoteServer; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.command.GeyserCommandManager; import org.geysermc.geyser.configuration.GeyserConfiguration; import org.geysermc.geyser.entity.EntityDefinitions; @@ -478,12 +478,6 @@ public class GeyserImpl implements GeyserApi { } if (config.getRemote().authType() == AuthType.ONLINE) { - if (config.getUserAuths() != null && !config.getUserAuths().isEmpty()) { - getLogger().warning("The 'userAuths' config section is now deprecated, and will be removed in the near future! " + - "Please migrate to the new 'saved-user-logins' config option: " + - "https://wiki.geysermc.org/geyser/understanding-the-config/"); - } - // May be written/read to on multiple threads from each GeyserSession as well as writing the config savedRefreshTokens = new ConcurrentHashMap<>(); diff --git a/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java b/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java index 222af341b..e36ec819b 100644 --- a/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java +++ b/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java @@ -36,7 +36,6 @@ import org.geysermc.geyser.text.GeyserLocale; import java.nio.file.Path; import java.util.List; -import java.util.Map; public interface GeyserConfiguration { /** @@ -53,9 +52,6 @@ public interface GeyserConfiguration { List getSavedUserLogins(); - @Deprecated - Map getUserAuths(); - boolean isCommandSuggestions(); @JsonIgnore @@ -147,8 +143,6 @@ public interface GeyserConfiguration { void setPort(int port); - boolean isPasswordAuthentication(); - boolean isUseProxyProtocol(); boolean isForwardHost(); @@ -164,18 +158,6 @@ public interface GeyserConfiguration { void setAuthType(AuthType authType); } - interface IUserAuthenticationInfo { - String getEmail(); - - String getPassword(); - - /** - * Will be removed after Microsoft accounts are fully migrated - */ - @Deprecated - boolean isMicrosoftAccount(); - } - interface IMetricsInfo { boolean isEnabled(); diff --git a/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java b/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java index 64ab09954..268304844 100644 --- a/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java +++ b/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java @@ -44,7 +44,6 @@ import java.io.IOException; import java.nio.file.Path; import java.util.Collections; import java.util.List; -import java.util.Map; import java.util.UUID; import java.util.stream.Collectors; @@ -67,8 +66,6 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration public abstract Path getFloodgateKeyPath(); - private Map userAuths; - @JsonProperty("command-suggestions") private boolean commandSuggestions = true; @@ -275,10 +272,6 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration return false; } - @Getter - @JsonProperty("allow-password-authentication") - private boolean passwordAuthentication = true; - @Getter @JsonProperty("use-proxy-protocol") private boolean useProxyProtocol = false; @@ -288,19 +281,6 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration private boolean forwardHost = false; } - @Getter - @JsonIgnoreProperties(ignoreUnknown = true) // DO NOT REMOVE THIS! Otherwise, after we remove microsoft-account configs will not load - public static class UserAuthenticationInfo implements IUserAuthenticationInfo { - @AsteriskSerializer.Asterisk() - private String email; - - @AsteriskSerializer.Asterisk() - private String password; - - @JsonProperty("microsoft-account") - private boolean microsoftAccount = false; - } - @Getter @JsonIgnoreProperties(ignoreUnknown = true) public static class MetricsInfo implements IMetricsInfo { diff --git a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java index 6b43422e5..361aaffb9 100644 --- a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java +++ b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java @@ -52,7 +52,6 @@ import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.api.pack.PackCodec; import org.geysermc.geyser.api.pack.ResourcePack; import org.geysermc.geyser.api.pack.ResourcePackManifest; -import org.geysermc.geyser.configuration.GeyserConfiguration; import org.geysermc.geyser.event.type.SessionLoadResourcePacksEventImpl; import org.geysermc.geyser.pack.GeyserResourcePack; import org.geysermc.geyser.registry.BlockRegistries; @@ -257,21 +256,9 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { return true; } } - if (geyser.getConfig().getUserAuths() != null) { - GeyserConfiguration.IUserAuthenticationInfo info = geyser.getConfig().getUserAuths().get(bedrockUsername); - - if (info != null) { - geyser.getLogger().info(GeyserLocale.getLocaleStringLog("geyser.auth.stored_credentials", session.getAuthData().name())); - session.setMicrosoftAccount(info.isMicrosoftAccount()); - session.authenticate(info.getEmail(), info.getPassword()); - return true; - } - } PendingMicrosoftAuthentication.AuthenticationTask task = geyser.getPendingMicrosoftAuthentication().getTask(session.getAuthData().xuid()); if (task != null) { - if (task.getAuthentication().isDone() && session.onMicrosoftLoginComplete(task)) { - return true; - } + return task.getAuthentication().isDone() && session.onMicrosoftLoginComplete(task); } return false; diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 5c9725fae..673ff5f37 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -26,10 +26,7 @@ package org.geysermc.geyser.session; import com.github.steveice10.mc.auth.data.GameProfile; -import com.github.steveice10.mc.auth.exception.request.InvalidCredentialsException; import com.github.steveice10.mc.auth.exception.request.RequestException; -import com.github.steveice10.mc.auth.service.AuthenticationService; -import com.github.steveice10.mc.auth.service.MojangAuthenticationService; import com.github.steveice10.mc.auth.service.MsaAuthenticationService; import com.github.steveice10.mc.protocol.MinecraftConstants; import com.github.steveice10.mc.protocol.MinecraftProtocol; @@ -190,10 +187,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { @Setter private RemoteServer remoteServer; - @Deprecated - @Setter - private boolean microsoftAccount; - private final SessionPlayerEntity playerEntity; private final AdvancementsCache advancementsCache; @@ -701,76 +694,20 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { } public void authenticate(String username) { - authenticate(username, ""); - } - - public void authenticate(String username, String password) { if (loggedIn) { geyser.getLogger().severe(GeyserLocale.getLocaleStringLog("geyser.auth.already_loggedin", username)); return; } loggingIn = true; + // Always replace spaces with underscores to avoid illegal nicknames, e.g. with GeyserConnect + protocol = new MinecraftProtocol(username.replace(' ', '_')); - // Use a future to prevent timeouts as all the authentication is handled sync - CompletableFuture.supplyAsync(() -> { - try { - if (password != null && !password.isEmpty()) { - AuthenticationService authenticationService; - if (microsoftAccount) { - authenticationService = new MsaAuthenticationService(GeyserImpl.OAUTH_CLIENT_ID); - } else { - authenticationService = new MojangAuthenticationService(); - } - authenticationService.setUsername(username); - authenticationService.setPassword(password); - authenticationService.login(); - - GameProfile profile = authenticationService.getSelectedProfile(); - if (profile == null) { - // Java account is offline - disconnect(GeyserLocale.getPlayerLocaleString("geyser.network.remote.invalid_account", clientData.getLanguageCode())); - return null; - } - - protocol = new MinecraftProtocol(profile, authenticationService.getAccessToken()); - } else { - // always replace spaces when using Floodgate, - // as usernames with spaces cause issues with Bungeecord's login cycle. - // However, this doesn't affect the final username as Floodgate is still in charge of that. - // So if you have (for example) replace spaces enabled on Floodgate the spaces will re-appear. - String validUsername = username; - if (this.remoteServer.authType() == AuthType.FLOODGATE) { - validUsername = username.replace(' ', '_'); - } - - protocol = new MinecraftProtocol(validUsername); - } - } catch (InvalidCredentialsException | IllegalArgumentException e) { - geyser.getLogger().info(GeyserLocale.getLocaleStringLog("geyser.auth.login.invalid", username)); - disconnect(GeyserLocale.getPlayerLocaleString("geyser.auth.login.invalid.kick", getClientData().getLanguageCode())); - } catch (RequestException ex) { - disconnect(ex.getMessage()); - } - return null; - }).whenComplete((aVoid, ex) -> { - if (ex != null) { - disconnect(ex.toString()); - } - if (this.closed) { - if (ex != null) { - geyser.getLogger().error("", ex); - } - // Client disconnected during the authentication attempt - return; - } - - try { - connectDownstream(); - } catch (Throwable t) { - t.printStackTrace(); - } - }); + try { + connectDownstream(); + } catch (Throwable t) { + t.printStackTrace(); + } } public void authenticateWithRefreshToken(String refreshToken) { diff --git a/core/src/main/java/org/geysermc/geyser/util/FileUtils.java b/core/src/main/java/org/geysermc/geyser/util/FileUtils.java index acd2278fc..99e8f8d7d 100644 --- a/core/src/main/java/org/geysermc/geyser/util/FileUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/FileUtils.java @@ -25,6 +25,8 @@ package org.geysermc.geyser.util; +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.annotation.Nulls; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import org.geysermc.geyser.GeyserBootstrap; @@ -53,7 +55,8 @@ public class FileUtils { * @throws IOException if the config could not be loaded */ public static T loadConfig(File src, Class valueType) throws IOException { - ObjectMapper objectMapper = new ObjectMapper(new YAMLFactory()); + ObjectMapper objectMapper = new ObjectMapper(new YAMLFactory()) + .setDefaultSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY)); return objectMapper.readValue(src, valueType); } diff --git a/core/src/main/java/org/geysermc/geyser/util/LoginEncryptionUtils.java b/core/src/main/java/org/geysermc/geyser/util/LoginEncryptionUtils.java index eabfe3a88..478a6ef96 100644 --- a/core/src/main/java/org/geysermc/geyser/util/LoginEncryptionUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/LoginEncryptionUtils.java @@ -34,14 +34,12 @@ import org.cloudburstmc.protocol.bedrock.packet.ServerToClientHandshakePacket; import org.cloudburstmc.protocol.bedrock.util.ChainValidationResult; import org.cloudburstmc.protocol.bedrock.util.ChainValidationResult.IdentityData; import org.cloudburstmc.protocol.bedrock.util.EncryptionUtils; -import org.geysermc.cumulus.form.CustomForm; import org.geysermc.cumulus.form.ModalForm; import org.geysermc.cumulus.form.SimpleForm; import org.geysermc.cumulus.response.SimpleFormResponse; import org.geysermc.cumulus.response.result.FormResponseResult; import org.geysermc.cumulus.response.result.ValidFormResponseResult; import org.geysermc.geyser.GeyserImpl; -import org.geysermc.geyser.configuration.GeyserConfiguration; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.auth.AuthData; import org.geysermc.geyser.session.auth.BedrockClientData; @@ -137,26 +135,16 @@ public class LoginEncryptionUtils { // Set DoDaylightCycle to false so the time doesn't accelerate while we're here session.setDaylightCycle(false); - GeyserConfiguration config = session.getGeyser().getConfig(); - boolean isPasswordAuthEnabled = config.getRemote().isPasswordAuthentication(); - session.sendForm( SimpleForm.builder() .translator(GeyserLocale::getPlayerLocaleString, session.locale()) .title("geyser.auth.login.form.notice.title") .content("geyser.auth.login.form.notice.desc") - .optionalButton("geyser.auth.login.form.notice.btn_login.mojang", isPasswordAuthEnabled) .button("geyser.auth.login.form.notice.btn_login.microsoft") .button("geyser.auth.login.form.notice.btn_disconnect") .closedOrInvalidResultHandler(() -> buildAndShowLoginWindow(session)) .validResultHandler((response) -> { if (response.clickedButtonId() == 0) { - session.setMicrosoftAccount(false); - buildAndShowLoginDetailsWindow(session); - return; - } - - if (response.clickedButtonId() == 1) { session.authenticateWithMicrosoftCode(); return; } @@ -212,19 +200,6 @@ public class LoginEncryptionUtils { }; } - public static void buildAndShowLoginDetailsWindow(GeyserSession session) { - session.sendForm( - CustomForm.builder() - .translator(GeyserLocale::getPlayerLocaleString, session.locale()) - .title("geyser.auth.login.form.details.title") - .label("geyser.auth.login.form.details.desc") - .input("geyser.auth.login.form.details.email", "account@geysermc.org", "") - .input("geyser.auth.login.form.details.pass", "123456", "") - .invalidResultHandler(() -> buildAndShowLoginDetailsWindow(session)) - .closedResultHandler(() -> buildAndShowLoginWindow(session)) - .validResultHandler((response) -> session.authenticate(response.next(), response.next()))); - } - /** * Shows the code that a user must input into their browser */ From 3547fab228aefe556be948d8a4e650870a526cb5 Mon Sep 17 00:00:00 2001 From: chris Date: Tue, 3 Oct 2023 17:15:30 +0200 Subject: [PATCH 089/344] Fix: Bedrock clients timing out due to present Java resource packs (#4176) * fix: auto deny Java edition resource packs * 1.20.2 bump on Fabric * bump mcpl * Bump required min version in the fabric.mod.json file --- .../fabric/src/main/resources/fabric.mod.json | 2 +- .../JavaClientboundResourcePacksPacket.java | 43 +++++++++++++++++++ gradle/libs.versions.toml | 6 +-- 3 files changed, 47 insertions(+), 4 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaClientboundResourcePacksPacket.java diff --git a/bootstrap/fabric/src/main/resources/fabric.mod.json b/bootstrap/fabric/src/main/resources/fabric.mod.json index 4c442017a..f401e8f23 100644 --- a/bootstrap/fabric/src/main/resources/fabric.mod.json +++ b/bootstrap/fabric/src/main/resources/fabric.mod.json @@ -25,7 +25,7 @@ "depends": { "fabricloader": ">=0.14.21", "fabric": "*", - "minecraft": ">=1.20", + "minecraft": ">=1.20.2", "fabric-permissions-api-v0": "*" } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaClientboundResourcePacksPacket.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaClientboundResourcePacksPacket.java new file mode 100644 index 000000000..017502280 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaClientboundResourcePacksPacket.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019-2023 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.translator.protocol.java; + +import com.github.steveice10.mc.protocol.data.game.ResourcePackStatus; +import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundResourcePackPacket; +import com.github.steveice10.mc.protocol.packet.common.serverbound.ServerboundResourcePackPacket; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.protocol.PacketTranslator; +import org.geysermc.geyser.translator.protocol.Translator; + +@Translator(packet = ClientboundResourcePackPacket.class) +public class JavaClientboundResourcePacksPacket extends PacketTranslator { + + @Override + public void translate(GeyserSession session, ClientboundResourcePackPacket packet) { + // We need to "answer" this to avoid timeout issues related to resource packs + session.sendDownstreamPacket(new ServerboundResourcePackPacket(ResourcePackStatus.DECLINED)); + } +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 46106f490..579f9de31 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,7 +14,7 @@ protocol-connection = "3.0.0.Beta1-20230908.171156-105" raknet = "1.0.0.CR1-20230703.195238-9" blockstateupdater="1.20.30-20230918.203831-4" mcauthlib = "d9d773e" -mcprotocollib = "1.20.2-1-20231001.201013-5" +mcprotocollib = "1.20.2-1-20231003.141424-6" adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" @@ -28,9 +28,9 @@ adapters = "1.10-SNAPSHOT" commodore = "2.2" bungeecord = "a7c6ede" velocity = "3.1.1" -fabric-minecraft = "1.20" +fabric-minecraft = "1.20.2" fabric-loader = "0.14.21" -fabric-api = "0.83.0+1.20" +fabric-api = "0.89.0+1.20.2" [libraries] base-api = { group = "org.geysermc.api", name = "base-api", version.ref = "base-api" } From 89d7225c544b7b512ce5aa8dd6b19cd5a4edd86c Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Wed, 4 Oct 2023 09:56:47 -0700 Subject: [PATCH 090/344] Fix API Registration of Custom Block Overrides (#4178) * Api reg vanilla blockstate overrides; Closes #4177 Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * proper case non static Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Clear queue when done --------- Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .../CustomBlockRegistryPopulator.java | 41 ++++++++++++------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java index c9ed51166..e4bf43b93 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java @@ -72,9 +72,9 @@ public class CustomBlockRegistryPopulator { private static Set CUSTOM_BLOCKS; private static Set CUSTOM_BLOCK_NAMES; - private static Int2ObjectMap BLOCK_STATE_OVERRIDES; private static Map CUSTOM_BLOCK_ITEM_OVERRIDES; private static Map NON_VANILLA_BLOCK_STATE_OVERRIDES; + private static Map BLOCK_STATE_OVERRIDES_QUEUE; /** * Initializes custom blocks defined by API @@ -82,9 +82,9 @@ public class CustomBlockRegistryPopulator { private static void populateBedrock() { CUSTOM_BLOCKS = new ObjectOpenHashSet<>(); CUSTOM_BLOCK_NAMES = new ObjectOpenHashSet<>(); - BLOCK_STATE_OVERRIDES = new Int2ObjectOpenHashMap<>(); CUSTOM_BLOCK_ITEM_OVERRIDES = new HashMap<>(); NON_VANILLA_BLOCK_STATE_OVERRIDES = new HashMap<>(); + BLOCK_STATE_OVERRIDES_QUEUE = new HashMap<>(); GeyserImpl.getInstance().getEventBus().fire(new GeyserDefineCustomBlocksEvent() { @Override @@ -103,18 +103,11 @@ public class CustomBlockRegistryPopulator { @Override public void registerOverride(@NonNull String javaIdentifier, @NonNull CustomBlockState customBlockState) { - int id = BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(javaIdentifier, -1); - if (id == -1) { - throw new IllegalArgumentException("Unknown Java block state. Identifier: " + javaIdentifier); - } if (!CUSTOM_BLOCKS.contains(customBlockState.block())) { throw new IllegalArgumentException("Custom block is unregistered. Name: " + customBlockState.name()); } - CustomBlockState oldBlockState = BLOCK_STATE_OVERRIDES.put(id, customBlockState); - if (oldBlockState != null) { - GeyserImpl.getInstance().getLogger().debug("Duplicate block state override for Java Identifier: " + - javaIdentifier + " Old override: " + oldBlockState.name() + " New override: " + customBlockState.name()); - } + // We can't register these yet as we don't have the java block id registry populated + BLOCK_STATE_OVERRIDES_QUEUE.put(javaIdentifier, customBlockState); } @Override @@ -139,10 +132,28 @@ public class CustomBlockRegistryPopulator { * Registers all vanilla custom blocks and skulls defined by API and mappings */ private static void populateVanilla() { + Int2ObjectMap blockStateOverrides = new Int2ObjectOpenHashMap<>(); + for (CustomSkull customSkull : BlockRegistries.CUSTOM_SKULLS.get().values()) { CUSTOM_BLOCKS.add(customSkull.getCustomBlockData()); } + for(Map.Entry entry : BLOCK_STATE_OVERRIDES_QUEUE.entrySet()) { + int id = BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(entry.getKey(), -1); + if (id == -1) { + GeyserImpl.getInstance().getLogger().warning("Custom block state override for Java Identifier: " + + entry.getKey() + " could not be registered as it is not a valid block state."); + continue; + } + + CustomBlockState oldBlockState = blockStateOverrides.put(id, entry.getValue()); + if (oldBlockState != null) { + GeyserImpl.getInstance().getLogger().warning("Duplicate block state override for Java Identifier: " + + entry.getKey() + " Old override: " + oldBlockState.name() + " New override: " + entry.getValue().name()); + } + } + BLOCK_STATE_OVERRIDES_QUEUE = null; + Map> extendedCollisionBoxes = new HashMap<>(); Map extendedCollisionBoxSet = new HashMap<>(); MappingsConfigReader mappingsConfigReader = new MappingsConfigReader(); @@ -153,7 +164,7 @@ public class CustomBlockRegistryPopulator { } block.states().forEach((javaIdentifier, customBlockState) -> { int id = BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(javaIdentifier, -1); - BLOCK_STATE_OVERRIDES.put(id, customBlockState.state()); + blockStateOverrides.put(id, customBlockState.state()); BoxComponent extendedCollisionBox = customBlockState.extendedCollisionBox(); if (extendedCollisionBox != null) { CustomBlockData extendedCollisionBlock = extendedCollisionBoxSet.computeIfAbsent(extendedCollisionBox, box -> { @@ -167,9 +178,9 @@ public class CustomBlockRegistryPopulator { }); }); - BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.set(BLOCK_STATE_OVERRIDES); - if (BLOCK_STATE_OVERRIDES.size() != 0) { - GeyserImpl.getInstance().getLogger().info("Registered " + BLOCK_STATE_OVERRIDES.size() + " custom block overrides."); + BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.set(blockStateOverrides); + if (blockStateOverrides.size() != 0) { + GeyserImpl.getInstance().getLogger().info("Registered " + blockStateOverrides.size() + " custom block overrides."); } BlockRegistries.CUSTOM_BLOCK_ITEM_OVERRIDES.set(CUSTOM_BLOCK_ITEM_OVERRIDES); From b340d4d1c432631c82a9e9c8571b1cf368bd97d9 Mon Sep 17 00:00:00 2001 From: chris Date: Thu, 5 Oct 2023 19:23:14 +0200 Subject: [PATCH 091/344] Add wiki/setup guides to the Geyser config (#4186) * Added links to Wiki and Setup guide to the config * implement suggestions --- core/src/main/resources/config.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/src/main/resources/config.yml b/core/src/main/resources/config.yml index 37e74c662..8e4db5e38 100644 --- a/core/src/main/resources/config.yml +++ b/core/src/main/resources/config.yml @@ -5,6 +5,10 @@ # # GitHub: https://github.com/GeyserMC/Geyser # Discord: https://discord.gg/geysermc +# Wiki: https://wiki.geysermc.org/ +# +# NOTICE: See https://wiki.geysermc.org/geyser/setup/ for the setup guide. Many video tutorials are outdated. +# In most cases, especially with server hosting providers, further hosting-specific configuration is required. # -------------------------------- bedrock: From 82541a5b379836cfad63807f6c511f0948c616a5 Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 6 Oct 2023 15:50:01 +0200 Subject: [PATCH 092/344] Show only 1.20.2 as supported on Fabric (#4190) --- bootstrap/fabric/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap/fabric/build.gradle.kts b/bootstrap/fabric/build.gradle.kts index c260703a5..e392a4ef9 100644 --- a/bootstrap/fabric/build.gradle.kts +++ b/bootstrap/fabric/build.gradle.kts @@ -118,7 +118,7 @@ modrinth { syncBodyFrom.set(rootProject.file("README.md").readText()) uploadFile.set(tasks.getByPath("remapModrinthJar")) - gameVersions.addAll("1.20", "1.20.1") + gameVersions.addAll("1.20.2") loaders.add("fabric") failSilently.set(true) From e8eccc64be3c1464048545a08797ecef85de1f0c Mon Sep 17 00:00:00 2001 From: Hasan <52300558+hasankayra04@users.noreply.github.com> Date: Fri, 6 Oct 2023 17:18:48 +0300 Subject: [PATCH 093/344] Change Bedrock version - Update README.md (#4188) * Change Bedrock version - Update README.md * Update pullrequest.yml Don't ever ignore workflows from PRs based on files changed as this breaks pending approval --------- Co-authored-by: Kas-tle <26531652+Kas-tle@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 9 --------- README.md | 2 +- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 72f50ff97..797d68767 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -2,15 +2,6 @@ name: Build Pull Request on: pull_request: - paths-ignore: - - '.github/ISSUE_TEMPLATE/*.yml' - - '.idea/copyright/*.xml' - - '.gitignore' - - 'CONTRIBUTING.md' - - 'LICENSE' - - 'Jenkinsfile ' - - 'README.md' - - 'licenseheader.txt' jobs: build: diff --git a/README.md b/README.md index 6c26f3744..8a1f456c7 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,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.20.0 - 1.20.31 and Minecraft Java 1.20.2 +### Currently supporting Minecraft Bedrock 1.20.0 - 1.20.32 and Minecraft Java 1.20.2 ## Setting Up Take a look [here](https://wiki.geysermc.org/geyser/setup/) for how to set up Geyser. From 30cca70e56c93833b1cd6c5bbe4acb84369be63e Mon Sep 17 00:00:00 2001 From: rtm516 Date: Sat, 7 Oct 2023 21:38:44 +0100 Subject: [PATCH 094/344] Tell the server we loaded the resource pack (#4183) * Tell the server we loaded the resource pack * Decline resource packs if they are not required --------- Co-authored-by: onebeastchris --- .../protocol/java/JavaClientboundResourcePacksPacket.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaClientboundResourcePacksPacket.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaClientboundResourcePacksPacket.java index 017502280..cc2733076 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaClientboundResourcePacksPacket.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaClientboundResourcePacksPacket.java @@ -38,6 +38,11 @@ public class JavaClientboundResourcePacksPacket extends PacketTranslator Date: Sun, 8 Oct 2023 00:31:23 +0200 Subject: [PATCH 095/344] Fix: Implement 1.20.30 START_FLYING and STOP_FLYING cases (#4198) --- .../BedrockRequestAbilityTranslator.java | 1 + .../player/BedrockActionTranslator.java | 34 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockRequestAbilityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockRequestAbilityTranslator.java index 00cd5e5fd..f31fdba80 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockRequestAbilityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockRequestAbilityTranslator.java @@ -42,6 +42,7 @@ public class BedrockRequestAbilityTranslator extends PacketTranslator Date: Sun, 8 Oct 2023 12:33:17 +0200 Subject: [PATCH 096/344] Fix: Beacon effects broken since 1.20.2 (#4199) Since 1.20.2, effect IDs start at 0, not 1. Bedrock of course doesn't respect that, so we need to subtract 1! --- .../geyser/translator/inventory/BeaconInventoryTranslator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/BeaconInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/BeaconInventoryTranslator.java index db0702e13..a0b6ebe9c 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/BeaconInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/BeaconInventoryTranslator.java @@ -119,7 +119,7 @@ public class BeaconInventoryTranslator extends AbstractBlockInventoryTranslator } private OptionalInt toJava(int effectChoice) { - return effectChoice == 0 ? OptionalInt.empty() : OptionalInt.of(effectChoice); + return effectChoice == 0 ? OptionalInt.empty() : OptionalInt.of(effectChoice - 1); } @Override From 3f0e366bacad887bf971f8c77ee7d5867b5ba4c3 Mon Sep 17 00:00:00 2001 From: chris Date: Sun, 8 Oct 2023 18:04:22 +0200 Subject: [PATCH 097/344] Fix: Don't rename extensions while the extension directory is being walked (#4197) --- .../extension/GeyserExtensionLoader.java | 71 +++++++++---------- 1 file changed, 35 insertions(+), 36 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/extension/GeyserExtensionLoader.java b/core/src/main/java/org/geysermc/geyser/extension/GeyserExtensionLoader.java index dac5ee802..da0fbffda 100644 --- a/core/src/main/java/org/geysermc/geyser/extension/GeyserExtensionLoader.java +++ b/core/src/main/java/org/geysermc/geyser/extension/GeyserExtensionLoader.java @@ -43,9 +43,9 @@ import java.io.Reader; import java.nio.file.*; import java.util.HashMap; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.regex.Pattern; -import java.util.stream.Stream; @RequiredArgsConstructor public class GeyserExtensionLoader extends ExtensionLoader { @@ -148,47 +148,46 @@ public class GeyserExtensionLoader extends ExtensionLoader { Map loadedExtensions = new LinkedHashMap<>(); Pattern[] extensionFilters = this.extensionFilters(); - try (Stream entries = Files.walk(extensionsDirectory)) { - entries.forEach(path -> { - if (Files.isDirectory(path)) { + List extensionPaths = Files.walk(extensionsDirectory).toList(); + extensionPaths.forEach(path -> { + if (Files.isDirectory(path)) { + return; + } + + for (Pattern filter : extensionFilters) { + if (!filter.matcher(path.getFileName().toString()).matches()) { + return; + } + } + + try { + GeyserExtensionDescription description = this.extensionDescription(path); + + String name = description.name(); + String id = description.id(); + if (extensions.containsKey(id) || extensionManager.extension(id) != null) { + GeyserImpl.getInstance().getLogger().warning(GeyserLocale.getLocaleStringLog("geyser.extensions.load.duplicate", name, path.toString())); return; } - for (Pattern filter : extensionFilters) { - if (!filter.matcher(path.getFileName().toString()).matches()) { - return; - } + // Completely different API version + if (description.majorApiVersion() != Geyser.api().majorApiVersion()) { + GeyserImpl.getInstance().getLogger().error(GeyserLocale.getLocaleStringLog("geyser.extensions.load.failed_api_version", name, description.apiVersion())); + return; } - try { - GeyserExtensionDescription description = this.extensionDescription(path); - - String name = description.name(); - String id = description.id(); - if (extensions.containsKey(id) || extensionManager.extension(id) != null) { - GeyserImpl.getInstance().getLogger().warning(GeyserLocale.getLocaleStringLog("geyser.extensions.load.duplicate", name, path.toString())); - return; - } - - // Completely different API version - if (description.majorApiVersion() != Geyser.api().majorApiVersion()) { - GeyserImpl.getInstance().getLogger().error(GeyserLocale.getLocaleStringLog("geyser.extensions.load.failed_api_version", name, description.apiVersion())); - return; - } - - // If the extension requires new API features, being backwards compatible - if (description.minorApiVersion() > Geyser.api().minorApiVersion()) { - GeyserImpl.getInstance().getLogger().error(GeyserLocale.getLocaleStringLog("geyser.extensions.load.failed_api_version", name, description.apiVersion())); - return; - } - - extensions.put(id, path); - loadedExtensions.put(id, this.loadExtension(path, description)); - } catch (Exception e) { - GeyserImpl.getInstance().getLogger().error(GeyserLocale.getLocaleStringLog("geyser.extensions.load.failed_with_name", path.getFileName(), path.toAbsolutePath()), e); + // If the extension requires new API features, being backwards compatible + if (description.minorApiVersion() > Geyser.api().minorApiVersion()) { + GeyserImpl.getInstance().getLogger().error(GeyserLocale.getLocaleStringLog("geyser.extensions.load.failed_api_version", name, description.apiVersion())); + return; } - }); - } + + extensions.put(id, path); + loadedExtensions.put(id, this.loadExtension(path, description)); + } catch (Exception e) { + GeyserImpl.getInstance().getLogger().error(GeyserLocale.getLocaleStringLog("geyser.extensions.load.failed_with_name", path.getFileName(), path.toAbsolutePath()), e); + } + }); for (GeyserExtensionContainer container : loadedExtensions.values()) { this.extensionContainers.put(container.extension(), container); From e8048ede0856ea2f985b0a4122fd1683bf0d8968 Mon Sep 17 00:00:00 2001 From: chris Date: Sun, 8 Oct 2023 20:33:35 +0200 Subject: [PATCH 098/344] Fix: Skull rotation issues since 1.20.2 (#4200) --- .../org/geysermc/geyser/level/block/BlockStateValues.java | 4 ++-- 1 file changed, 2 insertions(+), 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 a686ba552..97ab18c6b 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 @@ -173,8 +173,8 @@ public final class BlockStateValues { } if (javaId.contains("wall_skull") || javaId.contains("wall_head")) { - String direction = javaId.substring(javaId.lastIndexOf("facing=") + 7); - int rotation = switch (direction.substring(0, direction.length() - 1)) { + String direction = javaId.substring(javaId.lastIndexOf("facing=") + 7, javaId.lastIndexOf("powered=") - 1); + int rotation = switch (direction) { case "north" -> 180; case "west" -> 90; case "east" -> 270; From b17f4a46f484666407297c1bba300297acb7c6c4 Mon Sep 17 00:00:00 2001 From: chris Date: Mon, 9 Oct 2023 18:20:18 +0200 Subject: [PATCH 099/344] Update outdated proxy message to check for 1.20.2, remove floodgate 1.0 checks (#4204) --- .../geyser/platform/bungeecord/GeyserBungeePlugin.java | 7 +------ .../geyser/platform/velocity/GeyserVelocityPlugin.java | 10 ---------- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java index 538e00a05..86f283329 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java @@ -77,7 +77,7 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { // Copied from ViaVersion. // https://github.com/ViaVersion/ViaVersion/blob/b8072aad86695cc8ec6f5e4103e43baf3abf6cc5/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java#L43 try { - ProtocolConstants.class.getField("MINECRAFT_1_19_3"); + ProtocolConstants.class.getField("MINECRAFT_1_20_2"); } catch (NoSuchFieldException e) { getLogger().warning(" / \\"); getLogger().warning(" / \\"); @@ -111,11 +111,6 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { @Override public void onEnable() { - // Remove this in like a year - if (getProxy().getPluginManager().getPlugin("floodgate-bungee") != null) { - geyserLogger.severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.outdated", "https://ci.opencollab.dev/job/GeyserMC/job/Floodgate/job/master/")); - return; - } // Force-disable query if enabled, or else Geyser won't enable for (ListenerInfo info : getProxy().getConfig().getListeners()) { diff --git a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java index aac27fb65..dbbd30c41 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java @@ -114,16 +114,6 @@ public class GeyserVelocityPlugin implements GeyserBootstrap { GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); this.geyser = GeyserImpl.load(PlatformType.VELOCITY, this); - - // Remove this in like a year - try { - // Should only exist on 1.0 - Class.forName("org.geysermc.floodgate.FloodgateAPI"); - geyserLogger.severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.outdated", - "https://ci.opencollab.dev/job/GeyserMC/job/Floodgate/job/master/")); - return; - } catch (ClassNotFoundException ignored) { - } } private void postStartup() { From 00800acd6acf0339f78c48c36c95c5038139139f Mon Sep 17 00:00:00 2001 From: EpsilonZunsat <121496151+EpsilonZunsat@users.noreply.github.com> Date: Thu, 12 Oct 2023 00:15:33 +0800 Subject: [PATCH 100/344] Fixed incorrect bedrock version of skin mirroring geometry (#4207) * fix geometry.humanoid.wearingCustomSkull.json's LeftLeg * fix geometry.humanoid.wearingCustomSkullSlim.json'LeftLeg --- .../bedrock/skin/geometry.humanoid.wearingCustomSkull.json | 7 +++---- .../skin/geometry.humanoid.wearingCustomSkullSlim.json | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/core/src/main/resources/bedrock/skin/geometry.humanoid.wearingCustomSkull.json b/core/src/main/resources/bedrock/skin/geometry.humanoid.wearingCustomSkull.json index b18d1205b..b3c5533da 100644 --- a/core/src/main/resources/bedrock/skin/geometry.humanoid.wearingCustomSkull.json +++ b/core/src/main/resources/bedrock/skin/geometry.humanoid.wearingCustomSkull.json @@ -145,10 +145,9 @@ { "origin": [ -0.1, 0.0, -2.0 ], "size": [ 4, 12, 4 ], - "uv": [ 0, 16 ] + "uv": [ 16, 48 ] } - ], - "mirror": true + ] }, { @@ -219,4 +218,4 @@ } } ] -} \ No newline at end of file +} diff --git a/core/src/main/resources/bedrock/skin/geometry.humanoid.wearingCustomSkullSlim.json b/core/src/main/resources/bedrock/skin/geometry.humanoid.wearingCustomSkullSlim.json index 3855c92ec..94559e3f7 100644 --- a/core/src/main/resources/bedrock/skin/geometry.humanoid.wearingCustomSkullSlim.json +++ b/core/src/main/resources/bedrock/skin/geometry.humanoid.wearingCustomSkullSlim.json @@ -145,10 +145,9 @@ { "origin": [ -0.1, 0.0, -2.0 ], "size": [ 4, 12, 4 ], - "uv": [ 0, 16 ] + "uv": [ 16, 48 ] } - ], - "mirror": true + ] }, { @@ -219,4 +218,4 @@ } } ] -} \ No newline at end of file +} From 3fa35b2cb94b628aaaa229742002eacfb0a42bad Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Thu, 12 Oct 2023 06:02:57 -0700 Subject: [PATCH 101/344] Restrict game packets to state; Closes #4191 (#4210) Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .../command/defaults/StatisticsCommand.java | 2 +- .../geyser/entity/type/InteractionEntity.java | 2 +- .../geyser/inventory/AnvilContainer.java | 4 +- .../geyser/inventory/click/ClickPlan.java | 2 +- .../updater/AnvilInventoryUpdater.java | 2 +- .../geyser/session/GeyserSession.java | 47 ++++++++++++++++--- .../session/cache/AdvancementsCache.java | 6 +-- .../geyser/session/cache/BookEditCache.java | 2 +- .../inventory/BeaconInventoryTranslator.java | 2 +- .../EnchantingInventoryTranslator.java | 2 +- .../inventory/LecternInventoryTranslator.java | 4 +- .../inventory/LoomInventoryTranslator.java | 2 +- .../MerchantInventoryTranslator.java | 2 +- .../inventory/PlayerInventoryTranslator.java | 6 +-- .../StonecutterInventoryTranslator.java | 2 +- .../bedrock/BedrockAnimateTranslator.java | 6 +-- .../BedrockBlockEntityDataTranslator.java | 4 +- .../BedrockCommandBlockUpdateTranslator.java | 4 +- .../BedrockContainerCloseTranslator.java | 2 +- ...BedrockInventoryTransactionTranslator.java | 28 +++++------ .../BedrockItemFrameDropItemTranslator.java | 2 +- .../BedrockLecternUpdateTranslator.java | 8 ++-- .../BedrockMobEquipmentTranslator.java | 4 +- .../BedrockMoveEntityAbsoluteTranslator.java | 2 +- .../bedrock/BedrockPlayerInputTranslator.java | 4 +- .../BedrockRequestAbilityTranslator.java | 2 +- .../bedrock/BedrockRespawnTranslator.java | 2 +- .../bedrock/BedrockShowCreditsTranslator.java | 2 +- .../entity/BedrockEntityEventTranslator.java | 2 +- .../player/BedrockActionTranslator.java | 40 +++++++--------- .../player/BedrockInteractTranslator.java | 8 ++-- .../player/BedrockMovePlayerTranslator.java | 4 +- .../player/BedrockRiderJumpTranslator.java | 2 +- .../BedrockLevelSoundEventTranslator.java | 2 +- .../java/JavaCustomQueryTranslator.java | 2 +- .../player/JavaPlayerPositionTranslator.java | 4 +- .../inventory/JavaOpenScreenTranslator.java | 2 +- .../JavaChunkBatchFinishedTranslator.java | 2 +- .../java/level/JavaGameEventTranslator.java | 2 +- .../geysermc/geyser/util/InventoryUtils.java | 8 ++-- 40 files changed, 132 insertions(+), 103 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/StatisticsCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/StatisticsCommand.java index ea2da51df..1ff12dea3 100644 --- a/core/src/main/java/org/geysermc/geyser/command/defaults/StatisticsCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/StatisticsCommand.java @@ -44,7 +44,7 @@ public class StatisticsCommand extends GeyserCommand { session.setWaitingForStatistics(true); ServerboundClientCommandPacket ServerboundClientCommandPacket = new ServerboundClientCommandPacket(ClientCommand.STATS); - session.sendDownstreamPacket(ServerboundClientCommandPacket); + session.sendDownstreamGamePacket(ServerboundClientCommandPacket); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/InteractionEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/InteractionEntity.java index c88f90f19..0917465d4 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/InteractionEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/InteractionEntity.java @@ -68,7 +68,7 @@ public class InteractionEntity extends Entity { animatePacket.setAction(AnimatePacket.Action.SWING_ARM); session.sendUpstreamPacket(animatePacket); - session.sendDownstreamPacket(new ServerboundSwingPacket(hand)); + session.sendDownstreamGamePacket(new ServerboundSwingPacket(hand)); return InteractionResult.SUCCESS; } diff --git a/core/src/main/java/org/geysermc/geyser/inventory/AnvilContainer.java b/core/src/main/java/org/geysermc/geyser/inventory/AnvilContainer.java index 5b0800e44..e99b901a4 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/AnvilContainer.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/AnvilContainer.java @@ -82,14 +82,14 @@ public class AnvilContainer extends Container { correctRename = plainNewName; // Java Edition sends a packet every time an item is renamed even slightly in GUI. Fortunately, this works out for us now ServerboundRenameItemPacket renameItemPacket = new ServerboundRenameItemPacket(plainNewName); - session.sendDownstreamPacket(renameItemPacket); + session.sendDownstreamGamePacket(renameItemPacket); } else { // Restore formatting for item since we're not renaming correctRename = MessageTranslator.convertMessageLenient(originalName); // Java Edition sends the original custom name when not renaming, // if there isn't a custom name an empty string is sent ServerboundRenameItemPacket renameItemPacket = new ServerboundRenameItemPacket(plainOriginalName); - session.sendDownstreamPacket(renameItemPacket); + session.sendDownstreamGamePacket(renameItemPacket); } useJavaLevelCost = false; diff --git a/core/src/main/java/org/geysermc/geyser/inventory/click/ClickPlan.java b/core/src/main/java/org/geysermc/geyser/inventory/click/ClickPlan.java index bfe5a7d9d..f31f6d82f 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/click/ClickPlan.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/click/ClickPlan.java @@ -152,7 +152,7 @@ public final class ClickPlan { changedItems ); - session.sendDownstreamPacket(clickPacket); + session.sendDownstreamGamePacket(clickPacket); } session.getPlayerInventory().setCursor(simulatedCursor, session); diff --git a/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java b/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java index ea4ef674b..aa7897038 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java @@ -120,7 +120,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater { // does not result in a FilterTextPacket String originalName = MessageTranslator.convertToPlainTextLenient(ItemUtils.getCustomName(input.getNbt()), session.locale()); ServerboundRenameItemPacket renameItemPacket = new ServerboundRenameItemPacket(originalName); - session.sendDownstreamPacket(renameItemPacket); + session.sendDownstreamGamePacket(renameItemPacket); anvilContainer.setNewName(null); } diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 673ff5f37..35b532905 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -1135,7 +1135,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { if (position != null) { ServerboundMovePlayerPosPacket packet = new ServerboundMovePlayerPosPacket(playerEntity.isOnGround(), position.getX(), position.getY(), position.getZ()); - sendDownstreamPacket(packet); + sendDownstreamGamePacket(packet); } lastMovementTimestamp = System.currentTimeMillis(); } @@ -1317,7 +1317,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { return false; } - sendDownstreamPacket(useItemPacket); + sendDownstreamGamePacket(useItemPacket); playerEntity.setFlag(EntityFlag.BLOCKING, true); // Metadata should be updated later return true; @@ -1351,7 +1351,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { if (playerEntity.getFlag(EntityFlag.BLOCKING)) { ServerboundPlayerActionPacket releaseItemPacket = new ServerboundPlayerActionPacket(PlayerAction.RELEASE_USE_ITEM, Vector3i.ZERO, Direction.DOWN, 0); - sendDownstreamPacket(releaseItemPacket); + sendDownstreamGamePacket(releaseItemPacket); playerEntity.setFlag(EntityFlag.BLOCKING, false); return true; } @@ -1361,7 +1361,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { public void requestOffhandSwap() { ServerboundPlayerActionPacket swapHandsPacket = new ServerboundPlayerActionPacket(PlayerAction.SWAP_HANDS, Vector3i.ZERO, Direction.DOWN, 0); - sendDownstreamPacket(swapHandsPacket); + sendDownstreamGamePacket(swapHandsPacket); } @Override @@ -1396,14 +1396,14 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { * Sends a chat message to the Java server. */ public void sendChat(String message) { - sendDownstreamPacket(new ServerboundChatPacket(message, Instant.now().toEpochMilli(), 0L, null, 0, new BitSet())); + sendDownstreamGamePacket(new ServerboundChatPacket(message, Instant.now().toEpochMilli(), 0L, null, 0, new BitSet())); } /** * Sends a command to the Java server. */ public void sendCommand(String command) { - sendDownstreamPacket(new ServerboundChatCommandPacket(command, Instant.now().toEpochMilli(), 0L, Collections.emptyList(), 0, new BitSet())); + sendDownstreamGamePacket(new ServerboundChatCommandPacket(command, Instant.now().toEpochMilli(), 0L, Collections.emptyList(), 0, new BitSet())); } public void setServerRenderDistance(int renderDistance) { @@ -1575,6 +1575,39 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { upstream.sendPacketImmediately(packet); } + /** + * Send a packet to the remote server if in the game state. + * + * @param packet the java edition packet from MCProtocolLib + */ + public void sendDownstreamGamePacket(Packet packet) { + sendDownstreamPacket(packet, ProtocolState.GAME); + } + + /** + * Send a packet to the remote server if in the login state. + * + * @param packet the java edition packet from MCProtocolLib + */ + public void sendDownstreamLoginPacket(Packet packet) { + sendDownstreamPacket(packet, ProtocolState.LOGIN); + } + + /** + * Send a packet to the remote server if in the specified state. + * + * @param packet the java edition packet from MCProtocolLib + * @param intendedState the state the client should be in + */ + public void sendDownstreamPacket(Packet packet, ProtocolState intendedState) { + if (protocol.getState() != intendedState) { + geyser.getLogger().debug("Tried to send " + packet.getClass().getSimpleName() + " packet while not in " + intendedState.name() + " state"); + return; + } + + sendDownstreamPacket(packet); + } + /** * Send a packet to the remote server. * @@ -1718,7 +1751,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { // We're "flying locked" in this gamemode flying = true; ServerboundPlayerAbilitiesPacket abilitiesPacket = new ServerboundPlayerAbilitiesPacket(true); - sendDownstreamPacket(abilitiesPacket); + sendDownstreamGamePacket(abilitiesPacket); } abilities.add(Ability.FLYING); } diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/AdvancementsCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/AdvancementsCache.java index 00b186292..db0321147 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/AdvancementsCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/AdvancementsCache.java @@ -97,7 +97,7 @@ public class AdvancementsCache { } else { // Send a packet indicating that we intend to open this particular advancement window ServerboundSeenAdvancementsPacket packet = new ServerboundSeenAdvancementsPacket(id); - session.sendDownstreamPacket(packet); + session.sendDownstreamGamePacket(packet); // Wait for a response there } } @@ -137,7 +137,7 @@ public class AdvancementsCache { builder.closedResultHandler(() -> { // Indicate that we have closed the current advancement tab - session.sendDownstreamPacket(new ServerboundSeenAdvancementsPacket()); + session.sendDownstreamGamePacket(new ServerboundSeenAdvancementsPacket()); }).validResultHandler((response) -> { if (response.getClickedButtonId() < visibleAdvancements.size()) { @@ -146,7 +146,7 @@ public class AdvancementsCache { } else { buildAndShowMenuForm(); // Indicate that we have closed the current advancement tab - session.sendDownstreamPacket(new ServerboundSeenAdvancementsPacket()); + session.sendDownstreamGamePacket(new ServerboundSeenAdvancementsPacket()); } }); diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/BookEditCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/BookEditCache.java index 35bea7295..d1ebd0c78 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/BookEditCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/BookEditCache.java @@ -68,7 +68,7 @@ public class BookEditCache { packet = null; return; } - session.sendDownstreamPacket(packet); + session.sendDownstreamGamePacket(packet); packet = null; lastBookUpdate = System.currentTimeMillis(); } diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/BeaconInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/BeaconInventoryTranslator.java index a0b6ebe9c..00323ce83 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/BeaconInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/BeaconInventoryTranslator.java @@ -114,7 +114,7 @@ public class BeaconInventoryTranslator extends AbstractBlockInventoryTranslator // Input a beacon payment BeaconPaymentAction beaconPayment = (BeaconPaymentAction) request.getActions()[0]; ServerboundSetBeaconPacket packet = new ServerboundSetBeaconPacket(toJava(beaconPayment.getPrimaryEffect()), toJava(beaconPayment.getSecondaryEffect())); - session.sendDownstreamPacket(packet); + session.sendDownstreamGamePacket(packet); return acceptRequest(request, makeContainerEntries(session, inventory, IntSets.emptySet())); } diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/EnchantingInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/EnchantingInventoryTranslator.java index a1c928c6b..0085a7550 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/EnchantingInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/EnchantingInventoryTranslator.java @@ -129,7 +129,7 @@ public class EnchantingInventoryTranslator extends AbstractBlockInventoryTransla return rejectRequest(request); } ServerboundContainerButtonClickPacket packet = new ServerboundContainerButtonClickPacket(inventory.getJavaId(), javaSlot); - session.sendDownstreamPacket(packet); + session.sendDownstreamGamePacket(packet); return acceptRequest(request, makeContainerEntries(session, inventory, IntSets.emptySet())); } diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java index ec0d4534d..92cd8a0d4 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java @@ -102,7 +102,7 @@ public class LecternInventoryTranslator extends BaseInventoryTranslator { if (session.isDroppingLecternBook()) { // We have to enter the inventory GUI to eject the book ServerboundContainerButtonClickPacket packet = new ServerboundContainerButtonClickPacket(inventory.getJavaId(), 3); - session.sendDownstreamPacket(packet); + session.sendDownstreamGamePacket(packet); session.setDroppingLecternBook(false); InventoryUtils.closeInventory(session, inventory.getJavaId(), false); } else if (lecternContainer.getBlockEntityTag() == null) { @@ -153,7 +153,7 @@ public class LecternInventoryTranslator extends BaseInventoryTranslator { session.getLecternCache().add(position); // Close the window - we will reopen it once the client has this data synced ServerboundContainerClosePacket closeWindowPacket = new ServerboundContainerClosePacket(lecternContainer.getJavaId()); - session.sendDownstreamPacket(closeWindowPacket); + session.sendDownstreamGamePacket(closeWindowPacket); InventoryUtils.closeInventory(session, inventory.getJavaId(), false); } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/LoomInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/LoomInventoryTranslator.java index 8fb98a284..0e43ba660 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/LoomInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/LoomInventoryTranslator.java @@ -149,7 +149,7 @@ public class LoomInventoryTranslator extends AbstractBlockInventoryTranslator { // And the Java loom window has a fixed row/width of four // So... Number / 4 = row (so we don't have to bother there), and number % 4 is our column, which leads us back to our index. :) ServerboundContainerButtonClickPacket packet = new ServerboundContainerButtonClickPacket(inventory.getJavaId(), index); - session.sendDownstreamPacket(packet); + session.sendDownstreamGamePacket(packet); GeyserItemStack inputCopy = inventory.getItem(0).copy(1); inputCopy.setNetId(session.getNextItemNetId()); diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/MerchantInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/MerchantInventoryTranslator.java index e159827e8..c4f958ba1 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/MerchantInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/MerchantInventoryTranslator.java @@ -155,7 +155,7 @@ public class MerchantInventoryTranslator extends BaseInventoryTranslator { private ItemStackResponse handleTrade(GeyserSession session, Inventory inventory, ItemStackRequest request, int tradeChoice) { ServerboundSelectTradePacket packet = new ServerboundSelectTradePacket(tradeChoice); - session.sendDownstreamPacket(packet); + session.sendDownstreamGamePacket(packet); if (session.isEmulatePost1_13Logic()) { // 1.18 Java cooperates nicer than older versions diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java index b9468ac4f..613121dfd 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java @@ -359,7 +359,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { } ServerboundSetCreativeModeSlotPacket creativeDropPacket = new ServerboundSetCreativeModeSlotPacket(-1, sourceItem.getItemStack(dropAction.getCount())); - session.sendDownstreamPacket(creativeDropPacket); + session.sendDownstreamGamePacket(creativeDropPacket); sourceItem.sub(dropAction.getCount()); } @@ -494,7 +494,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { dropStack = new ItemStack(javaCreativeItem.getId(), dropAction.getCount(), javaCreativeItem.getNbt()); } ServerboundSetCreativeModeSlotPacket creativeDropPacket = new ServerboundSetCreativeModeSlotPacket(-1, dropStack); - session.sendDownstreamPacket(creativeDropPacket); + session.sendDownstreamGamePacket(creativeDropPacket); break; } default: @@ -515,7 +515,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { ItemStack itemStack = item.isEmpty() ? new ItemStack(-1, 0, null) : item.getItemStack(); ServerboundSetCreativeModeSlotPacket creativePacket = new ServerboundSetCreativeModeSlotPacket(slot, itemStack); - session.sendDownstreamPacket(creativePacket); + session.sendDownstreamGamePacket(creativePacket); } private static boolean isCraftingGrid(ItemStackRequestSlotData slotInfoData) { diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/StonecutterInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/StonecutterInventoryTranslator.java index 0663866ed..50c040a0b 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/StonecutterInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/StonecutterInventoryTranslator.java @@ -69,7 +69,7 @@ public class StonecutterInventoryTranslator extends AbstractBlockInventoryTransl if (container.getStonecutterButton() != button) { // Getting the index of the item in the Java stonecutter list ServerboundContainerButtonClickPacket packet = new ServerboundContainerButtonClickPacket(inventory.getJavaId(), button); - session.sendDownstreamPacket(packet); + session.sendDownstreamGamePacket(packet); container.setStonecutterButton(button); } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockAnimateTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockAnimateTranslator.java index 60ff187f5..33fbaed30 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockAnimateTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockAnimateTranslator.java @@ -64,7 +64,7 @@ public class BedrockAnimateTranslator extends PacketTranslator { // and Bedrock 1.19.51. // Note for the future: we should probably largely ignore this packet and instead replicate // all actions on our end, and send swings where needed. - session.sendDownstreamPacket(new ServerboundSwingPacket(Hand.MAIN_HAND)); + session.sendDownstreamGamePacket(new ServerboundSwingPacket(Hand.MAIN_HAND)); session.activateArmAnimationTicking(); } }, @@ -77,12 +77,12 @@ public class BedrockAnimateTranslator extends PacketTranslator { // Packet value is a float of how long one has been rowing, so we convert that into a boolean session.setSteeringLeft(packet.getRowingTime() > 0.0); ServerboundPaddleBoatPacket steerLeftPacket = new ServerboundPaddleBoatPacket(session.isSteeringLeft(), session.isSteeringRight()); - session.sendDownstreamPacket(steerLeftPacket); + session.sendDownstreamGamePacket(steerLeftPacket); } case ROW_RIGHT -> { session.setSteeringRight(packet.getRowingTime() > 0.0); ServerboundPaddleBoatPacket steerRightPacket = new ServerboundPaddleBoatPacket(session.isSteeringLeft(), session.isSteeringRight()); - session.sendDownstreamPacket(steerRightPacket); + session.sendDownstreamGamePacket(steerRightPacket); } } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockEntityDataTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockEntityDataTranslator.java index f280f144f..bab5e59a5 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockEntityDataTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockEntityDataTranslator.java @@ -108,7 +108,7 @@ public class BedrockBlockEntityDataTranslator extends PacketTranslator legacySlots = packet.getLegacySlots(); if (packet.getActions().size() == 1 && legacySlots.size() > 0) { @@ -453,13 +453,13 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator currentJavaPage) { for (int i = currentJavaPage; i < newJavaPage; i++) { ServerboundContainerButtonClickPacket clickButtonPacket = new ServerboundContainerButtonClickPacket(session.getOpenInventory().getJavaId(), 2); - session.sendDownstreamPacket(clickButtonPacket); + session.sendDownstreamGamePacket(clickButtonPacket); } } else { for (int i = currentJavaPage; i > newJavaPage; i--) { ServerboundContainerButtonClickPacket clickButtonPacket = new ServerboundContainerButtonClickPacket(session.getOpenInventory().getJavaId(), 1); - session.sendDownstreamPacket(clickButtonPacket); + session.sendDownstreamGamePacket(clickButtonPacket); } } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockMobEquipmentTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockMobEquipmentTranslator.java index d045a6c24..f5086e29a 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockMobEquipmentTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockMobEquipmentTranslator.java @@ -58,7 +58,7 @@ public class BedrockMobEquipmentTranslator extends PacketTranslator session.sendDownstreamPacket(new ServerboundUseItemPacket(Hand.MAIN_HAND, session.getWorldCache().nextPredictionSequence())), + session.scheduleInEventLoop(() -> session.sendDownstreamGamePacket(new ServerboundUseItemPacket(Hand.MAIN_HAND, session.getWorldCache().nextPredictionSequence())), 50, TimeUnit.MILLISECONDS); } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockMoveEntityAbsoluteTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockMoveEntityAbsoluteTranslator.java index 4b5107bda..8a8749e34 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockMoveEntityAbsoluteTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockMoveEntityAbsoluteTranslator.java @@ -72,6 +72,6 @@ public class BedrockMoveEntityAbsoluteTranslator extends PacketTranslator { public void translate(GeyserSession session, RespawnPacket packet) { if (packet.getState() == RespawnPacket.State.CLIENT_READY) { ServerboundClientCommandPacket javaRespawnPacket = new ServerboundClientCommandPacket(ClientCommand.RESPAWN); - session.sendDownstreamPacket(javaRespawnPacket); + session.sendDownstreamGamePacket(javaRespawnPacket); } } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockShowCreditsTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockShowCreditsTranslator.java index 0aec2a5d9..3314975ef 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockShowCreditsTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockShowCreditsTranslator.java @@ -39,7 +39,7 @@ public class BedrockShowCreditsTranslator extends PacketTranslator { // Not sent as of 1.18.10 ServerboundSelectTradePacket selectTradePacket = new ServerboundSelectTradePacket(packet.getData()); - session.sendDownstreamPacket(selectTradePacket); + session.sendDownstreamGamePacket(selectTradePacket); session.scheduleInEventLoop(() -> { Inventory openInventory = session.getOpenInventory(); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java index 826a76575..bff097248 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java @@ -26,10 +26,6 @@ package org.geysermc.geyser.translator.protocol.bedrock.entity.player; import com.github.steveice10.mc.protocol.data.game.entity.object.Direction; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundInteractPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundPlayerAbilitiesPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundPlayerActionPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundPlayerCommandPacket; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import com.github.steveice10.mc.protocol.data.game.entity.player.InteractAction; @@ -97,7 +93,7 @@ public class BedrockActionTranslator extends PacketTranslator } ServerboundInteractPacket interactPacket = new ServerboundInteractPacket(entity.getEntityId(), InteractAction.INTERACT, Hand.MAIN_HAND, session.isSneaking()); - session.sendDownstreamPacket(interactPacket); + session.sendDownstreamGamePacket(interactPacket); break; case DAMAGE: ServerboundInteractPacket attackPacket = new ServerboundInteractPacket(entity.getEntityId(), InteractAction.ATTACK, Hand.MAIN_HAND, session.isSneaking()); - session.sendDownstreamPacket(attackPacket); + session.sendDownstreamGamePacket(attackPacket); break; case LEAVE_VEHICLE: ServerboundPlayerCommandPacket sneakPacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.START_SNEAKING); - session.sendDownstreamPacket(sneakPacket); + session.sendDownstreamGamePacket(sneakPacket); Entity currentVehicle = session.getPlayerEntity().getVehicle(); if (currentVehicle != null) { @@ -123,7 +123,7 @@ public class BedrockInteractTranslator extends PacketTranslator if (ridingEntity instanceof AbstractHorseEntity || (ridingEntity != null && ridingEntity.getDefinition().entityType() == EntityType.CHEST_BOAT)) { // This mob has an inventory of its own that we should open instead. ServerboundPlayerCommandPacket openVehicleWindowPacket = new ServerboundPlayerCommandPacket(session.getPlayerEntity().getEntityId(), PlayerState.OPEN_VEHICLE_INVENTORY); - session.sendDownstreamPacket(openVehicleWindowPacket); + session.sendDownstreamGamePacket(openVehicleWindowPacket); } else { session.setOpenInventory(session.getPlayerInventory()); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockMovePlayerTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockMovePlayerTranslator.java index cae25e2a3..d81c0abab 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockMovePlayerTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockMovePlayerTranslator.java @@ -83,7 +83,7 @@ public class BedrockMovePlayerTranslator extends PacketTranslator { ServerboundClientCommandPacket javaRespawnPacket = new ServerboundClientCommandPacket(ClientCommand.RESPAWN); - session.sendDownstreamPacket(javaRespawnPacket); + session.sendDownstreamGamePacket(javaRespawnPacket); } case FIRST_TIME -> { ShowCreditsPacket showCreditsPacket = new ShowCreditsPacket(); diff --git a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java index 9141ee7ab..0348eca11 100644 --- a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java @@ -260,7 +260,7 @@ public class InventoryUtils { // If this is the item we're looking for if (geyserItem.getJavaId() == itemStack.getId() && Objects.equals(geyserItem.getNbt(), itemStack.getNbt())) { ServerboundPickItemPacket packetToSend = new ServerboundPickItemPacket(i); // https://wiki.vg/Protocol#Pick_Item - session.sendDownstreamPacket(packetToSend); + session.sendDownstreamGamePacket(packetToSend); return; } } @@ -274,7 +274,7 @@ public class InventoryUtils { if ((slot - 36) != inventory.getHeldItemSlot()) { setHotbarItem(session, slot); } - session.sendDownstreamPacket(actionPacket); + session.sendDownstreamGamePacket(actionPacket); } } @@ -325,7 +325,7 @@ public class InventoryUtils { } ServerboundPickItemPacket packetToSend = new ServerboundPickItemPacket(i); // https://wiki.vg/Protocol#Pick_Item - session.sendDownstreamPacket(packetToSend); + session.sendDownstreamGamePacket(packetToSend); return; } @@ -340,7 +340,7 @@ public class InventoryUtils { if ((slot - 36) != inventory.getHeldItemSlot()) { setHotbarItem(session, slot); } - session.sendDownstreamPacket(actionPacket); + session.sendDownstreamGamePacket(actionPacket); } else { session.getGeyser().getLogger().debug("Cannot find item for block " + itemName); } From 6b67e43f8463aa2ea0672d901e587a22a595ed7a Mon Sep 17 00:00:00 2001 From: rtm516 Date: Sun, 15 Oct 2023 21:51:06 +0100 Subject: [PATCH 102/344] Update AesKeyProducer.java (#4211) --- .../floodgate/crypto/AesKeyProducer.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/common/src/main/java/org/geysermc/floodgate/crypto/AesKeyProducer.java b/common/src/main/java/org/geysermc/floodgate/crypto/AesKeyProducer.java index 77dd46fde..4fae21b32 100644 --- a/common/src/main/java/org/geysermc/floodgate/crypto/AesKeyProducer.java +++ b/common/src/main/java/org/geysermc/floodgate/crypto/AesKeyProducer.java @@ -55,19 +55,20 @@ public final class AesKeyProducer implements KeyProducer { } private SecureRandom secureRandom() throws NoSuchAlgorithmException { - // use Windows-PRNG for windows (default impl is SHA1PRNG) - if (System.getProperty("os.name").startsWith("Windows")) { - return SecureRandom.getInstance("Windows-PRNG"); - } else { - try { + try { + // use Windows-PRNG for windows (default impl is SHA1PRNG) + if (System.getProperty("os.name").startsWith("Windows")) { + return SecureRandom.getInstance("Windows-PRNG"); + } else { // NativePRNG (which should be the default on unix-systems) can still block your // system. Even though it isn't as bad as NativePRNGBlocking, we still try to // prevent that if possible return SecureRandom.getInstance("NativePRNGNonBlocking"); - } catch (NoSuchAlgorithmException ignored) { - // at this point we just have to go with the default impl even if it blocks - return new SecureRandom(); + } + } catch (NoSuchAlgorithmException ignored) { + // Fall back to the default impl as we couldn't load any others + return new SecureRandom(); } } } From 647a73d9f625dad9ae44f470dbdd61f09945b412 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Thu, 19 Oct 2023 01:11:59 -0400 Subject: [PATCH 103/344] Support 1.20.40 connections --- .../geysermc/geyser/network/GameProtocol.java | 10 +- .../geyser/network/UpstreamPacketHandler.java | 2 + .../populator/BlockRegistryPopulator.java | 4 + .../populator/ItemRegistryPopulator.java | 2 + .../bedrock/block_palette.1_20_40.nbt | Bin 0 -> 158101 bytes .../bedrock/creative_items.1_20_40.json | 5787 +++++++++++++++++ .../bedrock/runtime_item_states.1_20_40.json | 5570 ++++++++++++++++ gradle/libs.versions.toml | 6 +- 8 files changed, 11373 insertions(+), 8 deletions(-) create mode 100644 core/src/main/resources/bedrock/block_palette.1_20_40.nbt create mode 100644 core/src/main/resources/bedrock/creative_items.1_20_40.json create mode 100644 core/src/main/resources/bedrock/runtime_item_states.1_20_40.json diff --git a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java index fb9684f77..bf40ea2f9 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java @@ -31,6 +31,7 @@ import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; import org.cloudburstmc.protocol.bedrock.codec.v589.Bedrock_v589; import org.cloudburstmc.protocol.bedrock.codec.v594.Bedrock_v594; import org.cloudburstmc.protocol.bedrock.codec.v618.Bedrock_v618; +import org.cloudburstmc.protocol.bedrock.codec.v622.Bedrock_v622; import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec; import org.geysermc.geyser.session.GeyserSession; @@ -46,9 +47,7 @@ public final class GameProtocol { * Default Bedrock codec that should act as a fallback. Should represent the latest available * release of the game that Geyser supports. */ - public static final BedrockCodec DEFAULT_BEDROCK_CODEC = Bedrock_v618.CODEC.toBuilder() - .minecraftVersion("1.20.31") - .build(); + public static final BedrockCodec DEFAULT_BEDROCK_CODEC = Bedrock_v622.CODEC; /** * A list of all supported Bedrock versions that can join Geyser @@ -68,9 +67,10 @@ public final class GameProtocol { SUPPORTED_BEDROCK_CODECS.add(Bedrock_v594.CODEC.toBuilder() .minecraftVersion("1.20.10/1.20.15") .build()); - SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC.toBuilder() - .minecraftVersion("1.20.30/1.20.31") + SUPPORTED_BEDROCK_CODECS.add(Bedrock_v618.CODEC.toBuilder() + .minecraftVersion("1.20.30/1.20.32") .build()); + SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC); } /** diff --git a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java index 361aaffb9..358d8df59 100644 --- a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java +++ b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java @@ -110,6 +110,8 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { } else if (protocolVersion < GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()) { session.disconnect(GeyserLocale.getLocaleStringLog("geyser.network.outdated.client", supportedVersions)); return false; + } else { + throw new IllegalStateException("Default codec of protocol version " + protocolVersion + " should have been found"); } } 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 86c380bbd..278ebadfb 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 @@ -36,11 +36,13 @@ import it.unimi.dsi.fastutil.objects.*; import org.cloudburstmc.blockstateupdater.BlockStateUpdater; import org.cloudburstmc.blockstateupdater.BlockStateUpdater_1_20_10; import org.cloudburstmc.blockstateupdater.BlockStateUpdater_1_20_30; +import org.cloudburstmc.blockstateupdater.BlockStateUpdater_1_20_40; import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; import org.cloudburstmc.nbt.*; import org.cloudburstmc.protocol.bedrock.codec.v589.Bedrock_v589; import org.cloudburstmc.protocol.bedrock.codec.v594.Bedrock_v594; import org.cloudburstmc.protocol.bedrock.codec.v618.Bedrock_v618; +import org.cloudburstmc.protocol.bedrock.codec.v622.Bedrock_v622; import org.cloudburstmc.protocol.bedrock.data.BlockPropertyData; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.geysermc.geyser.GeyserImpl; @@ -117,11 +119,13 @@ public final class BlockRegistryPopulator { private static void registerBedrockBlocks() { Remapper mapper594 = Remapper.of(BlockStateUpdater_1_20_10.INSTANCE); Remapper mapper618 = Remapper.of(BlockStateUpdater_1_20_10.INSTANCE, BlockStateUpdater_1_20_30.INSTANCE); + Remapper mapper622 = Remapper.of(BlockStateUpdater_1_20_10.INSTANCE, BlockStateUpdater_1_20_30.INSTANCE, BlockStateUpdater_1_20_40.INSTANCE); var blockMappers = ImmutableMap., Remapper>builder() .put(ObjectIntPair.of("1_20_0", Bedrock_v589.CODEC.getProtocolVersion()), tag -> tag) .put(ObjectIntPair.of("1_20_10", Bedrock_v594.CODEC.getProtocolVersion()), mapper594) .put(ObjectIntPair.of("1_20_30", Bedrock_v618.CODEC.getProtocolVersion()), mapper618) + .put(ObjectIntPair.of("1_20_40", Bedrock_v622.CODEC.getProtocolVersion()), mapper622) .build(); // We can keep this strong as nothing should be garbage collected 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 8f04ebbe5..857726038 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 @@ -41,6 +41,7 @@ import org.cloudburstmc.nbt.NbtType; import org.cloudburstmc.protocol.bedrock.codec.v589.Bedrock_v589; import org.cloudburstmc.protocol.bedrock.codec.v594.Bedrock_v594; import org.cloudburstmc.protocol.bedrock.codec.v618.Bedrock_v618; +import org.cloudburstmc.protocol.bedrock.codec.v622.Bedrock_v622; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; @@ -116,6 +117,7 @@ public class ItemRegistryPopulator { paletteVersions.add(new PaletteVersion("1_20_0", Bedrock_v589.CODEC.getProtocolVersion())); paletteVersions.add(new PaletteVersion("1_20_10", Bedrock_v594.CODEC.getProtocolVersion(), Collections.emptyMap(), remapper594)); paletteVersions.add(new PaletteVersion("1_20_30", Bedrock_v618.CODEC.getProtocolVersion(), Collections.emptyMap(), remapper618)); + paletteVersions.add(new PaletteVersion("1_20_40", Bedrock_v622.CODEC.getProtocolVersion(), Collections.emptyMap(), remapper618)); // NO item changes between 1.20.30 and 1.20.40 GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap(); diff --git a/core/src/main/resources/bedrock/block_palette.1_20_40.nbt b/core/src/main/resources/bedrock/block_palette.1_20_40.nbt new file mode 100644 index 0000000000000000000000000000000000000000..b18b0807a48e0109e46eebfa93ca8c77d956ea3a GIT binary patch literal 158101 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

g-=;VUl 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⁡z#A(DebW+` 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

* Logs and ignores all packets presented. Allows subclasses to override/implement only * packets of interest and limit boilerplate code. */ @@ -60,11 +60,6 @@ public class LoggingPacketHandler implements BedrockPacketHandler { return defaultHandler(packet); } - @Override - public PacketSignal handle(AdventureSettingsPacket packet) { - return defaultHandler(packet); - } - @Override public PacketSignal handle(AnimatePacket packet) { return defaultHandler(packet); @@ -120,11 +115,6 @@ public class LoggingPacketHandler implements BedrockPacketHandler { return defaultHandler(packet); } - @Override - public PacketSignal handle(CraftingEventPacket packet) { - return defaultHandler(packet); - } - @Override public PacketSignal handle(EntityEventPacket packet) { return defaultHandler(packet); @@ -505,11 +495,6 @@ public class LoggingPacketHandler implements BedrockPacketHandler { return defaultHandler(packet); } - @Override - public PacketSignal handle(ScriptCustomEventPacket packet) { - return defaultHandler(packet); - } - @Override public PacketSignal handle(ServerSettingsResponsePacket packet) { return defaultHandler(packet); @@ -560,6 +545,11 @@ public class LoggingPacketHandler implements BedrockPacketHandler { return defaultHandler(packet); } + @Override + public PacketSignal handle(SetPlayerInventoryOptionsPacket packet) { + return defaultHandler(packet); + } + @Override public PacketSignal handle(SetScoreboardIdentityPacket packet) { return defaultHandler(packet); 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 278ebadfb..265c6b1f7 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 @@ -37,12 +37,17 @@ import org.cloudburstmc.blockstateupdater.BlockStateUpdater; import org.cloudburstmc.blockstateupdater.BlockStateUpdater_1_20_10; import org.cloudburstmc.blockstateupdater.BlockStateUpdater_1_20_30; import org.cloudburstmc.blockstateupdater.BlockStateUpdater_1_20_40; +import org.cloudburstmc.blockstateupdater.BlockStateUpdater_1_20_50; import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; -import org.cloudburstmc.nbt.*; +import org.cloudburstmc.nbt.NBTInputStream; +import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtMapBuilder; +import org.cloudburstmc.nbt.NbtType; import org.cloudburstmc.protocol.bedrock.codec.v589.Bedrock_v589; import org.cloudburstmc.protocol.bedrock.codec.v594.Bedrock_v594; import org.cloudburstmc.protocol.bedrock.codec.v618.Bedrock_v618; import org.cloudburstmc.protocol.bedrock.codec.v622.Bedrock_v622; +import org.cloudburstmc.protocol.bedrock.codec.v630.Bedrock_v630; import org.cloudburstmc.protocol.bedrock.data.BlockPropertyData; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.geysermc.geyser.GeyserImpl; @@ -120,12 +125,14 @@ public final class BlockRegistryPopulator { Remapper mapper594 = Remapper.of(BlockStateUpdater_1_20_10.INSTANCE); Remapper mapper618 = Remapper.of(BlockStateUpdater_1_20_10.INSTANCE, BlockStateUpdater_1_20_30.INSTANCE); Remapper mapper622 = Remapper.of(BlockStateUpdater_1_20_10.INSTANCE, BlockStateUpdater_1_20_30.INSTANCE, BlockStateUpdater_1_20_40.INSTANCE); + Remapper mapper630 = Remapper.of(BlockStateUpdater_1_20_10.INSTANCE, BlockStateUpdater_1_20_30.INSTANCE, BlockStateUpdater_1_20_40.INSTANCE, BlockStateUpdater_1_20_50.INSTANCE); var blockMappers = ImmutableMap., Remapper>builder() .put(ObjectIntPair.of("1_20_0", Bedrock_v589.CODEC.getProtocolVersion()), tag -> tag) .put(ObjectIntPair.of("1_20_10", Bedrock_v594.CODEC.getProtocolVersion()), mapper594) .put(ObjectIntPair.of("1_20_30", Bedrock_v618.CODEC.getProtocolVersion()), mapper618) .put(ObjectIntPair.of("1_20_40", Bedrock_v622.CODEC.getProtocolVersion()), mapper622) + .put(ObjectIntPair.of("1_20_50", Bedrock_v630.CODEC.getProtocolVersion()), mapper630) .build(); // We can keep this strong as nothing should be garbage collected 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 857726038..fe6e21e6f 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 @@ -42,6 +42,7 @@ import org.cloudburstmc.protocol.bedrock.codec.v589.Bedrock_v589; import org.cloudburstmc.protocol.bedrock.codec.v594.Bedrock_v594; import org.cloudburstmc.protocol.bedrock.codec.v618.Bedrock_v618; import org.cloudburstmc.protocol.bedrock.codec.v622.Bedrock_v622; +import org.cloudburstmc.protocol.bedrock.codec.v630.Bedrock_v630; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; @@ -113,11 +114,25 @@ public class ItemRegistryPopulator { return mapping; }; + Remapper remapper630 = (item, mapping) -> { + mapping = remapper618.remap(item, mapping); // apply 1.20.30 remapper first + + String id = item.javaIdentifier(); + // 1.20.50 replaced stone & planks to individual stone types + // E.g.: granite, diorite, andesite, polished variants, dark_oak_planks etc + if (mapping.getBedrockIdentifier().equals("minecraft:stone") || mapping.getBedrockIdentifier().equals("minecraft:planks")) { + return mapping.withBedrockIdentifier(id); + } + + return mapping; + }; + List paletteVersions = new ArrayList<>(3); paletteVersions.add(new PaletteVersion("1_20_0", Bedrock_v589.CODEC.getProtocolVersion())); paletteVersions.add(new PaletteVersion("1_20_10", Bedrock_v594.CODEC.getProtocolVersion(), Collections.emptyMap(), remapper594)); paletteVersions.add(new PaletteVersion("1_20_30", Bedrock_v618.CODEC.getProtocolVersion(), Collections.emptyMap(), remapper618)); paletteVersions.add(new PaletteVersion("1_20_40", Bedrock_v622.CODEC.getProtocolVersion(), Collections.emptyMap(), remapper618)); // NO item changes between 1.20.30 and 1.20.40 + paletteVersions.add(new PaletteVersion("1_20_50", Bedrock_v630.CODEC.getProtocolVersion(), Collections.emptyMap(), remapper630)); GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap(); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetPlayerInventoryOptionsTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetPlayerInventoryOptionsTranslator.java new file mode 100644 index 000000000..0f07d84da --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetPlayerInventoryOptionsTranslator.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2019-2023 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.translator.protocol.bedrock.entity.player; + +import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; +import com.github.steveice10.mc.protocol.data.game.inventory.CraftingBookStateType; +import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundRecipeBookChangeSettingsPacket; +import org.cloudburstmc.protocol.bedrock.data.inventory.InventoryTabLeft; +import org.cloudburstmc.protocol.bedrock.data.inventory.InventoryTabRight; +import org.cloudburstmc.protocol.bedrock.packet.SetPlayerInventoryOptionsPacket; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.protocol.PacketTranslator; +import org.geysermc.geyser.translator.protocol.Translator; + +@Translator(packet = SetPlayerInventoryOptionsPacket.class) +public class BedrockSetPlayerInventoryOptionsTranslator extends PacketTranslator { + + @Override + public void translate(GeyserSession session, SetPlayerInventoryOptionsPacket packet) { + // Sent by 1.20.50+ - we can pass it through to the java server + + // This should ensure that we never send these packets when the player inventory is opened while in creative + // Java edition can't craft in the 2x2 grid in creative, and subsequently doesn't have a recipe book + if (session.getGameMode() == GameMode.CREATIVE && session.getPlayerInventory() == session.getOpenInventory()) { + return; + } + + boolean filtered = packet.isFiltering(); + boolean bookOpen = isBookOpen(packet.getLeftTab(), packet.getRightTab()); + + // Hardcoded to crafting; bedrock does not have any furnace recipe books + session.sendDownstreamPacket(new ServerboundRecipeBookChangeSettingsPacket(CraftingBookStateType.CRAFTING, bookOpen, filtered)); + } + + private boolean isBookOpen(InventoryTabLeft leftTab, InventoryTabRight rightTab) { + boolean leftOpen = (leftTab != InventoryTabLeft.NONE && leftTab != InventoryTabLeft.SURVIVAL); + boolean rightOpen = rightTab == InventoryTabRight.CRAFTING; + return leftOpen || rightOpen; + } +} diff --git a/core/src/main/resources/bedrock/block_palette.1_20_50.nbt b/core/src/main/resources/bedrock/block_palette.1_20_50.nbt new file mode 100644 index 0000000000000000000000000000000000000000..0eecda74f72dcf026d3f665c050d04a1f8485bb8 GIT binary patch literal 170466 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 JkFhIPadz0t*h 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

oYIzSyh{iiN^y?}E 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 LqW$og#cL=429 Date: Wed, 22 Nov 2023 22:03:24 +0100 Subject: [PATCH 127/344] Don't send an awkward "null" when a exeption disconnect cause doesn't have a message (#4306) * Don't send an awkward "null" when a cause doesn't have a message * Fix accidental regression leading to unhandled "CraftingEventPackets" --- .../org/geysermc/geyser/network/LoggingPacketHandler.java | 5 +++++ .../java/org/geysermc/geyser/session/GeyserSession.java | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/network/LoggingPacketHandler.java b/core/src/main/java/org/geysermc/geyser/network/LoggingPacketHandler.java index ec1bef1df..80e624895 100644 --- a/core/src/main/java/org/geysermc/geyser/network/LoggingPacketHandler.java +++ b/core/src/main/java/org/geysermc/geyser/network/LoggingPacketHandler.java @@ -115,6 +115,11 @@ public class LoggingPacketHandler implements BedrockPacketHandler { return defaultHandler(packet); } + @Override + public PacketSignal handle(CraftingEventPacket packet) { + return defaultHandler(packet); + } + @Override public PacketSignal handle(EntityEventPacket packet) { return defaultHandler(packet); diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index ebb0025da..9bfb4e01c 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -1039,7 +1039,11 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { geyser.getLogger().info(GeyserLocale.getLocaleStringLog("geyser.network.remote.disconnect", authData.name(), remoteServer.address(), disconnectMessage)); } if (cause != null) { - GeyserImpl.getInstance().getLogger().error(cause.getMessage()); + if (cause.getMessage() != null) { + GeyserImpl.getInstance().getLogger().error(cause.getMessage()); + } else { + GeyserImpl.getInstance().getLogger().error("An exception occurred: ", cause); + } // GeyserSession is disconnected via session.disconnect() called indirectly be the server // This only needs to be "initiated" here when there is an exception, hence the cause clause GeyserSession.this.disconnect(disconnectMessage); From 3292718e696b2e26b89750e339de4267a70c422d Mon Sep 17 00:00:00 2001 From: chris Date: Thu, 23 Nov 2023 09:51:57 +0100 Subject: [PATCH 128/344] Don't show custom names on display entities (#4309) * Ensure that a custom text display entity name doesn't show up - it doesn't show on Java, and if we show it, the text display contents aren't shown. * Update core/src/main/java/org/geysermc/geyser/entity/type/TextDisplayEntity.java Co-authored-by: Konicai <71294714+Konicai@users.noreply.github.com> --------- Co-authored-by: Konicai <71294714+Konicai@users.noreply.github.com> --- .../org/geysermc/geyser/entity/type/TextDisplayEntity.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/TextDisplayEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/TextDisplayEntity.java index 703d5210b..0b6160401 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/TextDisplayEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/TextDisplayEntity.java @@ -34,6 +34,7 @@ import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.text.MessageTranslator; +import java.util.Optional; import java.util.UUID; // Note: 1.19.4 requires that the billboard is set to something in order to show, on Java Edition @@ -56,6 +57,12 @@ public class TextDisplayEntity extends Entity { // On JE: Hiding the display name still shows the display entity text. } + @Override + public void setDisplayName(EntityMetadata, ?> entityMetadata) { + // This would usually set EntityDataTypes.NAME, but we are instead using NAME for the text display. + // On JE: custom name does not override text display. + } + public void setText(EntityMetadata entityMetadata) { this.dirtyMetadata.put(EntityDataTypes.NAME, MessageTranslator.convertMessage(entityMetadata.getValue())); } From 0f50a3cbe604f6c4ab8d6004c6dd09d7a071879c Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Tue, 28 Nov 2023 20:33:07 -0800 Subject: [PATCH 129/344] Re-implement subchunk v9 with proper index (#4287) * Re-implement subchunk v9 with proper index Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * typo in comment --------- Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- build.gradle.kts | 4 +++- .../level/chunk/GeyserChunkSection.java | 19 +++++++++------- .../JavaLevelChunkWithLightTranslator.java | 22 +++++++++++-------- .../org/geysermc/geyser/util/ChunkUtils.java | 22 +++++++++++++------ 4 files changed, 42 insertions(+), 25 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 9eb8a6ed0..d7360b701 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,7 @@ plugins { `java-library` + // Ensure AP works in eclipse (no effect on other IDEs) + `eclipse` id("geyser.build-logic") id("io.freefair.lombok") version "6.3.0" apply false } @@ -35,4 +37,4 @@ subprojects { in platforms -> plugins.apply("geyser.platform-conventions") else -> plugins.apply("geyser.base-conventions") } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/geysermc/geyser/level/chunk/GeyserChunkSection.java b/core/src/main/java/org/geysermc/geyser/level/chunk/GeyserChunkSection.java index f3e6b8399..8a3534a8e 100644 --- a/core/src/main/java/org/geysermc/geyser/level/chunk/GeyserChunkSection.java +++ b/core/src/main/java/org/geysermc/geyser/level/chunk/GeyserChunkSection.java @@ -30,18 +30,20 @@ import org.cloudburstmc.protocol.common.util.Preconditions; public class GeyserChunkSection { - // Temporary reversion to v8 as it reduces the frequnecy of https://github.com/GeyserMC/Geyser/issues/4240 - // This does not fully resolve the issue so a better solution is still needed - private static final int CHUNK_SECTION_VERSION = 8; + // As of at least 1.19.80 + private static final int CHUNK_SECTION_VERSION = 9; private final BlockStorage[] storage; + // Counts up from 00 for y >= 0 and down from FF for y < 0 + private final int subChunkIndex; - public GeyserChunkSection(int airBlockId) { - this(new BlockStorage[]{new BlockStorage(airBlockId), new BlockStorage(airBlockId)}); + public GeyserChunkSection(int airBlockId, int subChunkIndex) { + this(new BlockStorage[]{new BlockStorage(airBlockId), new BlockStorage(airBlockId)}, subChunkIndex); } - public GeyserChunkSection(BlockStorage[] storage) { + public GeyserChunkSection(BlockStorage[] storage, int subChunkIndex) { this.storage = storage; + this.subChunkIndex = subChunkIndex; } public int getFullBlock(int x, int y, int z, int layer) { @@ -60,6 +62,7 @@ public class GeyserChunkSection { buffer.writeByte(CHUNK_SECTION_VERSION); buffer.writeByte(this.storage.length); // Required for chunk version 9+ + buffer.writeByte(this.subChunkIndex); for (BlockStorage blockStorage : this.storage) { blockStorage.writeToNetwork(buffer); } @@ -86,12 +89,12 @@ public class GeyserChunkSection { return true; } - public GeyserChunkSection copy() { + public GeyserChunkSection copy(int subChunkIndex) { BlockStorage[] storage = new BlockStorage[this.storage.length]; for (int i = 0; i < storage.length; i++) { storage[i] = this.storage[i].copy(); } - return new GeyserChunkSection(storage); + return new GeyserChunkSection(storage, subChunkIndex); } public static int blockPosition(int x, int y, int z) { 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 85eec40e0..9a8681542 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 @@ -78,7 +78,8 @@ import java.util.BitSet; import java.util.List; import java.util.Map; -import static org.geysermc.geyser.util.ChunkUtils.SERIALIZED_CHUNK_DATA; +import static org.geysermc.geyser.util.ChunkUtils.EMPTY_BLOCK_STORAGE; +import static org.geysermc.geyser.util.ChunkUtils.EMPTY_CHUNK_SECTION_SIZE; import static org.geysermc.geyser.util.ChunkUtils.indexYZXtoXZY; @Translator(packet = ClientboundLevelChunkWithLightPacket.class) @@ -127,6 +128,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator> 4)); + int subChunkIndex = sectionY + yOffset; if (bedrockSectionY < 0 || maxBedrockSectionY < bedrockSectionY) { // Ignore this chunk section since it goes outside the bounds accepted by the Bedrock client if (useExtendedCollisions) { @@ -154,7 +156,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator> 4) - (bedrockDimension.minY() >> 4); + int subChunkIndex = (y >> 4) + (bedrockDimension.minY() >> 4); if (0 <= bedrockSectionY && bedrockSectionY < maxBedrockSectionY) { // Custom skull is in a section accepted by Bedrock GeyserChunkSection bedrockSection = sections[bedrockSectionY]; IntList palette = bedrockSection.getBlockStorageArray()[0].getPalette(); if (palette instanceof IntImmutableList || palette instanceof IntLists.Singleton) { // TODO there has to be a better way to expand the palette .-. - bedrockSection = bedrockSection.copy(); + bedrockSection = bedrockSection.copy(subChunkIndex); sections[bedrockSectionY] = bedrockSection; } bedrockSection.setFullBlock(x, y & 0xF, z, 0, blockDefinition.getRuntimeId()); @@ -458,7 +461,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator> 4)); + new GeyserChunkSection(EMPTY_BLOCK_STORAGE, subChunkIndex).writeToNetwork(byteBuf); } } diff --git a/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java b/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java index cded234f9..114a7b6de 100644 --- a/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java @@ -54,19 +54,27 @@ import static org.geysermc.geyser.level.block.BlockStateValues.JAVA_AIR_ID; @UtilityClass public class ChunkUtils { - /** - * An empty subchunk. - */ - public static final byte[] SERIALIZED_CHUNK_DATA; + public static final byte[] EMPTY_BIOME_DATA; + public static final BlockStorage[] EMPTY_BLOCK_STORAGE; + + public static final int EMPTY_CHUNK_SECTION_SIZE; + static { + EMPTY_BLOCK_STORAGE = new BlockStorage[0]; + ByteBuf byteBuf = Unpooled.buffer(); try { - new GeyserChunkSection(new BlockStorage[0]) + new GeyserChunkSection(EMPTY_BLOCK_STORAGE, 0) .writeToNetwork(byteBuf); - SERIALIZED_CHUNK_DATA = new byte[byteBuf.readableBytes()]; - byteBuf.readBytes(SERIALIZED_CHUNK_DATA); + + byte[] emptyChunkData = new byte[byteBuf.readableBytes()]; + byteBuf.readBytes(emptyChunkData); + + EMPTY_CHUNK_SECTION_SIZE = emptyChunkData.length; + + emptyChunkData = null; } finally { byteBuf.release(); } From 11945db7a040587d71390443fa67cde4d131e2e9 Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 1 Dec 2023 10:27:42 +0100 Subject: [PATCH 130/344] Clear mob spawners if the Java server so requests (#4232) * Clear mob spawners if the Java server so requests * Empty spawners by replacing the spawner block with a new one instead of adding an invalid identifier to them. Unfortunately, sending one UpdateBlockPacket that replaces the spawner does not work, we need to set the spawner to air first. Cool. But at least we don't summon particles for all empty spawners now * store position vector (address review by @konicai) * remove empty line --- .../populator/BlockRegistryPopulator.java | 8 ++++- .../geyser/registry/type/BlockMappings.java | 1 + .../block/entity/BlockEntityTranslator.java | 3 +- .../entity/SpawnerBlockEntityTranslator.java | 36 +++++++++++++++++-- .../level/JavaBlockEntityDataTranslator.java | 4 +-- .../JavaLevelChunkWithLightTranslator.java | 2 +- 6 files changed, 47 insertions(+), 7 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 265c6b1f7..e3f4e685d 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 @@ -221,6 +221,7 @@ public final class BlockRegistryPopulator { GeyserBedrockBlock airDefinition = null; BlockDefinition commandBlockDefinition = null; + BlockDefinition mobSpawnerBlockDefinition = null; BlockDefinition waterDefinition = null; BlockDefinition movingBlockDefinition = null; Iterator> blocksIterator = BLOCKS_JSON.fields(); @@ -269,6 +270,7 @@ public final class BlockRegistryPopulator { case "minecraft:air" -> airDefinition = bedrockDefinition; case "minecraft:water[level=0]" -> waterDefinition = bedrockDefinition; case "minecraft:command_block[conditional=false,facing=north]" -> commandBlockDefinition = bedrockDefinition; + case "minecraft:spawner" -> mobSpawnerBlockDefinition = bedrockDefinition; case "minecraft:moving_piston[facing=north,type=normal]" -> movingBlockDefinition = bedrockDefinition; } @@ -298,9 +300,13 @@ public final class BlockRegistryPopulator { if (commandBlockDefinition == null) { throw new AssertionError("Unable to find command block in palette"); } - builder.commandBlock(commandBlockDefinition); + if (mobSpawnerBlockDefinition == null) { + throw new AssertionError("Unable to find mob spawner block in palette"); + } + builder.mobSpawnerBlock(mobSpawnerBlockDefinition); + if (waterDefinition == null) { throw new AssertionError("Unable to find water in palette"); } 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 80be3fbce..3d06cecac 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 @@ -54,6 +54,7 @@ public class BlockMappings implements DefinitionRegistry { int[] remappedVanillaIds; BlockDefinition commandBlock; + BlockDefinition mobSpawnerBlock; Map itemFrames; Map flowerPotBlocks; diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BlockEntityTranslator.java index b89a2a547..7566e0d90 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BlockEntityTranslator.java @@ -30,6 +30,7 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; +import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.BlockEntityUtils; /** @@ -41,7 +42,7 @@ public abstract class BlockEntityTranslator { public abstract void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState); - public NbtMap getBlockEntityTag(BlockEntityType type, int x, int y, int z, CompoundTag tag, int blockState) { + public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, CompoundTag tag, int blockState) { NbtMapBuilder tagBuilder = getConstantBedrockTag(BlockEntityUtils.getBedrockBlockEntityId(type), x, y, z); translateTag(tagBuilder, tag, blockState); return tagBuilder.build(); diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SpawnerBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SpawnerBlockEntityTranslator.java index d1af70d8d..0aa8af279 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SpawnerBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SpawnerBlockEntityTranslator.java @@ -29,12 +29,44 @@ import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; 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 org.cloudburstmc.math.vector.Vector3i; +import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; +import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.registry.Registries; +import org.geysermc.geyser.session.GeyserSession; @BlockEntity(type = BlockEntityType.MOB_SPAWNER) public class SpawnerBlockEntityTranslator extends BlockEntityTranslator { + + @Override + public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, CompoundTag tag, int blockState) { + // Sending an empty EntityIdentifier to empty the spawner is ignored by the client, so we send a whole new spawner! + // Fixes https://github.com/GeyserMC/Geyser/issues/4214 + CompoundTag spawnData = tag.get("SpawnData"); + if (spawnData != null) { + CompoundTag entityTag = spawnData.get("entity"); + if (entityTag.isEmpty()) { + Vector3i position = Vector3i.from(x, y, z); + // Set to air and back to reset the spawner - "just" updating the spawner doesn't work + UpdateBlockPacket emptyBlockPacket = new UpdateBlockPacket(); + emptyBlockPacket.setDataLayer(0); + emptyBlockPacket.setBlockPosition(position); + emptyBlockPacket.setDefinition(session.getBlockMappings().getBedrockAir()); + session.sendUpstreamPacket(emptyBlockPacket); + + UpdateBlockPacket spawnerBlockPacket = new UpdateBlockPacket(); + spawnerBlockPacket.setDataLayer(0); + spawnerBlockPacket.setBlockPosition(position); + spawnerBlockPacket.setDefinition(session.getBlockMappings().getMobSpawnerBlock()); + session.sendUpstreamPacket(spawnerBlockPacket); + } + } + + return super.getBlockEntityTag(session, type, x, y, z, tag, blockState); + } + @Override public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) { Tag current; @@ -69,8 +101,8 @@ public class SpawnerBlockEntityTranslator extends BlockEntityTranslator { CompoundTag spawnData = tag.get("SpawnData"); if (spawnData != null) { - StringTag idTag = ((CompoundTag) spawnData.get("entity")).get("id"); - if (idTag != null) { + CompoundTag entityTag = spawnData.get("entity"); + if (entityTag.get("id") instanceof StringTag idTag) { // As of 1.19.3, spawners can be empty String entityId = idTag.getValue(); builder.put("EntityIdentifier", entityId); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEntityDataTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEntityDataTranslator.java index b86882d84..c67a6dee4 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEntityDataTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEntityDataTranslator.java @@ -62,7 +62,7 @@ public class JavaBlockEntityDataTranslator extends PacketTranslator Date: Fri, 1 Dec 2023 20:38:25 +0100 Subject: [PATCH 131/344] Fix: Recipe tags application We only need to use recipe tags when there is more than one possible ingredient option. For example, before this, we applied a logs item tag to the planks recipe, which caused an issue with plank type suggestions. (#4321) --- .../translator/protocol/java/JavaUpdateRecipesTranslator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java index 5beb1a201..71cb6019a 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java @@ -337,7 +337,7 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator 1) { optionSet.add(new ItemDescriptorWithCount(new ItemTagDescriptor(recipeTag), groupedItem.count)); continue; } From 308f293021e261a4504fea5831f6e32d5333ffd1 Mon Sep 17 00:00:00 2001 From: chris Date: Mon, 4 Dec 2023 01:44:06 +0100 Subject: [PATCH 132/344] Fix potential issue with the settings form - coordinate showing might change while we are in the settings menu (#4324) --- .../geysermc/geyser/util/SettingsUtils.java | 36 +++++++++++-------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/util/SettingsUtils.java b/core/src/main/java/org/geysermc/geyser/util/SettingsUtils.java index 8a8d684f6..ed97408b9 100644 --- a/core/src/main/java/org/geysermc/geyser/util/SettingsUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/SettingsUtils.java @@ -49,28 +49,32 @@ public class SettingsUtils { .title("geyser.settings.title.main") .iconPath("textures/ui/settings_glyph_color_2x.png"); + // Let's store these to avoid issues + boolean showCoordinates = session.getPreferencesCache().isAllowShowCoordinates(); + boolean cooldownShown = CooldownUtils.getDefaultShowCooldown() != CooldownUtils.CooldownType.DISABLED; + boolean customSkulls = session.getGeyser().getConfig().isAllowCustomSkulls(); + // Only show the client title if any of the client settings are available - boolean showClientSettings = session.getPreferencesCache().isAllowShowCoordinates() - || CooldownUtils.getDefaultShowCooldown() != CooldownUtils.CooldownType.DISABLED - || session.getGeyser().getConfig().isAllowCustomSkulls(); + boolean showClientSettings = showCoordinates || cooldownShown || customSkulls; if (showClientSettings) { builder.label("geyser.settings.title.client"); // Client can only see its coordinates if reducedDebugInfo is disabled and coordinates are enabled in geyser config. - if (session.getPreferencesCache().isAllowShowCoordinates()) { + if (showCoordinates) { builder.toggle("%createWorldScreen.showCoordinates", session.getPreferencesCache().isPrefersShowCoordinates()); } - if (CooldownUtils.getDefaultShowCooldown() != CooldownUtils.CooldownType.DISABLED) { + if (cooldownShown) { DropdownComponent.Builder cooldownDropdown = DropdownComponent.builder("options.attackIndicator"); - cooldownDropdown.option("options.attack.crosshair", session.getPreferencesCache().getCooldownPreference() == CooldownUtils.CooldownType.TITLE); - cooldownDropdown.option("options.attack.hotbar", session.getPreferencesCache().getCooldownPreference() == CooldownUtils.CooldownType.ACTIONBAR); - cooldownDropdown.option("options.off", session.getPreferencesCache().getCooldownPreference() == CooldownUtils.CooldownType.DISABLED); + CooldownUtils.CooldownType currentCooldownType = session.getPreferencesCache().getCooldownPreference(); + cooldownDropdown.option("options.attack.crosshair", currentCooldownType == CooldownUtils.CooldownType.TITLE); + cooldownDropdown.option("options.attack.hotbar", currentCooldownType == CooldownUtils.CooldownType.ACTIONBAR); + cooldownDropdown.option("options.off", currentCooldownType == CooldownUtils.CooldownType.DISABLED); builder.dropdown(cooldownDropdown); } - if (session.getGeyser().getConfig().isAllowCustomSkulls()) { + if (customSkulls) { builder.toggle("geyser.settings.option.customSkulls", session.getPreferencesCache().isPrefersCustomSkulls()); } } @@ -94,17 +98,21 @@ public class SettingsUtils { builder.validResultHandler((response) -> { if (showClientSettings) { // Client can only see its coordinates if reducedDebugInfo is disabled and coordinates are enabled in geyser config. - if (session.getPreferencesCache().isAllowShowCoordinates()) { - session.getPreferencesCache().setPrefersShowCoordinates(response.next()); - session.getPreferencesCache().updateShowCoordinates(); + if (showCoordinates) { + // In theory, a server could update the gamerule while the client is in the settings menu. + // We need to still read the response to update the client's preference, but we don't want to update the gamerule. + if (session.getPreferencesCache().isAllowShowCoordinates()) { + session.getPreferencesCache().setPrefersShowCoordinates(response.next()); + session.getPreferencesCache().updateShowCoordinates(); + } } - if (CooldownUtils.getDefaultShowCooldown() != CooldownUtils.CooldownType.DISABLED) { + if (cooldownShown) { CooldownUtils.CooldownType cooldownType = CooldownUtils.CooldownType.VALUES[(int) response.next()]; session.getPreferencesCache().setCooldownPreference(cooldownType); } - if (session.getGeyser().getConfig().isAllowCustomSkulls()) { + if (customSkulls) { session.getPreferencesCache().setPrefersCustomSkulls(response.next()); } } From 998caee156d38245a15e560f15864319ad125cbb Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Mon, 4 Dec 2023 17:05:12 -0500 Subject: [PATCH 133/344] Catch all throwables when loading each extension (#4320) --- .../geyser/extension/GeyserExtensionLoader.java | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/extension/GeyserExtensionLoader.java b/core/src/main/java/org/geysermc/geyser/extension/GeyserExtensionLoader.java index da0fbffda..2f0ff1580 100644 --- a/core/src/main/java/org/geysermc/geyser/extension/GeyserExtensionLoader.java +++ b/core/src/main/java/org/geysermc/geyser/extension/GeyserExtensionLoader.java @@ -56,7 +56,7 @@ public class GeyserExtensionLoader extends ExtensionLoader { private final Map extensionContainers = new HashMap<>(); private final Path extensionsDirectory = GeyserImpl.getInstance().getBootstrap().getConfigFolder().resolve("extensions"); - public GeyserExtensionContainer loadExtension(Path path, GeyserExtensionDescription description) throws InvalidExtensionException { + public GeyserExtensionContainer loadExtension(Path path, GeyserExtensionDescription description) throws Throwable { if (path == null) { throw new InvalidExtensionException("Path is null"); } @@ -92,8 +92,14 @@ public class GeyserExtensionLoader extends ExtensionLoader { this.classLoaders.put(description.id(), loader); - final Extension extension = loader.load(); - return this.setup(extension, description, dataFolder, new GeyserExtensionEventBus(GeyserImpl.getInstance().eventBus(), extension)); + try { + final Extension extension = loader.load(); + return this.setup(extension, description, dataFolder, new GeyserExtensionEventBus(GeyserImpl.getInstance().eventBus(), extension)); + } catch (Throwable e) { + // if the extension failed to load, remove its classloader and close it. + this.classLoaders.remove(description.id()).close(); + throw e; + } } private GeyserExtensionContainer setup(Extension extension, GeyserExtensionDescription description, Path dataFolder, ExtensionEventBus eventBus) { @@ -182,9 +188,10 @@ public class GeyserExtensionLoader extends ExtensionLoader { return; } + GeyserExtensionContainer container = this.loadExtension(path, description); extensions.put(id, path); - loadedExtensions.put(id, this.loadExtension(path, description)); - } catch (Exception e) { + loadedExtensions.put(id, container); + } catch (Throwable e) { GeyserImpl.getInstance().getLogger().error(GeyserLocale.getLocaleStringLog("geyser.extensions.load.failed_with_name", path.getFileName(), path.toAbsolutePath()), e); } }); From 95d65350e42bbffa0d2901e2b8a558968d85f24a Mon Sep 17 00:00:00 2001 From: chris Date: Wed, 6 Dec 2023 00:54:42 +0100 Subject: [PATCH 134/344] Project wide syntax/annotation cleanup (#4238) Co-authored-by: Konicai <71294714+Konicai@users.noreply.github.com> --- CONTRIBUTING.md | 18 +- .../geyser/processor/ClassProcessor.java | 4 +- .../org/geysermc/geyser/api/GeyserApi.java | 1 + .../api/bedrock/camera/CameraShake.java | 2 +- .../custom/component/PlacementConditions.java | 6 +- .../custom/nonvanilla/JavaBlockState.java | 12 +- .../custom/nonvanilla/JavaBoundingBox.java | 4 +- .../geysermc/geyser/api/event/EventBus.java | 1 - .../geyser/api/event/EventSubscriber.java | 1 - .../connection/GeyserBedrockPingEvent.java | 2 +- .../lifecycle/GeyserDefineCommandsEvent.java | 2 +- .../GeyserDefineCustomBlocksEvent.java | 7 +- .../GeyserDefineCustomItemsEvent.java | 2 +- .../GeyserDefineCustomSkullsEvent.java | 2 +- .../InvalidDescriptionException.java | 6 + .../exception/InvalidExtensionException.java | 6 + .../geyser/api/util/CreativeCategory.java | 2 +- .../geysermc/geyser/api/util/TriState.java | 2 +- .../bungeecord/GeyserBungeeDumpInfo.java | 4 +- .../bungeecord/GeyserBungeeInjector.java | 3 +- .../GeyserBungeePingPassthrough.java | 3 +- .../bungeecord/GeyserBungeePlugin.java | 5 +- .../command/BungeeCommandSource.java | 3 +- .../platform/fabric/GeyserFabricMod.java | 6 +- .../fabric/command/FabricCommandSender.java | 7 +- .../command/GeyserFabricCommandExecutor.java | 6 +- .../mixin/client/IntegratedServerMixin.java | 3 + .../world/GeyserFabricWorldManager.java | 16 +- .../spigot/GeyserPaperPingPassthrough.java | 7 +- .../GeyserSpigotCompressionDisabler.java | 2 +- .../platform/spigot/GeyserSpigotDumpInfo.java | 1 + .../platform/spigot/GeyserSpigotInjector.java | 13 +- .../spigot/GeyserSpigotPingPassthrough.java | 9 +- .../platform/spigot/GeyserSpigotPlugin.java | 9 +- .../spigot/GeyserSpigotVersionChecker.java | 1 + .../platform/spigot/PaperAdventure.java | 8 +- .../platform/spigot/ReflectedNames.java | 13 +- .../command/GeyserPaperCommandListener.java | 2 +- .../command/GeyserSpigotCommandExecutor.java | 5 +- .../spigot/command/SpigotCommandSource.java | 6 +- .../GeyserSpigotLegacyNativeWorldManager.java | 2 + .../GeyserSpigotNativeWorldManager.java | 2 +- .../manager/GeyserSpigotWorldManager.java | 41 +++-- .../standalone/GeyserStandaloneBootstrap.java | 8 +- .../platform/standalone/gui/ColorPane.java | 9 +- .../standalone/gui/GeyserStandaloneGUI.java | 7 +- .../platform/standalone/gui/GraphPanel.java | 9 +- .../velocity/GeyserVelocityInjector.java | 3 +- .../velocity/GeyserVelocityPlugin.java | 8 +- .../command/VelocityCommandSource.java | 3 +- .../floodgate/crypto/AesKeyProducer.java | 2 +- .../floodgate/crypto/FloodgateCipher.java | 5 +- .../floodgate/crypto/KeyProducer.java | 2 +- .../org/geysermc/floodgate/news/NewsItem.java | 1 + .../floodgate/news/NewsItemAction.java | 4 +- .../floodgate/news/NewsItemMessage.java | 3 +- .../org/geysermc/floodgate/news/NewsType.java | 3 +- .../news/data/BuildSpecificData.java | 1 + .../news/data/ConfigSpecificData.java | 1 + .../geysermc/floodgate/util/BedrockData.java | 2 + .../util/InvalidFormatException.java | 3 + .../geysermc/floodgate/util/LinkedPlayer.java | 3 +- .../geysermc/floodgate/util/UiProfile.java | 4 +- .../floodgate/util/WebsocketEventType.java | 4 +- .../org/geysermc/geyser/GeyserBootstrap.java | 2 +- .../java/org/geysermc/geyser/GeyserImpl.java | 10 +- .../org/geysermc/geyser/GeyserLogger.java | 5 +- .../java/org/geysermc/geyser/GeyserMain.java | 5 +- .../geyser/command/GeyserCommand.java | 11 +- .../geyser/command/GeyserCommandExecutor.java | 2 +- .../geyser/command/GeyserCommandManager.java | 7 +- .../defaults/ConnectionTestCommand.java | 2 +- .../geyser/command/defaults/DumpCommand.java | 2 +- .../command/defaults/ExtensionsCommand.java | 2 +- .../command/defaults/VersionCommand.java | 7 +- .../configuration/GeyserConfiguration.java | 2 + .../GeyserJacksonConfiguration.java | 5 +- .../org/geysermc/geyser/dump/DumpInfo.java | 63 ++----- .../geyser/entity/EntityDefinition.java | 1 + .../entity/attribute/GeyserAttributeType.java | 3 +- .../entity/type/AreaEffectCloudEntity.java | 1 - .../geysermc/geyser/entity/type/Entity.java | 3 +- .../geyser/entity/type/LivingEntity.java | 3 +- .../geyser/entity/type/ThrowableEntity.java | 1 - .../type/living/AbstractFishEntity.java | 6 +- .../entity/type/living/AllayEntity.java | 10 +- .../entity/type/living/ArmorStandEntity.java | 4 +- .../entity/type/living/DolphinEntity.java | 10 +- .../entity/type/living/IronGolemEntity.java | 6 +- .../geyser/entity/type/living/MobEntity.java | 10 +- .../entity/type/living/SnowGolemEntity.java | 10 +- .../entity/type/living/TadpoleEntity.java | 10 +- .../type/living/animal/AnimalEntity.java | 10 +- .../type/living/animal/AxolotlEntity.java | 6 +- .../entity/type/living/animal/CowEntity.java | 10 +- .../entity/type/living/animal/GoatEntity.java | 6 +- .../type/living/animal/MooshroomEntity.java | 10 +- .../type/living/animal/OcelotEntity.java | 10 +- .../type/living/animal/PandaEntity.java | 12 +- .../entity/type/living/animal/PigEntity.java | 10 +- .../type/living/animal/SheepEntity.java | 10 +- .../type/living/animal/StriderEntity.java | 10 +- .../animal/horse/AbstractHorseEntity.java | 28 ++-- .../type/living/animal/horse/CamelEntity.java | 1 - .../animal/horse/ChestedHorseEntity.java | 8 +- .../animal/horse/SkeletonHorseEntity.java | 10 +- .../animal/horse/ZombieHorseEntity.java | 10 +- .../living/animal/tameable/CatEntity.java | 10 +- .../living/animal/tameable/ParrotEntity.java | 10 +- .../living/animal/tameable/WolfEntity.java | 10 +- .../merchant/AbstractMerchantEntity.java | 10 +- .../type/living/merchant/VillagerEntity.java | 4 +- .../type/living/monster/CreeperEntity.java | 10 +- .../type/living/monster/PiglinEntity.java | 12 +- .../living/monster/ZombieVillagerEntity.java | 10 +- .../entity/type/player/PlayerEntity.java | 5 +- .../type/player/SessionPlayerEntity.java | 6 +- .../AbstractGeyserboundPacketHandler.java | 2 +- .../GeyserboundHandshakePacketHandler.java | 4 +- .../erosion/UnixSocketClientListener.java | 5 +- .../geysermc/geyser/event/GeyserEventBus.java | 1 - .../geyser/event/GeyserEventSubscriber.java | 1 - .../type/GeyserBedrockPingEventImpl.java | 9 +- .../GeyserDefineCustomItemsEventImpl.java | 4 +- .../geyser/inventory/AnvilContainer.java | 3 +- .../geysermc/geyser/inventory/Container.java | 5 +- .../geyser/inventory/Generic3X3Container.java | 2 +- .../geyser/inventory/GeyserEnchantOption.java | 2 +- .../geyser/inventory/GeyserItemStack.java | 12 +- .../geysermc/geyser/inventory/Inventory.java | 4 +- .../geyser/inventory/PlayerInventory.java | 11 +- .../inventory/StonecutterContainer.java | 2 +- .../geyser/inventory/item/Enchantment.java | 7 +- .../geyser/inventory/item/Potion.java | 5 +- .../inventory/item/StoredItemMappings.java | 4 +- .../inventory/item/TippedArrowPotion.java | 9 +- .../updater/AnvilInventoryUpdater.java | 7 +- .../geyser/item/GeyserCustomItemOptions.java | 6 +- .../geyser/item/GeyserCustomMappingData.java | 1 - .../item/GeyserNonVanillaCustomItemData.java | 6 +- .../geyser/item/components/ToolTier.java | 11 -- .../InvalidCustomMappingsFileException.java | 12 +- .../geysermc/geyser/item/type/ArrowItem.java | 4 +- .../geyser/item/type/AxolotlBucketItem.java | 4 +- .../geysermc/geyser/item/type/BannerItem.java | 11 +- .../geyser/item/type/CompassItem.java | 5 +- .../geyser/item/type/CrossbowItem.java | 2 +- .../geyser/item/type/EnchantedBookItem.java | 3 +- .../geyser/item/type/FishingRodItem.java | 3 +- .../geyser/item/type/GoatHornItem.java | 3 +- .../org/geysermc/geyser/item/type/Item.java | 6 +- .../geysermc/geyser/item/type/MapItem.java | 5 +- .../geysermc/geyser/item/type/PotionItem.java | 3 +- .../geysermc/geyser/level/BedrockMapIcon.java | 3 +- .../geysermc/geyser/level/FireworkColor.java | 3 +- .../geyser/level/GeyserAdvancement.java | 4 +- .../geyser/level/GeyserWorldManager.java | 7 +- .../geysermc/geyser/level/WorldManager.java | 11 +- .../geyser/level/block/DoubleChestValue.java | 13 +- .../level/block/GeyserCustomBlockData.java | 6 +- .../level/block/GeyserCustomBlockState.java | 2 +- .../level/block/GeyserJavaBlockState.java | 12 +- .../level/chunk/bitarray/BitArrayVersion.java | 7 +- .../level/physics/CollisionManager.java | 3 +- .../geyser/level/physics/Direction.java | 8 +- .../geyser/level/physics/PistonBehavior.java | 4 +- .../geysermc/geyser/network/GameProtocol.java | 3 +- .../network/GeyserServerInitializer.java | 4 +- .../geyser/network/netty/ChannelWrapper.java | 3 +- .../network/netty/LocalChannelWrapper.java | 13 +- .../geyser/network/netty/LocalSession.java | 5 +- .../handler/RakConnectionRequestHandler.java | 2 +- .../netty/proxy/ProxyProtocolDecoder.java | 11 +- .../pack/GeyserResourcePackManifest.java | 4 +- .../geyser/pack/SkullResourcePackManager.java | 5 +- .../ping/GeyserLegacyPingPassthrough.java | 3 +- .../geyser/ping/IGeyserPingPassthrough.java | 2 +- .../registry/AbstractMappedRegistry.java | 2 +- .../geyser/registry/ArrayRegistry.java | 2 +- .../geyser/registry/BlockRegistries.java | 1 - .../geyser/registry/IntMappedRegistry.java | 2 +- .../geysermc/geyser/registry/Registry.java | 1 - .../geyser/registry/VersionedRegistry.java | 8 +- .../loader/AnnotatedRegistryLoader.java | 1 + .../loader/BiomeIdentifierRegistryLoader.java | 2 +- .../loader/CollisionRegistryLoader.java | 5 +- .../registry/loader/EffectRegistryLoader.java | 2 +- .../loader/EnchantmentRegistryLoader.java | 2 +- .../registry/loader/NbtRegistryLoader.java | 2 +- .../loader/PotionMixRegistryLoader.java | 3 +- .../registry/loader/SoundRegistryLoader.java | 2 +- .../mappings/MappingsConfigReader.java | 17 +- .../mappings/util/CustomBlockMapping.java | 6 +- .../mappings/versions/MappingsReader.java | 9 +- .../mappings/versions/MappingsReader_v1.java | 14 +- .../populator/BlockRegistryPopulator.java | 33 ++-- .../CreativeItemRegistryPopulator.java | 7 +- .../CustomBlockRegistryPopulator.java | 15 +- .../CustomItemRegistryPopulator.java | 30 ++-- .../CustomSkullRegistryPopulator.java | 9 +- .../populator/ItemRegistryPopulator.java | 4 +- .../populator/RecipeRegistryPopulator.java | 2 +- .../geyser/registry/type/BlockMapping.java | 10 +- .../geyser/registry/type/BlockMappings.java | 5 +- .../geyser/registry/type/ParticleMapping.java | 6 +- .../geysermc/geyser/scoreboard/Objective.java | 3 +- .../geyser/scoreboard/Scoreboard.java | 13 +- .../geyser/scoreboard/ScoreboardUpdater.java | 1 + .../org/geysermc/geyser/scoreboard/Team.java | 6 +- .../geyser/session/GeyserSession.java | 17 +- .../PendingMicrosoftAuthentication.java | 12 +- .../geyser/session/SessionManager.java | 5 +- .../session/cache/AdvancementsCache.java | 2 +- .../geyser/session/cache/BookEditCache.java | 2 +- .../geyser/session/cache/LodestoneCache.java | 6 +- .../session/cache/PreferencesCache.java | 4 +- .../geyser/session/cache/SkullCache.java | 3 +- .../geyser/session/cache/WorldBorder.java | 5 +- .../geyser/skin/FakeHeadProvider.java | 4 +- .../org/geysermc/geyser/skin/SkinManager.java | 4 +- .../geysermc/geyser/skin/SkinProvider.java | 35 ++-- .../geyser/text/AsteriskSerializer.java | 10 +- .../geysermc/geyser/text/ChatTypeEntry.java | 7 +- .../text/DummyLegacyHoverEventSerializer.java | 10 +- .../geysermc/geyser/text/GeyserLocale.java | 3 +- .../text/GsonComponentSerializerWrapper.java | 16 +- .../geysermc/geyser/text/MinecraftLocale.java | 5 +- .../text/MinecraftTranslationRegistry.java | 12 +- .../translator/collision/BlockCollision.java | 2 +- .../collision/SpawnerCollision.java | 38 ----- .../inventory/InventoryTranslator.java | 2 +- .../inventory/item/ItemTranslator.java | 22 ++- .../block/entity/BedrockOnlyBlockEntity.java | 3 +- .../ShulkerBoxBlockEntityTranslator.java | 3 +- .../entity/SkullBlockEntityTranslator.java | 3 +- ...BedrockInventoryTransactionTranslator.java | 6 +- .../BedrockItemFrameDropItemTranslator.java | 2 +- .../entity/BedrockEntityEventTranslator.java | 2 +- .../protocol/java/JavaCommandsTranslator.java | 2 +- .../java/JavaLoginDisconnectTranslator.java | 4 +- .../java/JavaUpdateRecipesTranslator.java | 1 + .../java/entity/JavaAnimateTranslator.java | 24 ++- .../entity/JavaTakeItemEntityTranslator.java | 1 - .../JavaPlayerCombatKillTranslator.java | 1 - .../level/JavaBlockDestructionTranslator.java | 1 - .../level/JavaLevelParticlesTranslator.java | 3 +- .../translator/sound/SoundTranslator.java | 2 +- .../ComparatorSoundInteractionTranslator.java | 1 - .../block/DoorSoundInteractionTranslator.java | 1 - .../LeverSoundInteractionTranslator.java | 1 - .../translator/text/MessageTranslator.java | 2 +- .../geysermc/geyser/util/AttributeUtils.java | 2 +- .../geyser/util/BlockEntityUtils.java | 4 +- .../org/geysermc/geyser/util/BlockUtils.java | 3 +- .../geysermc/geyser/util/CooldownUtils.java | 2 +- .../org/geysermc/geyser/util/CpuUtils.java | 6 +- .../org/geysermc/geyser/util/FileUtils.java | 6 +- .../geysermc/geyser/util/InventoryUtils.java | 14 +- .../org/geysermc/geyser/util/ItemUtils.java | 5 +- .../geysermc/geyser/util/JavaCodecUtil.java | 4 +- .../org/geysermc/geyser/util/Metrics.java | 154 ++---------------- .../org/geysermc/geyser/util/SignUtils.java | 2 - .../org/geysermc/geyser/util/SoundUtils.java | 3 +- .../geyser/util/VersionCheckUtils.java | 7 +- .../org/geysermc/geyser/util/WebUtils.java | 13 +- .../util/collection/FixedInt2BooleanMap.java | 6 + .../util/collection/FixedInt2ByteMap.java | 6 + .../util/collection/FixedInt2IntMap.java | 5 + .../util/collection/LecternHasBookMap.java | 5 + .../geyser/util/collection/package-info.java | 2 +- 270 files changed, 891 insertions(+), 977 deletions(-) delete mode 100644 core/src/main/java/org/geysermc/geyser/translator/collision/SpawnerCollision.java diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dac8a9a07..a483fbe95 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -19,32 +19,28 @@ public class LongClassName { public int nameWithMultipleWords = 0; /** - * Javadoc comment to explain what a function does. - */ + * Javadoc comment to explain what a function does. + */ @RandomAnnotation(stuff = true, moreStuff = "might exist") public void applyStuff() { Variable variable = new Variable(); Variable otherVariable = new Variable(); if (condition) { - // Do stuff. + // Do stuff. } else if (anotherCondition) { - // Do something else. + // Do something else. } switch (value) { - case 0: - stuff(); - break; - case 1: - differentStuff(); - break; + case 0 -> stuff(); + case 1 -> differentStuff(); } } } ``` -Make sure to comment your code where possible. +Make sure to comment your code where possible. To mark nullable methods, use `@Nullable` (and subsequently, `@NonNull`) from the `org.checkerframework.checker.nullness.qual` package. The nature of our software requires a lot of arrays and maps to be stored - where possible, use Fastutil's specialized maps. For example, if you're storing block state translations, use an `Int2IntMap`. diff --git a/ap/src/main/java/org/geysermc/geyser/processor/ClassProcessor.java b/ap/src/main/java/org/geysermc/geyser/processor/ClassProcessor.java index e1da50f25..6fcd5d888 100644 --- a/ap/src/main/java/org/geysermc/geyser/processor/ClassProcessor.java +++ b/ap/src/main/java/org/geysermc/geyser/processor/ClassProcessor.java @@ -25,6 +25,8 @@ package org.geysermc.geyser.processor; +import org.checkerframework.checker.nullness.qual.Nullable; + import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.RoundEnvironment; @@ -159,7 +161,7 @@ public class ClassProcessor extends AbstractProcessor { this.processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Completed processing for " + this.annotationClassName); } - private BufferedReader createReader() throws IOException { + private @Nullable BufferedReader createReader() throws IOException { if (this.outputPath != null) { this.processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Reading existing " + this.annotationClassName + " list from " + this.outputPath); return Files.newBufferedReader(this.outputPath); diff --git a/api/src/main/java/org/geysermc/geyser/api/GeyserApi.java b/api/src/main/java/org/geysermc/geyser/api/GeyserApi.java index de5c78678..0d6007c1c 100644 --- a/api/src/main/java/org/geysermc/geyser/api/GeyserApi.java +++ b/api/src/main/java/org/geysermc/geyser/api/GeyserApi.java @@ -77,6 +77,7 @@ public interface GeyserApi extends GeyserApiBase { * @param apiClass the builder class * @param the implementation type * @param the API type + * @throws IllegalArgumentException if there is no provider for the specified API class * @return the builder instance */ @NonNull diff --git a/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraShake.java b/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraShake.java index 18bafb428..67b56b1f5 100644 --- a/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraShake.java +++ b/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraShake.java @@ -27,5 +27,5 @@ package org.geysermc.geyser.api.bedrock.camera; public enum CameraShake { POSITIONAL, - ROTATIONAL; + ROTATIONAL } diff --git a/api/src/main/java/org/geysermc/geyser/api/block/custom/component/PlacementConditions.java b/api/src/main/java/org/geysermc/geyser/api/block/custom/component/PlacementConditions.java index d06d9a967..e274fd8bd 100644 --- a/api/src/main/java/org/geysermc/geyser/api/block/custom/component/PlacementConditions.java +++ b/api/src/main/java/org/geysermc/geyser/api/block/custom/component/PlacementConditions.java @@ -25,11 +25,11 @@ package org.geysermc.geyser.api.block.custom.component; +import org.checkerframework.checker.nullness.qual.NonNull; + import java.util.LinkedHashMap; import java.util.Set; -import org.checkerframework.checker.nullness.qual.NonNull; - /** * This class is used to store conditions for a placement filter for a custom block. * @@ -43,7 +43,7 @@ public record PlacementConditions(@NonNull Set allowedFaces, @NonNull Link NORTH, SOUTH, WEST, - EAST; + EAST } public enum BlockFilterType { diff --git a/api/src/main/java/org/geysermc/geyser/api/block/custom/nonvanilla/JavaBlockState.java b/api/src/main/java/org/geysermc/geyser/api/block/custom/nonvanilla/JavaBlockState.java index 6293506a8..f7da4b932 100644 --- a/api/src/main/java/org/geysermc/geyser/api/block/custom/nonvanilla/JavaBlockState.java +++ b/api/src/main/java/org/geysermc/geyser/api/block/custom/nonvanilla/JavaBlockState.java @@ -39,7 +39,7 @@ public interface JavaBlockState { * * @return whether the block state is waterlogged */ - @NonNull boolean waterlogged(); + boolean waterlogged(); /** * Gets the collision of the block state @@ -53,7 +53,7 @@ public interface JavaBlockState { * * @return whether the block state can be broken with hand */ - @NonNull boolean canBreakWithHand(); + boolean canBreakWithHand(); /** * Gets the pick item of the block state @@ -74,7 +74,7 @@ public interface JavaBlockState { * * @return whether the block state has block entity */ - @Nullable boolean hasBlockEntity(); + boolean hasBlockEntity(); /** * Creates a new {@link JavaBlockState.Builder} instance @@ -94,17 +94,17 @@ public interface JavaBlockState { Builder blockHardness(@NonNegative float blockHardness); - Builder waterlogged(@NonNull boolean waterlogged); + Builder waterlogged(boolean waterlogged); Builder collision(@NonNull JavaBoundingBox[] collision); - Builder canBreakWithHand(@NonNull boolean canBreakWithHand); + Builder canBreakWithHand(boolean canBreakWithHand); Builder pickItem(@Nullable String pickItem); Builder pistonBehavior(@Nullable String pistonBehavior); - Builder hasBlockEntity(@Nullable boolean hasBlockEntity); + Builder hasBlockEntity(boolean hasBlockEntity); JavaBlockState build(); } diff --git a/api/src/main/java/org/geysermc/geyser/api/block/custom/nonvanilla/JavaBoundingBox.java b/api/src/main/java/org/geysermc/geyser/api/block/custom/nonvanilla/JavaBoundingBox.java index 56a4ca3da..9065e8711 100644 --- a/api/src/main/java/org/geysermc/geyser/api/block/custom/nonvanilla/JavaBoundingBox.java +++ b/api/src/main/java/org/geysermc/geyser/api/block/custom/nonvanilla/JavaBoundingBox.java @@ -1,6 +1,4 @@ package org.geysermc.geyser.api.block.custom.nonvanilla; -import org.checkerframework.checker.nullness.qual.NonNull; - -public record JavaBoundingBox(@NonNull double middleX, @NonNull double middleY, @NonNull double middleZ, @NonNull double sizeX, @NonNull double sizeY, @NonNull double sizeZ) { +public record JavaBoundingBox(double middleX, double middleY, double middleZ, double sizeX, double sizeY, double sizeZ) { } diff --git a/api/src/main/java/org/geysermc/geyser/api/event/EventBus.java b/api/src/main/java/org/geysermc/geyser/api/event/EventBus.java index 801bfa45f..3344e38f4 100644 --- a/api/src/main/java/org/geysermc/geyser/api/event/EventBus.java +++ b/api/src/main/java/org/geysermc/geyser/api/event/EventBus.java @@ -28,7 +28,6 @@ package org.geysermc.geyser.api.event; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.event.Event; import org.geysermc.event.bus.OwnedEventBus; -import org.geysermc.geyser.api.extension.Extension; import java.util.Set; diff --git a/api/src/main/java/org/geysermc/geyser/api/event/EventSubscriber.java b/api/src/main/java/org/geysermc/geyser/api/event/EventSubscriber.java index 7f91d09a3..258ef9164 100644 --- a/api/src/main/java/org/geysermc/geyser/api/event/EventSubscriber.java +++ b/api/src/main/java/org/geysermc/geyser/api/event/EventSubscriber.java @@ -27,7 +27,6 @@ package org.geysermc.geyser.api.event; import org.geysermc.event.Event; import org.geysermc.event.subscribe.OwnedSubscriber; -import org.geysermc.geyser.api.extension.Extension; /** * Represents a subscribed listener to a {@link Event}. Wraps around diff --git a/api/src/main/java/org/geysermc/geyser/api/event/connection/GeyserBedrockPingEvent.java b/api/src/main/java/org/geysermc/geyser/api/event/connection/GeyserBedrockPingEvent.java index 67a81ac58..10ccb93d5 100644 --- a/api/src/main/java/org/geysermc/geyser/api/event/connection/GeyserBedrockPingEvent.java +++ b/api/src/main/java/org/geysermc/geyser/api/event/connection/GeyserBedrockPingEvent.java @@ -34,7 +34,7 @@ import java.net.InetSocketAddress; /** * Called whenever Geyser gets pinged - * + *

* This event allows you to modify/obtain the MOTD, maximum player count, and current number of players online, * Geyser will reply to the client with what was given. */ diff --git a/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserDefineCommandsEvent.java b/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserDefineCommandsEvent.java index 77d5efa65..994373752 100644 --- a/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserDefineCommandsEvent.java +++ b/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserDefineCommandsEvent.java @@ -33,7 +33,7 @@ import java.util.Map; /** * Called when commands are defined within Geyser. - * + *

* This event allows you to register new commands using the {@link #register(Command)} * method and retrieve the default commands defined. */ diff --git a/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserDefineCustomBlocksEvent.java b/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserDefineCustomBlocksEvent.java index b1a01d7e6..a105578d9 100644 --- a/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserDefineCustomBlocksEvent.java +++ b/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserDefineCustomBlocksEvent.java @@ -28,13 +28,12 @@ package org.geysermc.geyser.api.event.lifecycle; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.api.block.custom.CustomBlockData; import org.geysermc.geyser.api.block.custom.CustomBlockState; -import org.geysermc.geyser.api.block.custom.nonvanilla.JavaBlockItem; import org.geysermc.geyser.api.block.custom.nonvanilla.JavaBlockState; import org.geysermc.event.Event; /** * Called on Geyser's startup when looking for custom blocks. Custom blocks must be registered through this event. - * + *

* This event will not be called if the "add-non-bedrock-items" setting is disabled in the Geyser config. */ public abstract class GeyserDefineCustomBlocksEvent implements Event { @@ -48,8 +47,8 @@ public abstract class GeyserDefineCustomBlocksEvent implements Event { /** * Registers the given {@link CustomBlockState} as an override for the * given java state identifier - * Java state identifiers are listed in - * https://raw.githubusercontent.com/GeyserMC/mappings/master/blocks.json + * Java state identifiers are listed + * here * * @param javaIdentifier the java state identifier to override * @param customBlockState the custom block state with which to override java state identifier diff --git a/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserDefineCustomItemsEvent.java b/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserDefineCustomItemsEvent.java index 0957b8551..bd14aaf43 100644 --- a/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserDefineCustomItemsEvent.java +++ b/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserDefineCustomItemsEvent.java @@ -36,7 +36,7 @@ import java.util.Map; /** * Called on Geyser's startup when looking for custom items. Custom items must be registered through this event. - * + *

* This event will not be called if the "add non-Bedrock items" setting is disabled in the Geyser config. */ public interface GeyserDefineCustomItemsEvent extends Event { diff --git a/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserDefineCustomSkullsEvent.java b/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserDefineCustomSkullsEvent.java index 17f7b599a..6443bbeb3 100644 --- a/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserDefineCustomSkullsEvent.java +++ b/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserDefineCustomSkullsEvent.java @@ -5,7 +5,7 @@ import org.geysermc.event.Event; /** * Called on Geyser's startup when looking for custom skulls. Custom skulls must be registered through this event. - * + *

* This event will not be called if the "add-non-bedrock-items" setting is disabled in the Geyser config. */ public abstract class GeyserDefineCustomSkullsEvent implements Event { diff --git a/api/src/main/java/org/geysermc/geyser/api/extension/exception/InvalidDescriptionException.java b/api/src/main/java/org/geysermc/geyser/api/extension/exception/InvalidDescriptionException.java index 1fe88e9e9..5313c1f40 100644 --- a/api/src/main/java/org/geysermc/geyser/api/extension/exception/InvalidDescriptionException.java +++ b/api/src/main/java/org/geysermc/geyser/api/extension/exception/InvalidDescriptionException.java @@ -25,10 +25,16 @@ package org.geysermc.geyser.api.extension.exception; +import java.io.Serial; + /** * Thrown when an extension's description is invalid. */ public class InvalidDescriptionException extends Exception { + + @Serial + private static final long serialVersionUID = 1L; + public InvalidDescriptionException(Throwable cause) { super(cause); } diff --git a/api/src/main/java/org/geysermc/geyser/api/extension/exception/InvalidExtensionException.java b/api/src/main/java/org/geysermc/geyser/api/extension/exception/InvalidExtensionException.java index 7fb6b6922..89780fe46 100644 --- a/api/src/main/java/org/geysermc/geyser/api/extension/exception/InvalidExtensionException.java +++ b/api/src/main/java/org/geysermc/geyser/api/extension/exception/InvalidExtensionException.java @@ -25,10 +25,16 @@ package org.geysermc.geyser.api.extension.exception; +import java.io.Serial; + /** * Thrown when an extension is invalid. */ public class InvalidExtensionException extends Exception { + + @Serial + private static final long serialVersionUID = 1L; + public InvalidExtensionException(Throwable cause) { super(cause); } diff --git a/api/src/main/java/org/geysermc/geyser/api/util/CreativeCategory.java b/api/src/main/java/org/geysermc/geyser/api/util/CreativeCategory.java index 7519ff157..207320b1e 100644 --- a/api/src/main/java/org/geysermc/geyser/api/util/CreativeCategory.java +++ b/api/src/main/java/org/geysermc/geyser/api/util/CreativeCategory.java @@ -51,7 +51,7 @@ public enum CreativeCategory { * * @return the name of the category */ - @NonNull public String internalName() { + public @NonNull String internalName() { return internalName; } diff --git a/api/src/main/java/org/geysermc/geyser/api/util/TriState.java b/api/src/main/java/org/geysermc/geyser/api/util/TriState.java index 457a38e32..a8bb723d6 100644 --- a/api/src/main/java/org/geysermc/geyser/api/util/TriState.java +++ b/api/src/main/java/org/geysermc/geyser/api/util/TriState.java @@ -30,7 +30,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; /** * This is a way to represent a boolean, but with a non set value added. - * This class was inspired by adventure's version https://github.com/KyoriPowered/adventure/blob/main/4/api/src/main/java/net/kyori/adventure/util/TriState.java + * This class was inspired by adventure's TriState */ public enum TriState { /** diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeDumpInfo.java b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeDumpInfo.java index ba7bc464f..85abd285b 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeDumpInfo.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeDumpInfo.java @@ -30,6 +30,7 @@ import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.plugin.Plugin; import org.geysermc.geyser.dump.BootstrapDumpInfo; +import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -51,7 +52,8 @@ public class GeyserBungeeDumpInfo extends BootstrapDumpInfo { this.plugins = new ArrayList<>(); for (net.md_5.bungee.api.config.ListenerInfo listener : proxy.getConfig().getListeners()) { - this.listeners.add(new ListenerInfo(listener.getHost().getHostString(), listener.getHost().getPort())); + InetSocketAddress address = (InetSocketAddress) listener.getSocketAddress(); + this.listeners.add(new ListenerInfo(address.getHostString(), address.getPort())); } for (Plugin plugin : proxy.getPluginManager().getPlugins()) { diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeInjector.java b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeInjector.java index e10b3ce6f..7c60ba95d 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeInjector.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeInjector.java @@ -39,6 +39,7 @@ import net.md_5.bungee.api.plugin.Listener; import net.md_5.bungee.api.plugin.Plugin; import net.md_5.bungee.event.EventHandler; import net.md_5.bungee.netty.PipelineUtils; +import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.network.netty.GeyserInjector; @@ -125,7 +126,7 @@ public class GeyserBungeeInjector extends GeyserInjector implements Listener { .channel(LocalServerChannelWrapper.class) .childHandler(new ChannelInitializer<>() { @Override - protected void initChannel(Channel ch) throws Exception { + protected void initChannel(@NonNull Channel ch) throws Exception { if (proxy.getConfig().getServers() == null) { // Proxy hasn't finished loading all plugins - it loads the config after all plugins // Probably doesn't need to be translatable? diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePingPassthrough.java b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePingPassthrough.java index e14e8ff66..3c3853ed8 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePingPassthrough.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePingPassthrough.java @@ -35,6 +35,7 @@ import net.md_5.bungee.api.connection.PendingConnection; import net.md_5.bungee.api.event.ProxyPingEvent; import net.md_5.bungee.api.plugin.Listener; import net.md_5.bungee.protocol.ProtocolConstants; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.ping.GeyserPingInfo; import org.geysermc.geyser.ping.IGeyserPingPassthrough; @@ -104,7 +105,7 @@ public class GeyserBungeePingPassthrough implements IGeyserPingPassthrough, List } @Override - public InetSocketAddress getVirtualHost() { + public @Nullable InetSocketAddress getVirtualHost() { return null; } diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java index e58abc3b4..c4eea66b8 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java @@ -30,6 +30,7 @@ import net.md_5.bungee.BungeeCord; import net.md_5.bungee.api.config.ListenerInfo; import net.md_5.bungee.api.plugin.Plugin; import net.md_5.bungee.protocol.ProtocolConstants; +import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.GeyserBootstrap; @@ -44,7 +45,6 @@ import org.geysermc.geyser.ping.IGeyserPingPassthrough; import org.geysermc.geyser.platform.bungeecord.command.GeyserBungeeCommandExecutor; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.util.FileUtils; -import org.jetbrains.annotations.NotNull; import java.io.File; import java.io.IOException; @@ -72,6 +72,7 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { private static boolean INITIALIZED = false; + @SuppressWarnings({"JavaReflectionMemberAccess", "ResultOfMethodCallIgnored"}) @Override public void onLoad() { GeyserLocale.init(this); @@ -251,7 +252,7 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { return this.geyserInjector.getServerSocketAddress(); } - @NotNull + @NonNull @Override public String getServerBindAddress() { return findCompatibleListener().map(InetSocketAddress::getHostString).orElse(""); diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/command/BungeeCommandSource.java b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/command/BungeeCommandSource.java index f65377643..e3099f170 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/command/BungeeCommandSource.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/command/BungeeCommandSource.java @@ -29,6 +29,7 @@ import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer; import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.api.connection.ProxiedPlayer; +import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.text.GeyserLocale; @@ -50,7 +51,7 @@ public class BungeeCommandSource implements GeyserCommandSource { } @Override - public void sendMessage(String message) { + public void sendMessage(@NonNull String message) { handle.sendMessage(TextComponent.fromLegacyText(message)); } diff --git a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMod.java b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMod.java index af0c9efca..071409046 100644 --- a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMod.java +++ b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMod.java @@ -37,6 +37,8 @@ import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.server.MinecraftServer; import org.apache.logging.log4j.LogManager; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserLogger; @@ -54,8 +56,6 @@ import org.geysermc.geyser.platform.fabric.command.GeyserFabricCommandExecutor; import org.geysermc.geyser.platform.fabric.world.GeyserFabricWorldManager; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.util.FileUtils; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.IOException; @@ -251,7 +251,7 @@ public class GeyserFabricMod implements ModInitializer, GeyserBootstrap { return this.server.getServerVersion(); } - @NotNull + @NonNull @Override public String getServerBindAddress() { String ip = this.server.getLocalIp(); diff --git a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/command/FabricCommandSender.java b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/command/FabricCommandSender.java index 6517ac133..28875ec6e 100644 --- a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/command/FabricCommandSender.java +++ b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/command/FabricCommandSender.java @@ -30,11 +30,12 @@ import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.minecraft.commands.CommandSourceStack; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; +import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.text.ChatColor; -import javax.annotation.Nonnull; +import java.util.Objects; public class FabricCommandSender implements GeyserCommandSource { @@ -50,7 +51,7 @@ public class FabricCommandSender implements GeyserCommandSource { } @Override - public void sendMessage(@Nonnull String message) { + public void sendMessage(@NonNull String message) { if (source.getEntity() instanceof ServerPlayer) { ((ServerPlayer) source.getEntity()).displayClientMessage(Component.literal(message), false); } else { @@ -62,7 +63,7 @@ public class FabricCommandSender implements GeyserCommandSource { public void sendMessage(net.kyori.adventure.text.Component message) { if (source.getEntity() instanceof ServerPlayer player) { String decoded = GsonComponentSerializer.gson().serialize(message); - player.displayClientMessage(Component.Serializer.fromJson(decoded), false); + player.displayClientMessage(Objects.requireNonNull(Component.Serializer.fromJson(decoded)), false); return; } GeyserCommandSource.super.sendMessage(message); diff --git a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/command/GeyserFabricCommandExecutor.java b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/command/GeyserFabricCommandExecutor.java index 8da7c8512..732b28ca7 100644 --- a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/command/GeyserFabricCommandExecutor.java +++ b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/command/GeyserFabricCommandExecutor.java @@ -52,12 +52,12 @@ public class GeyserFabricCommandExecutor extends GeyserCommandExecutor implement } @Override - public int run(CommandContext context) { + public int run(CommandContext context) { return runWithArgs(context, ""); } - public int runWithArgs(CommandContext context, String args) { - CommandSourceStack source = (CommandSourceStack) context.getSource(); + public int runWithArgs(CommandContext context, String args) { + CommandSourceStack source = context.getSource(); FabricCommandSender sender = new FabricCommandSender(source); GeyserSession session = getGeyserSession(sender); if (!testPermission(source)) { diff --git a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/mixin/client/IntegratedServerMixin.java b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/mixin/client/IntegratedServerMixin.java index 942909068..f11d3a1ae 100644 --- a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/mixin/client/IntegratedServerMixin.java +++ b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/mixin/client/IntegratedServerMixin.java @@ -42,6 +42,8 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import java.util.Objects; + @Environment(EnvType.CLIENT) @Mixin(IntegratedServer.class) public class IntegratedServerMixin implements GeyserServerPortGetter { @@ -58,6 +60,7 @@ public class IntegratedServerMixin implements GeyserServerPortGetter { // Ensure player locale has been loaded, in case it's different from Java system language GeyserLocale.loadGeyserLocale(this.minecraft.options.languageCode); // Give indication that Geyser is loaded + Objects.requireNonNull(this.minecraft.player); this.minecraft.player.displayClientMessage(Component.literal(GeyserLocale.getPlayerLocaleString("geyser.core.start", this.minecraft.options.languageCode, "localhost", String.valueOf(this.publishedPort))), false); } diff --git a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/world/GeyserFabricWorldManager.java b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/world/GeyserFabricWorldManager.java index 923db9b25..9d7b81831 100644 --- a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/world/GeyserFabricWorldManager.java +++ b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/world/GeyserFabricWorldManager.java @@ -39,6 +39,7 @@ import net.minecraft.world.level.block.entity.BannerBlockEntity; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.LecternBlockEntity; import net.minecraft.world.level.chunk.LevelChunk; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; @@ -48,9 +49,9 @@ import org.geysermc.geyser.level.GeyserWorldManager; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.BlockEntityUtils; -import javax.annotation.Nonnull; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.concurrent.CompletableFuture; public class GeyserFabricWorldManager extends GeyserWorldManager { @@ -73,9 +74,11 @@ public class GeyserFabricWorldManager extends GeyserWorldManager { return; } + //noinspection resource - level() is just a getter LevelChunk chunk = player.level().getChunk(x, z); final int chunkBlockX = x << 4; final int chunkBlockZ = z << 4; + //noinspection ForLoopReplaceableByForEach - avoid constructing iterator for (int i = 0; i < blockEntityInfos.size(); i++) { BlockEntityInfo blockEntityInfo = blockEntityInfos.get(i); BlockEntity blockEntity = chunk.getBlockEntity(new BlockPos(chunkBlockX + blockEntityInfo.getX(), @@ -92,7 +95,7 @@ public class GeyserFabricWorldManager extends GeyserWorldManager { if (player == null) { return; } - + //noinspection resource - level() is just a getter BlockEntity blockEntity = player.level().getBlockEntity(new BlockPos(x, y, z)); sendLecternData(session, blockEntity, false); }); @@ -159,7 +162,7 @@ public class GeyserFabricWorldManager extends GeyserWorldManager { return GameMode.byId(server.getDefaultGameType().getId()); } - @Nonnull + @NonNull @Override public CompletableFuture getPickItemNbt(GeyserSession session, int x, int y, int z, boolean addNbtData) { CompletableFuture future = new CompletableFuture<>(); @@ -172,6 +175,7 @@ public class GeyserFabricWorldManager extends GeyserWorldManager { BlockPos pos = new BlockPos(x, y, z); // Don't create a new block entity if invalid + //noinspection resource - level() is just a getter BlockEntity blockEntity = player.level().getChunkAt(pos).getBlockEntity(pos); if (blockEntity instanceof BannerBlockEntity banner) { // Potentially exposes other NBT data? But we need to get the NBT data for the banner patterns *and* @@ -263,7 +267,7 @@ public class GeyserFabricWorldManager extends GeyserWorldManager { } @Override - public void visitCompound(CompoundTag compoundTag) { + public void visitCompound(@NonNull CompoundTag compoundTag) { currentTag = convert(currentKey, compoundTag); } @@ -271,7 +275,7 @@ public class GeyserFabricWorldManager extends GeyserWorldManager { OpenNbtTagVisitor visitor = new OpenNbtTagVisitor(name); for (String key : compoundTag.getAllKeys()) { visitor.currentKey = key; - Tag tag = compoundTag.get(key); + Tag tag = Objects.requireNonNull(compoundTag.get(key)); tag.accept(visitor); visitor.root.put(visitor.currentTag); } @@ -279,7 +283,7 @@ public class GeyserFabricWorldManager extends GeyserWorldManager { } @Override - public void visitEnd(EndTag endTag) { + public void visitEnd(@NonNull EndTag endTag) { } } } diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserPaperPingPassthrough.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserPaperPingPassthrough.java index 60e0ae519..6a962f450 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserPaperPingPassthrough.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserPaperPingPassthrough.java @@ -28,11 +28,11 @@ package org.geysermc.geyser.platform.spigot; import com.destroystokyo.paper.event.server.PaperServerListPingEvent; import com.destroystokyo.paper.network.StatusClient; import org.bukkit.Bukkit; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.ping.GeyserPingInfo; import org.geysermc.geyser.ping.IGeyserPingPassthrough; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.lang.reflect.Constructor; import java.net.InetSocketAddress; @@ -50,6 +50,7 @@ public final class GeyserPaperPingPassthrough implements IGeyserPingPassthrough this.logger = logger; } + @SuppressWarnings("deprecation") @Nullable @Override public GeyserPingInfo getPingInformation(InetSocketAddress inetSocketAddress) { @@ -89,7 +90,7 @@ public final class GeyserPaperPingPassthrough implements IGeyserPingPassthrough private record GeyserStatusClient(InetSocketAddress address) implements StatusClient { @Override - public @NotNull InetSocketAddress getAddress() { + public @NonNull InetSocketAddress getAddress() { return address; } diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotCompressionDisabler.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotCompressionDisabler.java index 9b112f62f..2a6056df9 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotCompressionDisabler.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotCompressionDisabler.java @@ -34,7 +34,7 @@ import org.geysermc.geyser.GeyserImpl; /** * Disables the compression packet (and the compression handlers from being added to the pipeline) for Geyser clients * that won't be receiving the data over the network. - * + *

* As of 1.8 - 1.17.1, compression is enabled in the Netty pipeline by adding a listener after a packet is written. * If we simply "cancel" or don't forward the packet, then the listener is never called. */ diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotDumpInfo.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotDumpInfo.java index d340935b3..329663709 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotDumpInfo.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotDumpInfo.java @@ -47,6 +47,7 @@ public class GeyserSpigotDumpInfo extends BootstrapDumpInfo { private final int serverPort; private final List plugins; + @SuppressWarnings("deprecation") GeyserSpigotDumpInfo() { super(); this.platformName = Bukkit.getName(); diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java index e3d73fb19..01bc0bea4 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java @@ -32,6 +32,7 @@ import io.netty.channel.*; import io.netty.channel.local.LocalAddress; import io.netty.util.concurrent.DefaultThreadFactory; import org.bukkit.Bukkit; +import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.network.netty.GeyserInjector; import org.geysermc.geyser.network.netty.LocalServerChannelWrapper; @@ -74,12 +75,10 @@ public class GeyserSpigotInjector extends GeyserInjector { Object connection = null; // Find the class that manages network IO for (Method m : serverClazz.getDeclaredMethods()) { - if (m.getReturnType() != null) { - // First is Spigot-mapped name, second is Mojang-mapped name which is implemented as future-proofing - if (m.getReturnType().getSimpleName().equals("ServerConnection") || m.getReturnType().getSimpleName().equals("ServerConnectionListener")) { - if (m.getParameterTypes().length == 0) { - connection = m.invoke(server); - } + // First is Spigot-mapped name, second is Mojang-mapped name which is implemented as future-proofing + if (m.getReturnType().getSimpleName().equals("ServerConnection") || m.getReturnType().getSimpleName().equals("ServerConnectionListener")) { + if (m.getParameterTypes().length == 0) { + connection = m.invoke(server); } } } @@ -117,7 +116,7 @@ public class GeyserSpigotInjector extends GeyserInjector { .channel(LocalServerChannelWrapper.class) .childHandler(new ChannelInitializer<>() { @Override - protected void initChannel(Channel ch) throws Exception { + protected void initChannel(@NonNull Channel ch) throws Exception { initChannel.invoke(childHandler, ch); if (bootstrap.getGeyserConfig().isDisableCompression() && GeyserSpigotCompressionDisabler.ENABLED) { diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPingPassthrough.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPingPassthrough.java index df197f137..4b1e42871 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPingPassthrough.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPingPassthrough.java @@ -30,10 +30,12 @@ import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.server.ServerListPingEvent; import org.bukkit.util.CachedServerIcon; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.ping.GeyserPingInfo; import org.geysermc.geyser.ping.IGeyserPingPassthrough; -import javax.annotation.Nonnull; import java.net.InetAddress; import java.net.InetSocketAddress; import java.util.Collections; @@ -44,8 +46,9 @@ public class GeyserSpigotPingPassthrough implements IGeyserPingPassthrough { private final GeyserSpigotLogger logger; + @SuppressWarnings("deprecation") @Override - public GeyserPingInfo getPingInformation(InetSocketAddress inetSocketAddress) { + public @Nullable GeyserPingInfo getPingInformation(InetSocketAddress inetSocketAddress) { try { ServerListPingEvent event = new GeyserPingEvent(inetSocketAddress.getAddress(), Bukkit.getMotd(), Bukkit.getOnlinePlayers().size(), Bukkit.getMaxPlayers()); Bukkit.getPluginManager().callEvent(event); @@ -67,7 +70,7 @@ public class GeyserSpigotPingPassthrough implements IGeyserPingPassthrough { public void setServerIcon(CachedServerIcon icon) throws IllegalArgumentException, UnsupportedOperationException { } - @Nonnull + @NonNull @Override public Iterator iterator() throws UnsupportedOperationException { return Collections.emptyIterator(); diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java index cfb6ff5ae..02ea91cf2 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java @@ -42,13 +42,14 @@ import org.bukkit.permissions.Permission; import org.bukkit.permissions.PermissionDefault; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.java.JavaPlugin; -import org.geysermc.geyser.api.util.PlatformType; +import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.Constants; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.adapters.spigot.SpigotAdapters; import org.geysermc.geyser.api.command.Command; import org.geysermc.geyser.api.extension.Extension; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.command.GeyserCommandManager; import org.geysermc.geyser.configuration.GeyserConfiguration; import org.geysermc.geyser.dump.BootstrapDumpInfo; @@ -66,7 +67,6 @@ import org.geysermc.geyser.platform.spigot.world.manager.GeyserSpigotNativeWorld import org.geysermc.geyser.platform.spigot.world.manager.GeyserSpigotWorldManager; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.util.FileUtils; -import org.jetbrains.annotations.NotNull; import java.io.File; import java.io.IOException; @@ -76,6 +76,7 @@ import java.net.SocketAddress; import java.nio.file.Path; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.UUID; import java.util.logging.Level; @@ -137,6 +138,7 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { // This is manually done instead of using Bukkit methods to save the config because otherwise comments get removed try { if (!getDataFolder().exists()) { + //noinspection ResultOfMethodCallIgnored getDataFolder().mkdir(); } File configFile = FileUtils.fileOrCopiedFromResource(new File(getDataFolder(), "config.yml"), "config.yml", @@ -272,6 +274,7 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { } PluginCommand geyserCommand = this.getCommand("geyser"); + Objects.requireNonNull(geyserCommand, "base command cannot be null"); geyserCommand.setExecutor(new GeyserSpigotCommandExecutor(geyser, geyserCommandManager.getCommands())); for (Map.Entry> entry : this.geyserCommandManager.extensionCommands().entrySet()) { @@ -437,7 +440,7 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { return false; } - @NotNull + @NonNull @Override public String getServerBindAddress() { return Bukkit.getIp(); diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotVersionChecker.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotVersionChecker.java index 0212ff9b0..057304357 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotVersionChecker.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotVersionChecker.java @@ -39,6 +39,7 @@ import java.lang.reflect.Modifier; public final class GeyserSpigotVersionChecker { private static final String VIAVERSION_DOWNLOAD_URL = "https://ci.viaversion.com/job/ViaVersion/"; + @SuppressWarnings("deprecation") public static void checkForSupportedProtocol(GeyserLogger logger, boolean viaversion) { if (viaversion) { checkViaVersionSupportedVersions(logger); diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/PaperAdventure.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/PaperAdventure.java index 5dd16da33..9e0b14b11 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/PaperAdventure.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/PaperAdventure.java @@ -28,8 +28,8 @@ package org.geysermc.geyser.platform.spigot; import com.github.steveice10.mc.protocol.data.DefaultComponentSerializer; import net.kyori.adventure.text.Component; import org.bukkit.command.CommandSender; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.GeyserImpl; -import org.jetbrains.annotations.Nullable; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; @@ -39,8 +39,8 @@ import java.lang.reflect.Method; /** * Utility class for converting our shaded Adventure into the Adventure bundled in Paper. - * - * Code mostly taken from https://github.com/KyoriPowered/adventure-platform/blob/94d5821f2e755170f42bd8a5fe1d5bf6f66d04ad/platform-bukkit/src/main/java/net/kyori/adventure/platform/bukkit/PaperFacet.java#L46 + *

+ * Code mostly taken from here * and the MinecraftReflection class. */ public final class PaperAdventure { @@ -102,7 +102,7 @@ public final class PaperAdventure { SEND_MESSAGE_COMPONENT = playerComponentSendMessage; } - public static Object toNativeComponent(final Component component) { + public static @Nullable Object toNativeComponent(final Component component) { if (NATIVE_GSON_COMPONENT_SERIALIZER_DESERIALIZE_METHOD_BOUND == null) { GeyserImpl.getInstance().getLogger().error("Illegal state where Component serialization was called when it wasn't available!"); return null; diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/ReflectedNames.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/ReflectedNames.java index 67e31fea2..275fec657 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/ReflectedNames.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/ReflectedNames.java @@ -29,8 +29,8 @@ import com.destroystokyo.paper.event.server.PaperServerListPingEvent; import com.destroystokyo.paper.network.StatusClient; import org.bukkit.event.server.ServerListPingEvent; import org.bukkit.util.CachedServerIcon; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.lang.reflect.Constructor; import java.net.InetAddress; @@ -40,15 +40,8 @@ import java.net.InetAddress; public final class ReflectedNames { static boolean checkPaperPingEvent() { - return classExists("com.destroystokyo.paper.event.server.PaperServerListPingEvent"); - } - - /** - * @return if this class name exists - */ - private static boolean classExists(String clazz) { try { - Class.forName(clazz); + Class.forName("com.destroystokyo.paper.event.server.PaperServerListPingEvent"); return true; } catch (ClassNotFoundException e) { return false; @@ -59,7 +52,7 @@ public final class ReflectedNames { return getConstructor(ServerListPingEvent.class, InetAddress.class, String.class, boolean.class, int.class, int.class) != null; } - static Constructor getOldPaperPingConstructor() { + static @Nullable Constructor getOldPaperPingConstructor() { if (getConstructor(PaperServerListPingEvent.class, StatusClient.class, String.class, int.class, int.class, String.class, int.class, CachedServerIcon.class) != null) { // @NotNull StatusClient client, @NotNull String motd, int numPlayers, int maxPlayers, diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/GeyserPaperCommandListener.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/GeyserPaperCommandListener.java index 9375e3a62..dcec045ab 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/GeyserPaperCommandListener.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/GeyserPaperCommandListener.java @@ -39,8 +39,8 @@ import java.util.Map; public final class GeyserPaperCommandListener implements Listener { + @SuppressWarnings("UnstableApiUsage") @EventHandler - @SuppressWarnings("deprecation") // Used to indicate an unstable event public void onCommandSend(AsyncPlayerSendCommandsEvent event) { // Documentation says to check (event.isAsynchronous() || !event.hasFiredAsync()), but as of Paper 1.18.2 // event.hasFiredAsync is never true diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/GeyserSpigotCommandExecutor.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/GeyserSpigotCommandExecutor.java index 61d394214..6780bde17 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/GeyserSpigotCommandExecutor.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/GeyserSpigotCommandExecutor.java @@ -29,6 +29,7 @@ import org.bukkit.ChatColor; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.command.TabExecutor; +import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.command.GeyserCommand; import org.geysermc.geyser.command.GeyserCommandExecutor; @@ -47,7 +48,7 @@ public class GeyserSpigotCommandExecutor extends GeyserCommandExecutor implement } @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + public boolean onCommand(@NonNull CommandSender sender, @NonNull Command command, @NonNull String label, String[] args) { SpigotCommandSource commandSender = new SpigotCommandSource(sender); GeyserSession session = getGeyserSession(commandSender); @@ -78,7 +79,7 @@ public class GeyserSpigotCommandExecutor extends GeyserCommandExecutor implement } @Override - public List onTabComplete(CommandSender sender, Command command, String label, String[] args) { + public List onTabComplete(@NonNull CommandSender sender, @NonNull Command command, @NonNull String label, String[] args) { if (args.length == 1) { return tabComplete(new SpigotCommandSource(sender)); } diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/SpigotCommandSource.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/SpigotCommandSource.java index 95fba707f..365e9ad17 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/SpigotCommandSource.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/SpigotCommandSource.java @@ -29,6 +29,7 @@ import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer; import org.bukkit.command.ConsoleCommandSender; import org.bukkit.entity.Player; +import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.platform.spigot.PaperAdventure; import org.geysermc.geyser.text.GeyserLocale; @@ -48,10 +49,11 @@ public class SpigotCommandSource implements GeyserCommandSource { } @Override - public void sendMessage(String message) { + public void sendMessage(@NonNull String message) { handle.sendMessage(message); } + @SuppressWarnings("deprecation") @Override public void sendMessage(Component message) { if (PaperAdventure.canSendMessageUsingComponent()) { @@ -68,9 +70,11 @@ public class SpigotCommandSource implements GeyserCommandSource { return handle instanceof ConsoleCommandSender; } + @SuppressWarnings("deprecation") @Override public String locale() { if (this.handle instanceof Player player) { + // getLocale() is deprecated on Paper, but not on Spigot return player.getLocale(); } diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotLegacyNativeWorldManager.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotLegacyNativeWorldManager.java index baffc9679..021db5ec1 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotLegacyNativeWorldManager.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotLegacyNativeWorldManager.java @@ -37,6 +37,7 @@ import org.geysermc.geyser.platform.spigot.GeyserSpigotPlugin; import org.geysermc.geyser.session.GeyserSession; import java.util.List; +import java.util.Objects; /** * Used when block IDs need to be translated to the latest version @@ -52,6 +53,7 @@ public class GeyserSpigotLegacyNativeWorldManager extends GeyserSpigotNativeWorl ProtocolVersion serverVersion = plugin.getServerProtocolVersion(); List protocolList = Via.getManager().getProtocolManager().getProtocolPath(GameProtocol.getJavaProtocolVersion(), serverVersion.getVersion()); + Objects.requireNonNull(protocolList, "protocolList cannot be null"); for (int oldBlockId : allBlockStates) { int newBlockId = oldBlockId; // protocolList should *not* be null; we checked for that before initializing this class diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotNativeWorldManager.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotNativeWorldManager.java index 6b5d1ea1e..00212663c 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotNativeWorldManager.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotNativeWorldManager.java @@ -28,11 +28,11 @@ package org.geysermc.geyser.platform.spigot.world.manager; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.adapters.spigot.SpigotAdapters; import org.geysermc.geyser.adapters.spigot.SpigotWorldAdapter; import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.session.GeyserSession; -import org.jetbrains.annotations.Nullable; public class GeyserSpigotNativeWorldManager extends GeyserSpigotWorldManager { protected final SpigotWorldAdapter adapter; diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java index c8ccfffd7..74f359e02 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java @@ -34,21 +34,23 @@ import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.nbt.NbtMap; import org.geysermc.erosion.bukkit.BukkitLecterns; import org.geysermc.erosion.bukkit.BukkitUtils; import org.geysermc.erosion.bukkit.PickBlockUtils; import org.geysermc.erosion.bukkit.SchedulerUtils; +import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.level.GameRule; import org.geysermc.geyser.level.WorldManager; import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.BlockEntityUtils; -import org.jetbrains.annotations.Nullable; -import javax.annotation.Nonnull; import java.util.List; +import java.util.Objects; import java.util.concurrent.CompletableFuture; /** @@ -128,7 +130,7 @@ public class GeyserSpigotWorldManager extends WorldManager { } } - private Chunk getChunk(World world, int x, int z) { + private @Nullable Chunk getChunk(World world, int x, int z) { if (!world.isChunkLoaded(x, z)) { return null; } @@ -136,6 +138,7 @@ public class GeyserSpigotWorldManager extends WorldManager { } private void sendLecternData(GeyserSession session, Chunk chunk, List blockEntityInfos) { + //noinspection ForLoopReplaceableByForEach - avoid constructing Iterator for (int i = 0; i < blockEntityInfos.size(); i++) { BlockEntityInfo info = blockEntityInfos.get(i); Block block = chunk.getBlock(info.getX(), info.getY(), info.getZ()); @@ -156,19 +159,34 @@ public class GeyserSpigotWorldManager extends WorldManager { } public boolean getGameRuleBool(GeyserSession session, GameRule gameRule) { - String value = Bukkit.getPlayer(session.getPlayerEntity().getUsername()).getWorld().getGameRuleValue(gameRule.getJavaID()); - if (!value.isEmpty()) { - return Boolean.parseBoolean(value); + org.bukkit.GameRule bukkitGameRule = org.bukkit.GameRule.getByName(gameRule.getJavaID()); + if (bukkitGameRule == null) { + GeyserImpl.getInstance().getLogger().debug("Unknown game rule " + gameRule.getJavaID()); + return gameRule.getDefaultBooleanValue(); } + + Player bukkitPlayer = Objects.requireNonNull(Bukkit.getPlayer(session.getPlayerEntity().getUuid())); + Object value = bukkitPlayer.getWorld().getGameRuleValue(bukkitGameRule); + if (value instanceof Boolean booleanValue) { + return booleanValue; + } + GeyserImpl.getInstance().getLogger().debug("Expected a bool for " + gameRule + " but got " + value); return gameRule.getDefaultBooleanValue(); } @Override public int getGameRuleInt(GeyserSession session, GameRule gameRule) { - String value = Bukkit.getPlayer(session.getPlayerEntity().getUsername()).getWorld().getGameRuleValue(gameRule.getJavaID()); - if (!value.isEmpty()) { - return Integer.parseInt(value); + org.bukkit.GameRule bukkitGameRule = org.bukkit.GameRule.getByName(gameRule.getJavaID()); + if (bukkitGameRule == null) { + GeyserImpl.getInstance().getLogger().debug("Unknown game rule " + gameRule.getJavaID()); + return gameRule.getDefaultIntValue(); } + Player bukkitPlayer = Objects.requireNonNull(Bukkit.getPlayer(session.getPlayerEntity().getUuid())); + Object value = bukkitPlayer.getWorld().getGameRuleValue(bukkitGameRule); + if (value instanceof Integer intValue) { + return intValue; + } + GeyserImpl.getInstance().getLogger().debug("Expected an int for " + gameRule + " but got " + value); return gameRule.getDefaultIntValue(); } @@ -179,12 +197,11 @@ public class GeyserSpigotWorldManager extends WorldManager { @Override public boolean hasPermission(GeyserSession session, String permission) { - return Bukkit.getPlayer(session.getPlayerEntity().getUsername()).hasPermission(permission); + return Objects.requireNonNull(Bukkit.getPlayer(session.getPlayerEntity().getUsername())).hasPermission(permission); } - @Nonnull @Override - public CompletableFuture<@Nullable CompoundTag> getPickItemNbt(GeyserSession session, int x, int y, int z, boolean addNbtData) { + public @NonNull CompletableFuture<@Nullable CompoundTag> getPickItemNbt(GeyserSession session, int x, int y, int z, boolean addNbtData) { CompletableFuture<@Nullable CompoundTag> future = new CompletableFuture<>(); Player bukkitPlayer; if ((bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUuid())) == null) { diff --git a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java index b505b361e..9f2208ea8 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java @@ -38,6 +38,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.core.Appender; import org.apache.logging.log4j.core.Logger; import org.apache.logging.log4j.core.appender.ConsoleAppender; +import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; @@ -51,7 +52,6 @@ import org.geysermc.geyser.platform.standalone.gui.GeyserStandaloneGUI; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.util.FileUtils; import org.geysermc.geyser.util.LoopbackUtil; -import org.jetbrains.annotations.NotNull; import java.io.File; import java.io.IOException; @@ -292,7 +292,7 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap { return new GeyserStandaloneDumpInfo(this); } - @NotNull + @NonNull @Override public String getServerBindAddress() { throw new IllegalStateException(); @@ -325,7 +325,7 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap { // Get the ignored properties Set ignoredProperties = OBJECT_MAPPER.getSerializationConfig().getAnnotationIntrospector() - .findPropertyIgnorals(beanDescription.getClassInfo()).getIgnored(); + .findPropertyIgnoralByName(OBJECT_MAPPER.getSerializationConfig() ,beanDescription.getClassInfo()).getIgnored(); // Filter properties removing the ignored ones return properties.stream() @@ -340,7 +340,7 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap { * @param parentObject The object to alter * @param value The new value of the property */ - @SuppressWarnings("unchecked") // Required for enum usage + @SuppressWarnings({"unchecked", "rawtypes"}) // Required for enum usage private static void setConfigOption(BeanPropertyDefinition property, Object parentObject, Object value) { Object parsedValue = value; diff --git a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/gui/ColorPane.java b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/gui/ColorPane.java index 1bdc90123..8e0eadb08 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/gui/ColorPane.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/gui/ColorPane.java @@ -28,11 +28,16 @@ package org.geysermc.geyser.platform.standalone.gui; import javax.swing.*; import javax.swing.text.*; import java.awt.*; +import java.io.Serial; /** - * This class was based on this code: https://stackoverflow.com/a/6899478/5299903 + * This class was based on this code */ public class ColorPane extends JTextPane { + + @Serial + private static final long serialVersionUID = 1L; + private static Color colorCurrent = ANSIColor.RESET.getColor(); private String remaining = ""; @@ -62,7 +67,7 @@ public class ColorPane extends JTextPane { int aPos = 0; // current char position in addString int aIndex; // index of next Escape sequence int mIndex; // index of "m" terminating Escape sequence - String tmpString = ""; + String tmpString; boolean stillSearching = true; // true until no more Escape sequences String addString = remaining + s; remaining = ""; diff --git a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/gui/GeyserStandaloneGUI.java b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/gui/GeyserStandaloneGUI.java index af3e1069f..c3e2e10e8 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/gui/GeyserStandaloneGUI.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/gui/GeyserStandaloneGUI.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.platform.standalone.gui; +import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserLogger; import org.geysermc.geyser.command.GeyserCommandManager; @@ -64,7 +65,6 @@ public class GeyserStandaloneGUI { private final List ramValues = new ArrayList<>(); private final DefaultTableModel playerTableModel = new DefaultTableModel(); - private final JTable playerTable = new JTable(playerTableModel); /** * Create and show the Geyser-Standalone GUI @@ -158,6 +158,7 @@ public class GeyserStandaloneGUI { playerTableModel.addColumn(GeyserLocale.getLocaleStringLog("geyser.gui.table.ip")); playerTableModel.addColumn(GeyserLocale.getLocaleStringLog("geyser.gui.table.username")); + JTable playerTable = new JTable(playerTableModel); JScrollPane playerScrollPane = new JScrollPane(playerTable); rightContentPane.add(playerScrollPane); @@ -253,12 +254,12 @@ public class GeyserStandaloneGUI { } @Override - public void write(byte[] b, int off, int len) { + public void write(byte @NonNull [] b, int off, int len) { appendConsole(new String(b, off, len)); } @Override - public void write(byte[] b) { + public void write(byte @NonNull[] b) { write(b, 0, b.length); } }; diff --git a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/gui/GraphPanel.java b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/gui/GraphPanel.java index d8fca3e1b..063824218 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/gui/GraphPanel.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/gui/GraphPanel.java @@ -29,15 +29,20 @@ import lombok.Setter; import javax.swing.*; import java.awt.*; +import java.io.Serial; import java.util.ArrayList; import java.util.Collection; import java.util.List; /** * This has been modified to fit Geyser more but is based on - * https://gist.github.com/roooodcastro/6325153#gistcomment-3107524 + * this Github gist */ public final class GraphPanel extends JPanel { + + @Serial + private static final long serialVersionUID = 1L; + private final static int padding = 10; private final static int labelPadding = 25; private final static int pointWidth = 4; @@ -103,7 +108,7 @@ public final class GraphPanel extends JPanel { g.drawLine(padding + labelPadding + 1 + pointWidth, y, width - padding, y); g.setColor(Color.BLACK); - final int tickValue = (int) (minScore + ((scoreRange * i) / numberYDivisions)); + final int tickValue = minScore + ((scoreRange * i) / numberYDivisions); final String yLabel = tickValue + ""; final int labelWidth = fontMetrics.stringWidth(yLabel); g.drawString(yLabel, x1 - labelWidth - 5, y + (fontHeight / 2) - 3); diff --git a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityInjector.java b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityInjector.java index 4ffb286b8..68a9eb40b 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityInjector.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityInjector.java @@ -29,6 +29,7 @@ import com.velocitypowered.api.proxy.ProxyServer; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.*; import io.netty.channel.local.LocalAddress; +import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.network.netty.GeyserInjector; import org.geysermc.geyser.network.netty.LocalServerChannelWrapper; @@ -76,7 +77,7 @@ public class GeyserVelocityInjector extends GeyserInjector { .channel(LocalServerChannelWrapper.class) .childHandler(new ChannelInitializer<>() { @Override - protected void initChannel(Channel ch) throws Exception { + protected void initChannel(@NonNull Channel ch) throws Exception { initChannel.invoke(channelInitializer, ch); if (bootstrap.getGeyserConfig().isDisableCompression() && GeyserVelocityCompressionDisabler.ENABLED) { diff --git a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java index d7c6c588e..bd3d6085a 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java @@ -36,11 +36,13 @@ import com.velocitypowered.api.plugin.Plugin; import com.velocitypowered.api.proxy.ProxyServer; import lombok.Getter; import net.kyori.adventure.util.Codec; -import org.geysermc.geyser.api.util.PlatformType; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.command.Command; import org.geysermc.geyser.api.extension.Extension; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.command.GeyserCommandManager; import org.geysermc.geyser.configuration.GeyserConfiguration; import org.geysermc.geyser.dump.BootstrapDumpInfo; @@ -49,8 +51,6 @@ import org.geysermc.geyser.ping.IGeyserPingPassthrough; import org.geysermc.geyser.platform.velocity.command.GeyserVelocityCommandExecutor; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.util.FileUtils; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import java.io.File; @@ -222,7 +222,7 @@ public class GeyserVelocityPlugin implements GeyserBootstrap { return this.geyserInjector.getServerSocketAddress(); } - @NotNull + @NonNull @Override public String getServerBindAddress() { return proxyServer.getBoundAddress().getHostString(); diff --git a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/command/VelocityCommandSource.java b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/command/VelocityCommandSource.java index 00c99e92b..403e4cb20 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/command/VelocityCommandSource.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/command/VelocityCommandSource.java @@ -30,6 +30,7 @@ import com.velocitypowered.api.proxy.ConsoleCommandSource; import com.velocitypowered.api.proxy.Player; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.text.GeyserLocale; @@ -56,7 +57,7 @@ public class VelocityCommandSource implements GeyserCommandSource { } @Override - public void sendMessage(String message) { + public void sendMessage(@NonNull String message) { handle.sendMessage(LegacyComponentSerializer.legacy('§').deserialize(message)); } diff --git a/common/src/main/java/org/geysermc/floodgate/crypto/AesKeyProducer.java b/common/src/main/java/org/geysermc/floodgate/crypto/AesKeyProducer.java index 4fae21b32..e39d5119a 100644 --- a/common/src/main/java/org/geysermc/floodgate/crypto/AesKeyProducer.java +++ b/common/src/main/java/org/geysermc/floodgate/crypto/AesKeyProducer.java @@ -32,7 +32,7 @@ import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; public final class AesKeyProducer implements KeyProducer { - public static int KEY_SIZE = 128; + public static final int KEY_SIZE = 128; @Override public SecretKey produce() { diff --git a/common/src/main/java/org/geysermc/floodgate/crypto/FloodgateCipher.java b/common/src/main/java/org/geysermc/floodgate/crypto/FloodgateCipher.java index 2f7b442f4..d3001f374 100644 --- a/common/src/main/java/org/geysermc/floodgate/crypto/FloodgateCipher.java +++ b/common/src/main/java/org/geysermc/floodgate/crypto/FloodgateCipher.java @@ -25,6 +25,7 @@ package org.geysermc.floodgate.crypto; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.floodgate.util.InvalidFormatException; import java.security.Key; @@ -97,7 +98,8 @@ public interface FloodgateCipher { * @return the decrypted data in a UTF-8 String * @throws Exception when the decrypting failed */ - default String decryptToString(byte[] data) throws Exception { + @SuppressWarnings("unused") + default @Nullable String decryptToString(byte[] data) throws Exception { byte[] decrypted = decrypt(data); if (decrypted == null) { return null; @@ -113,6 +115,7 @@ public interface FloodgateCipher { * @return the decrypted data in a byte[] * @throws Exception when the decrypting failed */ + @SuppressWarnings("unused") default byte[] decryptFromString(String data) throws Exception { return decrypt(data.getBytes(UTF_8)); } diff --git a/common/src/main/java/org/geysermc/floodgate/crypto/KeyProducer.java b/common/src/main/java/org/geysermc/floodgate/crypto/KeyProducer.java index 4ee00f366..0b8679dad 100644 --- a/common/src/main/java/org/geysermc/floodgate/crypto/KeyProducer.java +++ b/common/src/main/java/org/geysermc/floodgate/crypto/KeyProducer.java @@ -31,7 +31,7 @@ import java.nio.file.Path; import java.security.Key; public interface KeyProducer { - Key produce(); + @SuppressWarnings("unused") Key produce(); Key produceFrom(byte[] keyFileData); default Key produceFrom(Path keyFileLocation) throws IOException { diff --git a/common/src/main/java/org/geysermc/floodgate/news/NewsItem.java b/common/src/main/java/org/geysermc/floodgate/news/NewsItem.java index 8ae28f422..f0dd3fadb 100644 --- a/common/src/main/java/org/geysermc/floodgate/news/NewsItem.java +++ b/common/src/main/java/org/geysermc/floodgate/news/NewsItem.java @@ -109,6 +109,7 @@ public final class NewsItem { return (T) data; } + @SuppressWarnings("unused") public String getRawMessage() { return message; } diff --git a/common/src/main/java/org/geysermc/floodgate/news/NewsItemAction.java b/common/src/main/java/org/geysermc/floodgate/news/NewsItemAction.java index 00e34b622..31995e25d 100644 --- a/common/src/main/java/org/geysermc/floodgate/news/NewsItemAction.java +++ b/common/src/main/java/org/geysermc/floodgate/news/NewsItemAction.java @@ -25,6 +25,8 @@ package org.geysermc.floodgate.news; +import org.checkerframework.checker.nullness.qual.Nullable; + public enum NewsItemAction { ON_SERVER_STARTED, ON_OPERATOR_JOIN, @@ -33,7 +35,7 @@ public enum NewsItemAction { private static final NewsItemAction[] VALUES = values(); - public static NewsItemAction getByName(String actionName) { + public static @Nullable NewsItemAction getByName(String actionName) { for (NewsItemAction type : VALUES) { if (type.name().equalsIgnoreCase(actionName)) { return type; diff --git a/common/src/main/java/org/geysermc/floodgate/news/NewsItemMessage.java b/common/src/main/java/org/geysermc/floodgate/news/NewsItemMessage.java index 9c2f3d15d..ed5d8f949 100644 --- a/common/src/main/java/org/geysermc/floodgate/news/NewsItemMessage.java +++ b/common/src/main/java/org/geysermc/floodgate/news/NewsItemMessage.java @@ -26,6 +26,7 @@ package org.geysermc.floodgate.news; import com.google.gson.JsonArray; +import org.checkerframework.checker.nullness.qual.Nullable; // {} is used for things that have to be filled in by the server, // {@} is for things that have to be filled in by us @@ -49,7 +50,7 @@ public enum NewsItemMessage { this.messageSplitted = messageFormat.split(" "); } - public static NewsItemMessage getById(int id) { + public static @Nullable NewsItemMessage getById(int id) { return VALUES.length > id ? VALUES[id] : null; } diff --git a/common/src/main/java/org/geysermc/floodgate/news/NewsType.java b/common/src/main/java/org/geysermc/floodgate/news/NewsType.java index ed7c1553b..af1d8bc38 100644 --- a/common/src/main/java/org/geysermc/floodgate/news/NewsType.java +++ b/common/src/main/java/org/geysermc/floodgate/news/NewsType.java @@ -26,6 +26,7 @@ package org.geysermc.floodgate.news; import com.google.gson.JsonObject; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.floodgate.news.data.*; import java.util.function.Function; @@ -44,7 +45,7 @@ public enum NewsType { this.readFunction = readFunction; } - public static NewsType getByName(String newsType) { + public static @Nullable NewsType getByName(String newsType) { for (NewsType type : VALUES) { if (type.name().equalsIgnoreCase(newsType)) { return type; diff --git a/common/src/main/java/org/geysermc/floodgate/news/data/BuildSpecificData.java b/common/src/main/java/org/geysermc/floodgate/news/data/BuildSpecificData.java index 7f2c7360f..c987dcfbc 100644 --- a/common/src/main/java/org/geysermc/floodgate/news/data/BuildSpecificData.java +++ b/common/src/main/java/org/geysermc/floodgate/news/data/BuildSpecificData.java @@ -56,6 +56,7 @@ public final class BuildSpecificData implements ItemData { (allAffected || buildId > affectedGreaterThan && buildId < affectedLessThan); } + @SuppressWarnings("unused") public String getBranch() { return branch; } diff --git a/common/src/main/java/org/geysermc/floodgate/news/data/ConfigSpecificData.java b/common/src/main/java/org/geysermc/floodgate/news/data/ConfigSpecificData.java index 1479d20a1..6993fe91d 100644 --- a/common/src/main/java/org/geysermc/floodgate/news/data/ConfigSpecificData.java +++ b/common/src/main/java/org/geysermc/floodgate/news/data/ConfigSpecificData.java @@ -51,6 +51,7 @@ public final class ConfigSpecificData implements ItemData { return configSpecificData; } + @SuppressWarnings("unused") public boolean isAffected(Map config) { for (Map.Entry entry : affectedKeys.entrySet()) { if (config.containsKey(entry.getKey())) { diff --git a/common/src/main/java/org/geysermc/floodgate/util/BedrockData.java b/common/src/main/java/org/geysermc/floodgate/util/BedrockData.java index 95fc62229..f0ed6ea00 100644 --- a/common/src/main/java/org/geysermc/floodgate/util/BedrockData.java +++ b/common/src/main/java/org/geysermc/floodgate/util/BedrockData.java @@ -72,6 +72,7 @@ public final class BedrockData implements Cloneable { false, subscribeId, verifyCode); } + @SuppressWarnings("unused") public static BedrockData fromString(String data) { String[] split = data.split("\0"); if (split.length != EXPECTED_LENGTH) { @@ -92,6 +93,7 @@ public final class BedrockData implements Cloneable { dataLength); } + @SuppressWarnings("unused") public boolean hasPlayerLink() { return linkedPlayer != null; } diff --git a/common/src/main/java/org/geysermc/floodgate/util/InvalidFormatException.java b/common/src/main/java/org/geysermc/floodgate/util/InvalidFormatException.java index e0630d48c..a2526700e 100644 --- a/common/src/main/java/org/geysermc/floodgate/util/InvalidFormatException.java +++ b/common/src/main/java/org/geysermc/floodgate/util/InvalidFormatException.java @@ -26,6 +26,9 @@ package org.geysermc.floodgate.util; public class InvalidFormatException extends Exception { + + private static final long serialVersionUID = 1L; + public InvalidFormatException(String message) { super(message); } diff --git a/common/src/main/java/org/geysermc/floodgate/util/LinkedPlayer.java b/common/src/main/java/org/geysermc/floodgate/util/LinkedPlayer.java index 681080a30..0a131071e 100644 --- a/common/src/main/java/org/geysermc/floodgate/util/LinkedPlayer.java +++ b/common/src/main/java/org/geysermc/floodgate/util/LinkedPlayer.java @@ -28,6 +28,7 @@ package org.geysermc.floodgate.util; import lombok.AccessLevel; import lombok.Getter; import lombok.RequiredArgsConstructor; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.UUID; @@ -56,7 +57,7 @@ public final class LinkedPlayer implements Cloneable { return new LinkedPlayer(javaUsername, javaUniqueId, bedrockId); } - public static LinkedPlayer fromString(String data) { + public static @Nullable LinkedPlayer fromString(String data) { String[] split = data.split(";"); if (split.length != 3) { return null; diff --git a/common/src/main/java/org/geysermc/floodgate/util/UiProfile.java b/common/src/main/java/org/geysermc/floodgate/util/UiProfile.java index d93042277..4438ae67f 100644 --- a/common/src/main/java/org/geysermc/floodgate/util/UiProfile.java +++ b/common/src/main/java/org/geysermc/floodgate/util/UiProfile.java @@ -25,6 +25,8 @@ package org.geysermc.floodgate.util; +import org.checkerframework.checker.nullness.qual.NonNull; + public enum UiProfile { CLASSIC, POCKET; @@ -37,7 +39,7 @@ public enum UiProfile { * @param id the UiProfile identifier * @return The UiProfile or {@link #CLASSIC} if the UiProfile wasn't found */ - public static UiProfile fromId(int id) { + public static @NonNull UiProfile fromId(int id) { return VALUES.length > id ? VALUES[id] : VALUES[0]; } } diff --git a/common/src/main/java/org/geysermc/floodgate/util/WebsocketEventType.java b/common/src/main/java/org/geysermc/floodgate/util/WebsocketEventType.java index 61e6c63b1..dffbabaaf 100644 --- a/common/src/main/java/org/geysermc/floodgate/util/WebsocketEventType.java +++ b/common/src/main/java/org/geysermc/floodgate/util/WebsocketEventType.java @@ -25,6 +25,8 @@ package org.geysermc.floodgate.util; +import org.checkerframework.checker.nullness.qual.Nullable; + public enum WebsocketEventType { /** * Sent once we successfully connected to the server @@ -81,7 +83,7 @@ public enum WebsocketEventType { this.id = id; } - public static WebsocketEventType fromId(int id) { + public static @Nullable WebsocketEventType fromId(int id) { return VALUES.length > id ? VALUES[id] : null; } diff --git a/core/src/main/java/org/geysermc/geyser/GeyserBootstrap.java b/core/src/main/java/org/geysermc/geyser/GeyserBootstrap.java index 1827cfb36..4dbc1dca3 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserBootstrap.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserBootstrap.java @@ -152,7 +152,7 @@ public interface GeyserBootstrap { * @param resource Resource to get * @return InputStream of the given resource */ - default @NonNull InputStream getResource(String resource) { + default @NonNull InputStream getResourceOrThrow(@NonNull String resource) { InputStream stream = getResourceOrNull(resource); if (stream == null) { throw new AssertionError("Unable to find resource: " + resource); diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index 185ab7c2a..aef2288d6 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -71,6 +71,7 @@ import org.geysermc.geyser.level.WorldManager; import org.geysermc.geyser.network.netty.GeyserServer; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.Registries; +import org.geysermc.geyser.registry.provider.ProviderSupplier; import org.geysermc.geyser.scoreboard.ScoreboardUpdater; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.PendingMicrosoftAuthentication; @@ -622,7 +623,7 @@ public class GeyserImpl implements GeyserApi { */ public boolean isProductionEnvironment() { // First is if Blossom runs, second is if Blossom doesn't run - // noinspection ConstantConditions - changes in production + //noinspection ConstantConditions,MismatchedStringCase - changes in production return !("git-local/dev-0000000".equals(GeyserImpl.GIT_VERSION) || "${gitVersion}".equals(GeyserImpl.GIT_VERSION)); } @@ -638,8 +639,13 @@ public class GeyserImpl implements GeyserApi { } @Override + @SuppressWarnings("unchecked") public @NonNull R provider(@NonNull Class apiClass, @Nullable Object... args) { - return (R) Registries.PROVIDERS.get(apiClass).create(args); + ProviderSupplier provider = Registries.PROVIDERS.get(apiClass); + if (provider == null) { + throw new IllegalArgumentException("No provider found for " + apiClass); + } + return (R) provider.create(args); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/GeyserLogger.java b/core/src/main/java/org/geysermc/geyser/GeyserLogger.java index 88220eec9..aa79e3630 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserLogger.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserLogger.java @@ -26,9 +26,10 @@ package org.geysermc.geyser; import net.kyori.adventure.text.Component; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.command.GeyserCommandSource; -import javax.annotation.Nullable; public interface GeyserLogger extends GeyserCommandSource { @@ -119,7 +120,7 @@ public interface GeyserLogger extends GeyserCommandSource { } @Override - default void sendMessage(String message) { + default void sendMessage(@NonNull String message) { info(message); } diff --git a/core/src/main/java/org/geysermc/geyser/GeyserMain.java b/core/src/main/java/org/geysermc/geyser/GeyserMain.java index 4e60a79b8..05cbebed4 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserMain.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserMain.java @@ -30,6 +30,7 @@ import java.io.InputStream; import java.lang.reflect.Method; import java.nio.charset.StandardCharsets; import java.util.Locale; +import java.util.Objects; import java.util.Scanner; public class GeyserMain { @@ -61,8 +62,8 @@ public class GeyserMain { helpStream = GeyserMain.class.getClassLoader().getResourceAsStream("languages/run-help/en_US.txt"); } - Scanner help = new Scanner(helpStream, StandardCharsets.UTF_8).useDelimiter("\\Z"); - String line = ""; + Scanner help = new Scanner(Objects.requireNonNull(helpStream), StandardCharsets.UTF_8).useDelimiter("\\Z"); + String line; while (help.hasNext()) { line = help.next(); diff --git a/core/src/main/java/org/geysermc/geyser/command/GeyserCommand.java b/core/src/main/java/org/geysermc/geyser/command/GeyserCommand.java index 5808dbc2c..47d57e73f 100644 --- a/core/src/main/java/org/geysermc/geyser/command/GeyserCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/GeyserCommand.java @@ -29,10 +29,10 @@ import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.experimental.Accessors; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.api.command.Command; import org.geysermc.geyser.session.GeyserSession; -import javax.annotation.Nullable; import java.util.Collections; import java.util.List; @@ -73,15 +73,6 @@ public abstract class GeyserCommand implements Command { return Collections.emptyList(); } - /** - * Shortcut to {@link #subCommands()} ()}{@code .isEmpty()}. - * - * @return true if there are subcommand present for this command. - */ - public boolean hasSubCommands() { - return !this.subCommands().isEmpty(); - } - public void setAliases(List aliases) { this.aliases = aliases; } diff --git a/core/src/main/java/org/geysermc/geyser/command/GeyserCommandExecutor.java b/core/src/main/java/org/geysermc/geyser/command/GeyserCommandExecutor.java index a9b1c734f..37d2ef4fb 100644 --- a/core/src/main/java/org/geysermc/geyser/command/GeyserCommandExecutor.java +++ b/core/src/main/java/org/geysermc/geyser/command/GeyserCommandExecutor.java @@ -26,11 +26,11 @@ package org.geysermc.geyser.command; import lombok.AllArgsConstructor; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.command.Command; import org.geysermc.geyser.session.GeyserSession; -import javax.annotation.Nullable; import java.util.ArrayList; import java.util.Collections; import java.util.List; diff --git a/core/src/main/java/org/geysermc/geyser/command/GeyserCommandManager.java b/core/src/main/java/org/geysermc/geyser/command/GeyserCommandManager.java index 373395ea2..d646845c7 100644 --- a/core/src/main/java/org/geysermc/geyser/command/GeyserCommandManager.java +++ b/core/src/main/java/org/geysermc/geyser/command/GeyserCommandManager.java @@ -29,6 +29,7 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import lombok.Getter; import lombok.RequiredArgsConstructor; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.command.Command; @@ -53,8 +54,6 @@ import org.geysermc.geyser.event.type.GeyserDefineCommandsEventImpl; import org.geysermc.geyser.extension.command.GeyserExtensionCommand; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.GeyserLocale; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.Collections; import java.util.HashMap; @@ -136,12 +135,12 @@ public class GeyserCommandManager { } } - @NotNull + @NonNull public Map commands() { return Collections.unmodifiableMap(this.commands); } - @NotNull + @NonNull public Map> extensionCommands() { return Collections.unmodifiableMap(this.extensionCommands); } diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/ConnectionTestCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/ConnectionTestCommand.java index 12294ae06..4cda72c9b 100644 --- a/core/src/main/java/org/geysermc/geyser/command/defaults/ConnectionTestCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/ConnectionTestCommand.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.command.defaults; import com.fasterxml.jackson.databind.JsonNode; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.command.GeyserCommand; @@ -34,7 +35,6 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.util.LoopbackUtil; import org.geysermc.geyser.util.WebUtils; -import org.jetbrains.annotations.Nullable; import java.util.Random; import java.util.concurrent.CompletableFuture; diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/DumpCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/DumpCommand.java index 544be7446..b3fee375f 100644 --- a/core/src/main/java/org/geysermc/geyser/command/defaults/DumpCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/DumpCommand.java @@ -98,7 +98,7 @@ public class DumpCommand extends GeyserCommand { return; } - String uploadedDumpUrl = ""; + String uploadedDumpUrl; if (offlineDump) { sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.dump.writing", sender.locale())); diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/ExtensionsCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/ExtensionsCommand.java index 30d422b23..df33437d9 100644 --- a/core/src/main/java/org/geysermc/geyser/command/defaults/ExtensionsCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/ExtensionsCommand.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.command.defaults; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.extension.Extension; import org.geysermc.geyser.command.GeyserCommand; @@ -32,7 +33,6 @@ import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.GeyserLocale; -import org.jetbrains.annotations.Nullable; import java.util.Comparator; import java.util.List; diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/VersionCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/VersionCommand.java index b263d6727..eb2e8ff47 100644 --- a/core/src/main/java/org/geysermc/geyser/command/defaults/VersionCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/VersionCommand.java @@ -27,8 +27,8 @@ package org.geysermc.geyser.command.defaults; import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; import org.geysermc.geyser.Constants; -import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.command.GeyserCommand; import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.network.GameProtocol; @@ -37,7 +37,6 @@ import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.util.WebUtils; -import java.io.IOException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.List; @@ -77,7 +76,7 @@ public class VersionCommand extends GeyserCommand { sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.version.checking", sender.locale())); try { String buildXML = WebUtils.getBody("https://ci.opencollab.dev/job/GeyserMC/job/Geyser/job/" + - URLEncoder.encode(GeyserImpl.BRANCH, StandardCharsets.UTF_8.toString()) + "/lastSuccessfulBuild/api/xml?xpath=//buildNumber"); + URLEncoder.encode(GeyserImpl.BRANCH, StandardCharsets.UTF_8) + "/lastSuccessfulBuild/api/xml?xpath=//buildNumber"); if (buildXML.startsWith("")) { int latestBuildNum = Integer.parseInt(buildXML.replaceAll("<(\\\\)?(/)?buildNumber>", "").trim()); int buildNum = this.geyser.buildNumber(); @@ -90,7 +89,7 @@ public class VersionCommand extends GeyserCommand { } else { throw new AssertionError("buildNumber missing"); } - } catch (IOException e) { + } catch (Exception e) { GeyserImpl.getInstance().getLogger().error(GeyserLocale.getLocaleStringLog("geyser.commands.version.failed"), e); sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.commands.version.failed", sender.locale())); } diff --git a/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java b/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java index 51cd7d4ae..f9bb15b32 100644 --- a/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java +++ b/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java @@ -52,6 +52,7 @@ public interface GeyserConfiguration { List getSavedUserLogins(); + @SuppressWarnings("BooleanMethodIsAlwaysInverted") boolean isCommandSuggestions(); @JsonIgnore @@ -93,6 +94,7 @@ public interface GeyserConfiguration { boolean isForceResourcePacks(); + @SuppressWarnings("BooleanMethodIsAlwaysInverted") boolean isXboxAchievementsEnabled(); int getCacheImages(); diff --git a/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java b/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java index 95ac7b1de..0874daa07 100644 --- a/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java +++ b/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java @@ -34,6 +34,7 @@ import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import lombok.Getter; import lombok.Setter; +import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.network.CIDRMatcher; @@ -158,7 +159,7 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration private String address = "0.0.0.0"; @Override - public String address() { + public @NonNull String address() { return address; } @@ -260,7 +261,7 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration private AuthType authType = AuthType.ONLINE; @Override - public AuthType authType() { + public @NonNull AuthType authType() { return authType; } 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 290a0e3ad..818607314 100644 --- a/core/src/main/java/org/geysermc/geyser/dump/DumpInfo.java +++ b/core/src/main/java/org/geysermc/geyser/dump/DumpInfo.java @@ -33,7 +33,6 @@ import com.google.common.io.ByteSource; import com.google.common.io.Files; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -import lombok.AllArgsConstructor; import lombok.Getter; import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; import org.geysermc.floodgate.util.DeviceOs; @@ -106,8 +105,8 @@ public class DumpInfo { // https://stackoverflow.com/questions/304268/getting-a-files-md5-checksum-in-java File file = new File(DumpInfo.class.getProtectionDomain().getCodeSource().getLocation().toURI()); ByteSource byteSource = Files.asByteSource(file); - // Jenkins uses MD5 for its hash - //noinspection UnstableApiUsage + // Jenkins uses MD5 for its hash - TODO remove + //noinspection UnstableApiUsage,deprecation md5Hash = byteSource.hash(Hashing.md5()).toString(); //noinspection UnstableApiUsage sha256Hash = byteSource.hash(Hashing.sha256()).toString(); @@ -118,7 +117,7 @@ public class DumpInfo { } this.hashInfo = new HashInfo(md5Hash, sha256Hash); - this.ramInfo = new DumpInfo.RamInfo(); + this.ramInfo = new RamInfo(); if (addLog) { this.logsInfo = new LogsInfo(); @@ -202,7 +201,7 @@ public class DumpInfo { private boolean checkDockerBasic() { try { String OS = System.getProperty("os.name").toLowerCase(); - if (OS.indexOf("nix") >= 0 || OS.indexOf("nux") >= 0 || OS.indexOf("aix") > 0) { + if (OS.contains("nix") || OS.contains("nux") || OS.indexOf("aix") > 0) { String output = new String(java.nio.file.Files.readAllBytes(Paths.get("/proc/1/cgroup"))); if (output.contains("docker")) { @@ -259,60 +258,30 @@ public class DumpInfo { } } - @AllArgsConstructor - @Getter - public static class HashInfo { - private final String md5Hash; - private final String sha256Hash; + public record HashInfo(String md5Hash, String sha256Hash) { } - @Getter - public static class RamInfo { - private final long free; - private final long total; - private final long max; - - RamInfo() { - this.free = Runtime.getRuntime().freeMemory() / MEGABYTE; - this.total = Runtime.getRuntime().totalMemory() / MEGABYTE; - this.max = Runtime.getRuntime().maxMemory() / MEGABYTE; + public record RamInfo(long free, long total, long max) { + public RamInfo() { + this(Runtime.getRuntime().freeMemory() / MEGABYTE, + Runtime.getRuntime().totalMemory() / MEGABYTE, + Runtime.getRuntime().maxMemory() / MEGABYTE); } } /** * E.G. `-Xmx1024M` - all runtime JVM flags on this machine */ - @Getter - public static class FlagsInfo { - private final List flags; - - FlagsInfo() { - this.flags = ManagementFactory.getRuntimeMXBean().getInputArguments(); + public record FlagsInfo(List flags) { + public FlagsInfo() { + this(ManagementFactory.getRuntimeMXBean().getInputArguments()); } } - @Getter - @AllArgsConstructor - public static class ExtensionInfo { - public boolean enabled; - public String name; - public String version; - public String apiVersion; - public String main; - public List authors; + public record ExtensionInfo(boolean enabled, String name, String version, String apiVersion, String main, List authors) { } - @Getter - @AllArgsConstructor - public static class GitInfo { - private final String buildNumber; - @JsonProperty("git.commit.id.abbrev") - private final String commitHashAbbrev; - @JsonProperty("git.commit.id") - private final String commitHash; - @JsonProperty("git.branch") - private final String branchName; - @JsonProperty("git.remote.origin.url") - private final String originUrl; + public record GitInfo(String buildNumber, @JsonProperty("git.commit.id.abbrev") String commitHashAbbrev, @JsonProperty("git.commit.id") String commitHash, + @JsonProperty("git.branch") String branchName, @JsonProperty("git.remote.origin.url") String originUrl) { } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinition.java b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinition.java index 566b3daff..8b430d559 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinition.java +++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinition.java @@ -59,6 +59,7 @@ public record EntityDefinition(EntityFactory factory, Entit return new Builder<>(factory); } + @SuppressWarnings("unchecked") public void translateMetadata(T entity, EntityMetadata> metadata) { EntityMetadataTranslator>> translator = (EntityMetadataTranslator>>) this.translators.get(metadata.getId()); if (translator == null) { diff --git a/core/src/main/java/org/geysermc/geyser/entity/attribute/GeyserAttributeType.java b/core/src/main/java/org/geysermc/geyser/entity/attribute/GeyserAttributeType.java index 92bfb7585..234c1afe9 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/attribute/GeyserAttributeType.java +++ b/core/src/main/java/org/geysermc/geyser/entity/attribute/GeyserAttributeType.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.entity.attribute; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.data.AttributeData; import lombok.AllArgsConstructor; import lombok.Getter; @@ -69,7 +70,7 @@ public enum GeyserAttributeType { return getAttribute(value, maximum); } - public AttributeData getAttribute(float value, float maximum) { + public @Nullable AttributeData getAttribute(float value, float maximum) { if (bedrockIdentifier == null) { return null; } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/AreaEffectCloudEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/AreaEffectCloudEntity.java index fcd4f2160..84dfae468 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/AreaEffectCloudEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/AreaEffectCloudEntity.java @@ -34,7 +34,6 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.registry.Registries; -import org.geysermc.geyser.registry.type.ParticleMapping; import org.geysermc.geyser.session.GeyserSession; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java b/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java index 5ca739f61..a2b7cc6ec 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java @@ -36,6 +36,7 @@ import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; import net.kyori.adventure.text.Component; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector2f; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; @@ -580,7 +581,7 @@ public class Entity implements GeyserEntity { } @SuppressWarnings("unchecked") - public I as(Class entityClass) { + public @Nullable I as(Class entityClass) { return entityClass.isInstance(this) ? (I) this : null; } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java index be38098ac..245b99cef 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java @@ -38,6 +38,7 @@ import com.github.steveice10.opennbt.tag.builtin.StringTag; import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.AttributeData; @@ -120,7 +121,7 @@ public class LivingEntity extends Entity { session.sendUpstreamPacket(attributesPacket); } - public Vector3i setBedPosition(EntityMetadata, ?> entityMetadata) { + public @Nullable Vector3i setBedPosition(EntityMetadata, ?> entityMetadata) { Optional optionalPos = entityMetadata.getValue(); if (optionalPos.isPresent()) { Vector3i bedPosition = optionalPos.get(); diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/ThrowableEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ThrowableEntity.java index 72ae88310..60840e65b 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/ThrowableEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/ThrowableEntity.java @@ -51,7 +51,6 @@ public class ThrowableEntity extends Entity implements Tickable { /** * Updates the position for the Bedrock client. - * * Java clients assume the next positions of moving items. Bedrock needs to be explicitly told positions */ @Override diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/AbstractFishEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/AbstractFishEntity.java index ec0caac33..9cc3a006e 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/AbstractFishEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/AbstractFishEntity.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.entity.type.living; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; @@ -34,7 +35,6 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.EntityUtils; import org.geysermc.geyser.util.InteractionResult; -import javax.annotation.Nonnull; import java.util.UUID; public class AbstractFishEntity extends WaterEntity { @@ -48,9 +48,9 @@ public class AbstractFishEntity extends WaterEntity { setFlag(EntityFlag.HAS_GRAVITY, false); } - @Nonnull + @NonNull @Override - protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (EntityUtils.attemptToBucket(itemInHand)) { return InteractionResult.SUCCESS; } else { diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/AllayEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/AllayEntity.java index f39200eed..48d633e5d 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/AllayEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/AllayEntity.java @@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type.living; import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; @@ -36,7 +37,6 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; -import javax.annotation.Nonnull; import java.util.UUID; public class AllayEntity extends MobEntity { @@ -54,9 +54,9 @@ public class AllayEntity extends MobEntity { this.canDuplicate = entityMetadata.getPrimitiveValue(); } - @Nonnull + @NonNull @Override - protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (this.canDuplicate && getFlag(EntityFlag.DANCING) && isDuplicationItem(itemInHand)) { // Maybe better as another tag? return InteractiveTag.GIVE_ITEM_TO_ALLAY; @@ -70,9 +70,9 @@ public class AllayEntity extends MobEntity { } } - @Nonnull + @NonNull @Override - protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (this.canDuplicate && getFlag(EntityFlag.DANCING) && isDuplicationItem(itemInHand)) { //TOCHECK sound return InteractionResult.SUCCESS; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java index c9018fe76..c64776f18 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java @@ -70,7 +70,7 @@ public class ArmorStandEntity extends LivingEntity { private boolean primaryEntity = true; /** * Whether the entity's position must be updated to included the offset. - * + *

* This should be true when the Java server marks the armor stand as invisible, but we shrink the entity * to allow the nametag to appear. Basically: * - Is visible: this is irrelevant (false) @@ -207,7 +207,7 @@ public class ArmorStandEntity extends LivingEntity { * @param negativeZToggle the flag to set true if the Z value of rotation is negative * @param rotation the Java rotation value */ - private void onRotationUpdate(EntityDataType dataLeech, EntityFlag negativeXToggle, EntityFlag negativeYToggle, EntityFlag negativeZToggle, Vector3f rotation) { + private void onRotationUpdate(EntityDataType dataLeech, EntityFlag negativeXToggle, EntityFlag negativeYToggle, EntityFlag negativeZToggle, Vector3f rotation) { // Indicate that rotation should be checked setFlag(EntityFlag.BRIBED, true); diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/DolphinEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/DolphinEntity.java index 7c1d8efc7..f0348bcaf 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/DolphinEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/DolphinEntity.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.entity.type.living; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.inventory.GeyserItemStack; @@ -33,7 +34,6 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; -import javax.annotation.Nonnull; import java.util.UUID; public class DolphinEntity extends WaterEntity { @@ -46,18 +46,18 @@ public class DolphinEntity extends WaterEntity { return true; } - @Nonnull + @NonNull @Override - protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (!itemInHand.isEmpty() && session.getTagCache().isFish(itemInHand)) { return InteractiveTag.FEED; } return super.testMobInteraction(hand, itemInHand); } - @Nonnull + @NonNull @Override - protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (!itemInHand.isEmpty() && session.getTagCache().isFish(itemInHand)) { // Feed return InteractionResult.SUCCESS; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/IronGolemEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/IronGolemEntity.java index 1f653decd..7afa4b436 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/IronGolemEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/IronGolemEntity.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.entity.type.living; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; @@ -35,7 +36,6 @@ import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; -import javax.annotation.Nonnull; import java.util.UUID; public class IronGolemEntity extends GolemEntity { @@ -51,9 +51,9 @@ public class IronGolemEntity extends GolemEntity { maxHealth = 100f; } - @Nonnull + @NonNull @Override - protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (itemInHand.asItem() == Items.IRON_INGOT) { if (health < maxHealth) { // Healing the iron golem diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/MobEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/MobEntity.java index 60a9a1474..0ac81c957 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/MobEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/MobEntity.java @@ -28,6 +28,7 @@ package org.geysermc.geyser.entity.type.living; import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import lombok.Getter; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; @@ -40,7 +41,6 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; -import javax.annotation.Nonnull; import java.util.UUID; public class MobEntity extends LivingEntity { @@ -133,13 +133,13 @@ public class MobEntity extends LivingEntity { return InteractionResult.PASS; } - @Nonnull - protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + @NonNull + protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { return InteractiveTag.NONE; } - @Nonnull - protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + @NonNull + protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { return InteractionResult.PASS; } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/SnowGolemEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/SnowGolemEntity.java index ced274185..7f0699415 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/SnowGolemEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/SnowGolemEntity.java @@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type.living; import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; @@ -36,7 +37,6 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; -import javax.annotation.Nonnull; import java.util.UUID; public class SnowGolemEntity extends GolemEntity { @@ -51,9 +51,9 @@ public class SnowGolemEntity extends GolemEntity { setFlag(EntityFlag.SHEARED, (xd & 0x10) != 0x10); } - @Nonnull + @NonNull @Override - protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (Items.SHEARS == itemInHand.asItem() && isAlive() && !getFlag(EntityFlag.SHEARED)) { // Shearing the snow golem return InteractiveTag.SHEAR; @@ -61,9 +61,9 @@ public class SnowGolemEntity extends GolemEntity { return InteractiveTag.NONE; } - @Nonnull + @NonNull @Override - protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (Items.SHEARS == itemInHand.asItem() && isAlive() && !getFlag(EntityFlag.SHEARED)) { // Shearing the snow golem return InteractionResult.SUCCESS; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/TadpoleEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/TadpoleEntity.java index 47ddb9126..7094c431e 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/TadpoleEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/TadpoleEntity.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.entity.type.living; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.inventory.GeyserItemStack; @@ -34,7 +35,6 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; -import javax.annotation.Nonnull; import java.util.UUID; public class TadpoleEntity extends AbstractFishEntity { @@ -42,18 +42,18 @@ public class TadpoleEntity extends AbstractFishEntity { super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); } - @Nonnull + @NonNull @Override - protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (isFood(itemInHand)) { return InteractiveTag.FEED; } return super.testMobInteraction(hand, itemInHand); } - @Nonnull + @NonNull @Override - protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (isFood(itemInHand)) { //TODO particles return InteractionResult.SUCCESS; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AnimalEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AnimalEntity.java index 2c46da13b..7278709ce 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AnimalEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AnimalEntity.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.entity.type.living.animal; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; @@ -38,7 +39,6 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; -import javax.annotation.Nonnull; import java.util.UUID; public class AnimalEntity extends AgeableEntity { @@ -59,18 +59,18 @@ public class AnimalEntity extends AgeableEntity { return item == Items.WHEAT; } - @Nonnull + @NonNull @Override - protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (canEat(itemInHand)) { return InteractiveTag.FEED; } return super.testMobInteraction(hand, itemInHand); } - @Nonnull + @NonNull @Override - protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (canEat(itemInHand)) { // FEED if (getFlag(EntityFlag.BABY)) { diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java index 06eb0791b..85b2afc14 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java @@ -28,6 +28,7 @@ package org.geysermc.geyser.entity.type.living.animal; import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; @@ -38,7 +39,6 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.EntityUtils; import org.geysermc.geyser.util.InteractionResult; -import javax.annotation.Nonnull; import java.util.UUID; public class AxolotlEntity extends AnimalEntity { @@ -74,9 +74,9 @@ public class AxolotlEntity extends AnimalEntity { return true; } - @Nonnull + @NonNull @Override - protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (EntityUtils.attemptToBucket(itemInHand)) { return InteractionResult.SUCCESS; } else { diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/CowEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/CowEntity.java index 01641c8c3..cdcf534a3 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/CowEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/CowEntity.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.entity.type.living.animal; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; @@ -36,7 +37,6 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; -import javax.annotation.Nonnull; import java.util.UUID; public class CowEntity extends AnimalEntity { @@ -44,9 +44,9 @@ public class CowEntity extends AnimalEntity { super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); } - @Nonnull + @NonNull @Override - protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (getFlag(EntityFlag.BABY) || itemInHand.asItem() != Items.BUCKET) { return super.testMobInteraction(hand, itemInHand); } @@ -54,9 +54,9 @@ public class CowEntity extends AnimalEntity { return InteractiveTag.MILK; } - @Nonnull + @NonNull @Override - protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (getFlag(EntityFlag.BABY) || itemInHand.asItem() != Items.BUCKET) { return super.mobInteract(hand, itemInHand); } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/GoatEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/GoatEntity.java index 20b8f5ccf..9ed94f96f 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/GoatEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/GoatEntity.java @@ -28,6 +28,7 @@ package org.geysermc.geyser.entity.type.living.animal; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose; import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; @@ -38,7 +39,6 @@ import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; -import javax.annotation.Nonnull; import java.util.UUID; public class GoatEntity extends AnimalEntity { @@ -70,9 +70,9 @@ public class GoatEntity extends AnimalEntity { // TODO testMobInteraction? - @Nonnull + @NonNull @Override - protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (!getFlag(EntityFlag.BABY) && itemInHand.asItem() == Items.BUCKET) { session.playSoundEvent(isScreamer ? SoundEvent.MILK_SCREAMER : SoundEvent.MILK, position); return InteractionResult.SUCCESS; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/MooshroomEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/MooshroomEntity.java index 2d136a169..1c347bf31 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/MooshroomEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/MooshroomEntity.java @@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type.living.animal; import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ObjectEntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.geysermc.geyser.entity.EntityDefinition; @@ -37,7 +38,6 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; -import javax.annotation.Nonnull; import java.util.UUID; public class MooshroomEntity extends AnimalEntity { @@ -52,9 +52,9 @@ public class MooshroomEntity extends AnimalEntity { dirtyMetadata.put(EntityDataTypes.VARIANT, isBrown ? 1 : 0); } - @Nonnull + @NonNull @Override - protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (!isBaby()) { if (itemInHand.asItem() == Items.BOWL) { // Stew @@ -67,9 +67,9 @@ public class MooshroomEntity extends AnimalEntity { return super.testMobInteraction(hand, itemInHand); } - @Nonnull + @NonNull @Override - protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { boolean isBaby = isBaby(); if (!isBaby && itemInHand.asItem() == Items.BOWL) { // Stew diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/OcelotEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/OcelotEntity.java index c81ddd52e..c115ebcdc 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/OcelotEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/OcelotEntity.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.entity.type.living.animal; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; @@ -36,7 +37,6 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; -import javax.annotation.Nonnull; import java.util.UUID; public class OcelotEntity extends AnimalEntity { @@ -50,9 +50,9 @@ public class OcelotEntity extends AnimalEntity { return item == Items.COD || item == Items.SALMON; } - @Nonnull + @NonNull @Override - protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (!getFlag(EntityFlag.TRUSTING) && canEat(itemInHand) && session.getPlayerEntity().getPosition().distanceSquared(position) < 9f) { // Attempt to feed return InteractiveTag.FEED; @@ -61,9 +61,9 @@ public class OcelotEntity extends AnimalEntity { } } - @Nonnull + @NonNull @Override - protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (!getFlag(EntityFlag.TRUSTING) && canEat(itemInHand) && session.getPlayerEntity().getPosition().distanceSquared(position) < 9f) { // Attempt to feed return InteractionResult.SUCCESS; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PandaEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PandaEntity.java index 212eaa91e..d2ef36932 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PandaEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PandaEntity.java @@ -28,6 +28,8 @@ package org.geysermc.geyser.entity.type.living.animal; import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType; @@ -41,8 +43,6 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.UUID; public class PandaEntity extends AnimalEntity { @@ -93,18 +93,18 @@ public class PandaEntity extends AnimalEntity { return item == Items.BAMBOO; } - @Nonnull + @NonNull @Override - protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (mainGene == Gene.WORRIED && session.isThunder()) { return InteractiveTag.NONE; } return super.testMobInteraction(hand, itemInHand); } - @Nonnull + @NonNull @Override - protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (mainGene == Gene.WORRIED && session.isThunder()) { // Huh! return InteractionResult.PASS; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PigEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PigEntity.java index 91e94321c..2bc02cd55 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PigEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PigEntity.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.entity.type.living.animal; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; @@ -37,7 +38,6 @@ import org.geysermc.geyser.util.EntityUtils; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; -import javax.annotation.Nonnull; import java.util.UUID; public class PigEntity extends AnimalEntity { @@ -51,9 +51,9 @@ public class PigEntity extends AnimalEntity { return item == Items.CARROT || item == Items.POTATO || item == Items.BEETROOT; } - @Nonnull + @NonNull @Override - protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (!canEat(itemInHand) && getFlag(EntityFlag.SADDLED) && passengers.isEmpty() && !session.isSneaking()) { // Mount return InteractiveTag.MOUNT; @@ -68,9 +68,9 @@ public class PigEntity extends AnimalEntity { } } - @Nonnull + @NonNull @Override - protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (!canEat(itemInHand) && getFlag(EntityFlag.SADDLED) && passengers.isEmpty() && !session.isSneaking()) { // Mount return InteractionResult.SUCCESS; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SheepEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SheepEntity.java index 8c9458012..13059244a 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SheepEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SheepEntity.java @@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type.living.animal; import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; @@ -38,7 +39,6 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; -import javax.annotation.Nonnull; import java.util.UUID; public class SheepEntity extends AnimalEntity { @@ -55,9 +55,9 @@ public class SheepEntity extends AnimalEntity { dirtyMetadata.put(EntityDataTypes.COLOR, (byte) color); } - @Nonnull + @NonNull @Override - protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (itemInHand.asItem() == Items.SHEARS) { return InteractiveTag.SHEAR; } else { @@ -73,9 +73,9 @@ public class SheepEntity extends AnimalEntity { } } - @Nonnull + @NonNull @Override - protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (itemInHand.asItem() == Items.SHEARS) { return InteractionResult.CONSUME; } else { diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/StriderEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/StriderEntity.java index e58fa5aca..39a55fa1e 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/StriderEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/StriderEntity.java @@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type.living.animal; import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; @@ -39,7 +40,6 @@ import org.geysermc.geyser.util.EntityUtils; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; -import javax.annotation.Nonnull; import java.util.UUID; public class StriderEntity extends AnimalEntity { @@ -98,9 +98,9 @@ public class StriderEntity extends AnimalEntity { return item == Items.WARPED_FUNGUS; } - @Nonnull + @NonNull @Override - protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (!canEat(itemInHand) && getFlag(EntityFlag.SADDLED) && passengers.isEmpty() && !session.isSneaking()) { // Mount Strider return InteractiveTag.RIDE_STRIDER; @@ -115,9 +115,9 @@ public class StriderEntity extends AnimalEntity { } } - @Nonnull + @NonNull @Override - protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (!canEat(itemInHand) && getFlag(EntityFlag.SADDLED) && passengers.isEmpty() && !session.isSneaking()) { // Mount Strider return InteractionResult.SUCCESS; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/AbstractHorseEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/AbstractHorseEntity.java index 872f72190..faa495487 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/AbstractHorseEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/AbstractHorseEntity.java @@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type.living.animal.horse; import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType; @@ -44,7 +45,6 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; -import javax.annotation.Nonnull; import java.util.Set; import java.util.UUID; @@ -128,14 +128,14 @@ public class AbstractHorseEntity extends AnimalEntity { return DONKEY_AND_HORSE_FOODS.contains(item); } - @Nonnull + @NonNull @Override - protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { return testHorseInteraction(hand, itemInHand); } - @Nonnull - protected final InteractiveTag testHorseInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + @NonNull + protected final InteractiveTag testHorseInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { boolean isBaby = isBaby(); if (!isBaby) { if (getFlag(EntityFlag.TAMED) && session.isSneaking()) { @@ -178,14 +178,14 @@ public class AbstractHorseEntity extends AnimalEntity { } } - @Nonnull + @NonNull @Override - protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { return mobHorseInteract(hand, itemInHand); } - @Nonnull - protected final InteractionResult mobHorseInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + @NonNull + protected final InteractionResult mobHorseInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { boolean isBaby = isBaby(); if (!isBaby) { if (getFlag(EntityFlag.TAMED) && session.isSneaking()) { @@ -236,21 +236,21 @@ public class AbstractHorseEntity extends AnimalEntity { } } - protected boolean testSaddle(@Nonnull GeyserItemStack itemInHand) { + protected boolean testSaddle(@NonNull GeyserItemStack itemInHand) { return isAlive() && !getFlag(EntityFlag.BABY) && getFlag(EntityFlag.TAMED); } - protected boolean testForChest(@Nonnull GeyserItemStack itemInHand) { + protected boolean testForChest(@NonNull GeyserItemStack itemInHand) { return false; } - protected boolean additionalTestForInventoryOpen(@Nonnull GeyserItemStack itemInHand) { + protected boolean additionalTestForInventoryOpen(@NonNull GeyserItemStack itemInHand) { return itemInHand.asItem().javaIdentifier().endsWith("_horse_armor"); } /* Just a place to stuff common code for the undead variants without having duplicate code */ - protected final InteractiveTag testUndeadHorseInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected final InteractiveTag testUndeadHorseInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (!getFlag(EntityFlag.TAMED)) { return InteractiveTag.NONE; } else if (isBaby()) { @@ -272,7 +272,7 @@ public class AbstractHorseEntity extends AnimalEntity { } } - protected final InteractionResult undeadHorseInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected final InteractionResult undeadHorseInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (!getFlag(EntityFlag.TAMED)) { return InteractionResult.PASS; } else if (isBaby()) { diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/CamelEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/CamelEntity.java index 4ce6f062b..8106b096d 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/CamelEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/CamelEntity.java @@ -111,6 +111,5 @@ public class CamelEntity extends AbstractHorseEntity { } public void setDashing(BooleanEntityMetadata entityMetadata) { - } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/ChestedHorseEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/ChestedHorseEntity.java index 0fb9438d2..fc8584de3 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/ChestedHorseEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/ChestedHorseEntity.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.entity.type.living.animal.horse; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; @@ -32,7 +33,6 @@ import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; -import javax.annotation.Nonnull; import java.util.UUID; public class ChestedHorseEntity extends AbstractHorseEntity { @@ -47,18 +47,18 @@ public class ChestedHorseEntity extends AbstractHorseEntity { } @Override - protected boolean testSaddle(@Nonnull GeyserItemStack itemInHand) { + protected boolean testSaddle(@NonNull GeyserItemStack itemInHand) { // Not checked here return false; } @Override - protected boolean testForChest(@Nonnull GeyserItemStack itemInHand) { + protected boolean testForChest(@NonNull GeyserItemStack itemInHand) { return itemInHand.asItem() == Items.CHEST && !getFlag(EntityFlag.CHESTED); } @Override - protected boolean additionalTestForInventoryOpen(@Nonnull GeyserItemStack itemInHand) { + protected boolean additionalTestForInventoryOpen(@NonNull GeyserItemStack itemInHand) { // Armor won't work on these return false; } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/SkeletonHorseEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/SkeletonHorseEntity.java index 43c76202c..7080f9f75 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/SkeletonHorseEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/SkeletonHorseEntity.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.entity.type.living.animal.horse; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.inventory.GeyserItemStack; @@ -33,7 +34,6 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; -import javax.annotation.Nonnull; import java.util.UUID; public class SkeletonHorseEntity extends AbstractHorseEntity { @@ -41,15 +41,15 @@ public class SkeletonHorseEntity extends AbstractHorseEntity { super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); } - @Nonnull + @NonNull @Override - protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { return testUndeadHorseInteraction(hand, itemInHand); } - @Nonnull + @NonNull @Override - protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { return undeadHorseInteract(hand, itemInHand); } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/ZombieHorseEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/ZombieHorseEntity.java index 423537496..3275712fc 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/ZombieHorseEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/ZombieHorseEntity.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.entity.type.living.animal.horse; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.inventory.GeyserItemStack; @@ -33,7 +34,6 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; -import javax.annotation.Nonnull; import java.util.UUID; public class ZombieHorseEntity extends AbstractHorseEntity { @@ -41,15 +41,15 @@ public class ZombieHorseEntity extends AbstractHorseEntity { super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); } - @Nonnull + @NonNull @Override - protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { return testUndeadHorseInteraction(hand, itemInHand); } - @Nonnull + @NonNull @Override - protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { return undeadHorseInteract(hand, itemInHand); } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/CatEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/CatEntity.java index 7903d85ca..412157b5d 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/CatEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/CatEntity.java @@ -29,6 +29,7 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanE import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; @@ -40,7 +41,6 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; -import javax.annotation.Nonnull; import java.util.UUID; public class CatEntity extends TameableEntity { @@ -112,9 +112,9 @@ public class CatEntity extends TameableEntity { return item == Items.COD || item == Items.SALMON; } - @Nonnull + @NonNull @Override - protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { boolean tamed = getFlag(EntityFlag.TAMED); if (tamed && ownerBedrockId == session.getPlayerEntity().getGeyserId()) { // Toggle sitting @@ -124,9 +124,9 @@ public class CatEntity extends TameableEntity { } } - @Nonnull + @NonNull @Override - protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { boolean tamed = getFlag(EntityFlag.TAMED); if (tamed && ownerBedrockId == session.getPlayerEntity().getGeyserId()) { return InteractionResult.SUCCESS; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/ParrotEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/ParrotEntity.java index 43f379de8..4c4b6a222 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/ParrotEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/ParrotEntity.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.entity.type.living.animal.tameable; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; @@ -36,7 +37,6 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; -import javax.annotation.Nonnull; import java.util.Set; import java.util.UUID; @@ -61,9 +61,9 @@ public class ParrotEntity extends TameableEntity { return item == Items.COOKIE; } - @Nonnull + @NonNull @Override - protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { boolean tame = getFlag(EntityFlag.TAMED); if (!tame && isTameFood(itemInHand.asItem())) { return InteractiveTag.FEED; @@ -76,9 +76,9 @@ public class ParrotEntity extends TameableEntity { return super.testMobInteraction(hand, itemInHand); } - @Nonnull + @NonNull @Override - protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { boolean tame = getFlag(EntityFlag.TAMED); if (!tame && isTameFood(itemInHand.asItem())) { return InteractionResult.SUCCESS; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java index ecf0736a3..0f5b36ec3 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java @@ -28,6 +28,7 @@ package org.geysermc.geyser.entity.type.living.animal.tameable; import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; @@ -40,7 +41,6 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; -import javax.annotation.Nonnull; import java.util.Set; import java.util.UUID; @@ -103,9 +103,9 @@ public class WolfEntity extends TameableEntity { return !getFlag(EntityFlag.ANGRY) && super.canBeLeashed(); } - @Nonnull + @NonNull @Override - protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (getFlag(EntityFlag.ANGRY)) { return InteractiveTag.NONE; } @@ -126,9 +126,9 @@ public class WolfEntity extends TameableEntity { return super.testMobInteraction(hand, itemInHand); } - @Nonnull + @NonNull @Override - protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (ownerBedrockId == session.getPlayerEntity().getGeyserId() || getFlag(EntityFlag.TAMED) || itemInHand.asItem() == Items.BONE && !getFlag(EntityFlag.ANGRY)) { // Sitting toggle or feeding; not angry diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/AbstractMerchantEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/AbstractMerchantEntity.java index b8465f9ca..c7b29130f 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/AbstractMerchantEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/AbstractMerchantEntity.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.entity.type.living.merchant; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; @@ -37,7 +38,6 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; -import javax.annotation.Nonnull; import java.util.UUID; public class AbstractMerchantEntity extends AgeableEntity { @@ -51,9 +51,9 @@ public class AbstractMerchantEntity extends AgeableEntity { return false; } - @Nonnull + @NonNull @Override - protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (itemInHand.asItem() != Items.VILLAGER_SPAWN_EGG && (definition != EntityDefinitions.VILLAGER || !getFlag(EntityFlag.SLEEPING) && ((VillagerEntity) this).isCanTradeWith())) { // An additional check we know cannot work @@ -64,9 +64,9 @@ public class AbstractMerchantEntity extends AgeableEntity { return super.testMobInteraction(hand, itemInHand); } - @Nonnull + @NonNull @Override - protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (itemInHand.asItem() != Items.VILLAGER_SPAWN_EGG && (definition != EntityDefinitions.VILLAGER || !getFlag(EntityFlag.SLEEPING)) && (definition != EntityDefinitions.WANDERING_TRADER || !getFlag(EntityFlag.BABY))) { diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/VillagerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/VillagerEntity.java index 84fa7d1bd..9b0f50050 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/VillagerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/VillagerEntity.java @@ -28,6 +28,7 @@ package org.geysermc.geyser.entity.type.living.merchant; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.metadata.VillagerData; import lombok.Getter; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; @@ -78,6 +79,7 @@ public class VillagerEntity extends AbstractMerchantEntity { VILLAGER_REGIONS[6] = 6; } + @Nullable private Vector3i bedPosition; /** * Used in the interactive tag manager @@ -103,7 +105,7 @@ public class VillagerEntity extends AbstractMerchantEntity { } @Override - public Vector3i setBedPosition(EntityMetadata, ?> entityMetadata) { + public @Nullable Vector3i setBedPosition(EntityMetadata, ?> entityMetadata) { return bedPosition = super.setBedPosition(entityMetadata); } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/CreeperEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/CreeperEntity.java index e50722681..33ea4e544 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/CreeperEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/CreeperEntity.java @@ -28,6 +28,7 @@ package org.geysermc.geyser.entity.type.living.monster; import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; @@ -37,7 +38,6 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; -import javax.annotation.Nonnull; import java.util.UUID; public class CreeperEntity extends MonsterEntity { @@ -62,9 +62,9 @@ public class CreeperEntity extends MonsterEntity { setFlag(EntityFlag.IGNITED, ignitedByFlintAndSteel); } - @Nonnull + @NonNull @Override - protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (session.getTagCache().isCreeperIgniter(itemInHand.asItem())) { return InteractiveTag.IGNITE_CREEPER; } else { @@ -72,9 +72,9 @@ public class CreeperEntity extends MonsterEntity { } } - @Nonnull + @NonNull @Override - protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (session.getTagCache().isCreeperIgniter(itemInHand.asItem())) { // Ignite creeper - as of 1.19.3 session.playSoundEvent(SoundEvent.IGNITE, position); diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java index 25fe7f802..450c546ec 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java @@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type.living.monster; import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; @@ -37,7 +38,6 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; -import javax.annotation.Nonnull; import java.util.UUID; public class PiglinEntity extends BasePiglinEntity { @@ -71,9 +71,9 @@ public class PiglinEntity extends BasePiglinEntity { super.updateOffHand(session); } - @Nonnull + @NonNull @Override - protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { InteractiveTag tag = super.testMobInteraction(hand, itemInHand); if (tag != InteractiveTag.NONE) { return tag; @@ -82,9 +82,9 @@ public class PiglinEntity extends BasePiglinEntity { } } - @Nonnull + @NonNull @Override - protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { InteractionResult superResult = super.mobInteract(hand, itemInHand); if (superResult.consumesAction()) { return superResult; @@ -93,7 +93,7 @@ public class PiglinEntity extends BasePiglinEntity { } } - private boolean canGiveGoldTo(@Nonnull GeyserItemStack itemInHand) { + private boolean canGiveGoldTo(@NonNull GeyserItemStack itemInHand) { return !getFlag(EntityFlag.BABY) && itemInHand.asItem() == Items.GOLD_INGOT && !getFlag(EntityFlag.ADMIRING); } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieVillagerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieVillagerEntity.java index fbac8663f..32e45507a 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieVillagerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieVillagerEntity.java @@ -29,6 +29,7 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadat import com.github.steveice10.mc.protocol.data.game.entity.metadata.VillagerData; import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; @@ -40,7 +41,6 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; -import javax.annotation.Nonnull; import java.util.UUID; public class ZombieVillagerEntity extends ZombieEntity { @@ -67,9 +67,9 @@ public class ZombieVillagerEntity extends ZombieEntity { return getFlag(EntityFlag.IS_TRANSFORMING) || super.isShaking(); } - @Nonnull + @NonNull @Override - protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (itemInHand.asItem() == Items.GOLDEN_APPLE) { return InteractiveTag.CURE; } else { @@ -77,9 +77,9 @@ public class ZombieVillagerEntity extends ZombieEntity { } } - @Nonnull + @NonNull @Override - protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) { + protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { if (itemInHand.asItem() == Items.GOLDEN_APPLE) { // The client doesn't know if the entity has weakness as that's not usually sent over the network return InteractionResult.CONSUME; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java index e80418744..7504db1b1 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java @@ -36,6 +36,7 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import lombok.Getter; import lombok.Setter; import net.kyori.adventure.text.Component; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.*; @@ -57,7 +58,6 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.util.ChunkUtils; -import javax.annotation.Nullable; import java.util.Collections; import java.util.List; import java.util.Optional; @@ -86,6 +86,7 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity { @Nullable private String texturesProperty; + @Nullable private Vector3i bedPosition; /** @@ -240,7 +241,7 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity { } @Override - public Vector3i setBedPosition(EntityMetadata, ?> entityMetadata) { + public @Nullable Vector3i setBedPosition(EntityMetadata, ?> entityMetadata) { bedPosition = super.setBedPosition(entityMetadata); if (bedPosition != null) { // Required to sync position of entity to bed diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java index 58b7ffddb..751a24871 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java @@ -33,6 +33,7 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEnti import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import lombok.Getter; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.AttributeData; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; @@ -44,7 +45,6 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.AttributeUtils; import org.geysermc.geyser.util.DimensionUtils; -import javax.annotation.Nullable; import java.util.Collections; import java.util.List; import java.util.Map; @@ -112,7 +112,7 @@ public class SessionPlayerEntity extends PlayerEntity { /** * Sending any updated flags (sprinting, onFire, etc.) to the client while in spectator is not needed - * Also "fixes" https://github.com/GeyserMC/Geyser/issues/3318 + * Also "fixes" issue 3318 */ @Override public void setFlags(ByteEntityMetadata entityMetadata) { @@ -126,7 +126,7 @@ public class SessionPlayerEntity extends PlayerEntity { /** * Since 1.19.40, the client must be re-informed of its bounding box on respawn - * See https://github.com/GeyserMC/Geyser/issues/3370 + * See issue 3370 */ public void updateBoundingBox() { dirtyMetadata.put(EntityDataTypes.HEIGHT, getBoundingBoxHeight()); diff --git a/core/src/main/java/org/geysermc/geyser/erosion/AbstractGeyserboundPacketHandler.java b/core/src/main/java/org/geysermc/geyser/erosion/AbstractGeyserboundPacketHandler.java index eabed8f7b..b8363efc9 100644 --- a/core/src/main/java/org/geysermc/geyser/erosion/AbstractGeyserboundPacketHandler.java +++ b/core/src/main/java/org/geysermc/geyser/erosion/AbstractGeyserboundPacketHandler.java @@ -25,9 +25,9 @@ package org.geysermc.geyser.erosion; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.erosion.packet.geyserbound.*; import org.geysermc.geyser.session.GeyserSession; -import org.jetbrains.annotations.Nullable; public abstract class AbstractGeyserboundPacketHandler implements GeyserboundPacketHandler { protected final GeyserSession session; diff --git a/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundHandshakePacketHandler.java b/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundHandshakePacketHandler.java index 196595383..0b4f03643 100644 --- a/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundHandshakePacketHandler.java +++ b/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundHandshakePacketHandler.java @@ -26,11 +26,11 @@ package org.geysermc.geyser.erosion; import io.netty.channel.Channel; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.erosion.netty.NettyPacketSender; import org.geysermc.erosion.packet.ErosionPacketHandler; import org.geysermc.erosion.packet.geyserbound.GeyserboundHandshakePacket; import org.geysermc.geyser.session.GeyserSession; -import org.jetbrains.annotations.Nullable; public final class GeyserboundHandshakePacketHandler extends AbstractGeyserboundPacketHandler { @@ -66,7 +66,7 @@ public final class GeyserboundHandshakePacketHandler extends AbstractGeyserbound } @Override - public ErosionPacketHandler setChannel(Channel channel) { + public @Nullable ErosionPacketHandler setChannel(Channel channel) { return null; } } diff --git a/core/src/main/java/org/geysermc/geyser/erosion/UnixSocketClientListener.java b/core/src/main/java/org/geysermc/geyser/erosion/UnixSocketClientListener.java index a236099df..1e00fe02c 100644 --- a/core/src/main/java/org/geysermc/geyser/erosion/UnixSocketClientListener.java +++ b/core/src/main/java/org/geysermc/geyser/erosion/UnixSocketClientListener.java @@ -31,6 +31,7 @@ import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; import io.netty.channel.epoll.EpollDomainSocketChannel; import io.netty.channel.epoll.EpollEventLoopGroup; +import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.erosion.netty.impl.AbstractUnixSocketListener; import org.geysermc.erosion.packet.geyserbound.GeyserboundPacketHandler; @@ -49,9 +50,9 @@ public final class UnixSocketClientListener extends AbstractUnixSocketListener { initializeEventLoopGroup(); (new Bootstrap() .channel(EpollDomainSocketChannel.class) - .handler(new ChannelInitializer() { + .handler(new ChannelInitializer<>() { @Override - protected void initChannel(Channel ch) { + protected void initChannel(@NonNull Channel ch) { initPipeline(ch, handler); } }) diff --git a/core/src/main/java/org/geysermc/geyser/event/GeyserEventBus.java b/core/src/main/java/org/geysermc/geyser/event/GeyserEventBus.java index 9593e327e..d8657b612 100644 --- a/core/src/main/java/org/geysermc/geyser/event/GeyserEventBus.java +++ b/core/src/main/java/org/geysermc/geyser/event/GeyserEventBus.java @@ -34,7 +34,6 @@ import org.geysermc.event.subscribe.Subscribe; import org.geysermc.geyser.api.event.EventBus; import org.geysermc.geyser.api.event.EventRegistrar; import org.geysermc.geyser.api.event.EventSubscriber; -import org.geysermc.geyser.api.extension.Extension; import java.util.Set; import java.util.function.BiConsumer; diff --git a/core/src/main/java/org/geysermc/geyser/event/GeyserEventSubscriber.java b/core/src/main/java/org/geysermc/geyser/event/GeyserEventSubscriber.java index d33de8cdd..ea2b73b5c 100644 --- a/core/src/main/java/org/geysermc/geyser/event/GeyserEventSubscriber.java +++ b/core/src/main/java/org/geysermc/geyser/event/GeyserEventSubscriber.java @@ -31,7 +31,6 @@ import org.geysermc.event.PostOrder; import org.geysermc.event.subscribe.impl.OwnedSubscriberImpl; import org.geysermc.geyser.api.event.EventRegistrar; import org.geysermc.geyser.api.event.ExtensionEventSubscriber; -import org.geysermc.geyser.api.extension.Extension; import java.util.function.BiConsumer; import java.util.function.Consumer; diff --git a/core/src/main/java/org/geysermc/geyser/event/type/GeyserBedrockPingEventImpl.java b/core/src/main/java/org/geysermc/geyser/event/type/GeyserBedrockPingEventImpl.java index 579b4c68c..df1f16650 100644 --- a/core/src/main/java/org/geysermc/geyser/event/type/GeyserBedrockPingEventImpl.java +++ b/core/src/main/java/org/geysermc/geyser/event/type/GeyserBedrockPingEventImpl.java @@ -26,12 +26,11 @@ package org.geysermc.geyser.event.type; import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.BedrockPong; import org.geysermc.geyser.api.event.connection.GeyserBedrockPingEvent; -import org.jetbrains.annotations.NotNull; -import javax.annotation.Nonnull; import java.net.InetSocketAddress; import java.util.Objects; @@ -45,12 +44,12 @@ public class GeyserBedrockPingEventImpl implements GeyserBedrockPingEvent { } @Override - public void primaryMotd(@Nonnull String primary) { + public void primaryMotd(@NonNull String primary) { pong.motd(Objects.requireNonNull(primary, "Primary MOTD cannot be null")); } @Override - public void secondaryMotd(@Nonnull String secondary) { + public void secondaryMotd(@NonNull String secondary) { pong.subMotd(Objects.requireNonNull(secondary, "Secondary MOTD cannot be null")); } @@ -87,7 +86,7 @@ public class GeyserBedrockPingEventImpl implements GeyserBedrockPingEvent { } @Override - public @NotNull InetSocketAddress address() { + public @NonNull InetSocketAddress address() { return address; } } diff --git a/core/src/main/java/org/geysermc/geyser/event/type/GeyserDefineCustomItemsEventImpl.java b/core/src/main/java/org/geysermc/geyser/event/type/GeyserDefineCustomItemsEventImpl.java index 65fd7ea0d..b9a059f19 100644 --- a/core/src/main/java/org/geysermc/geyser/event/type/GeyserDefineCustomItemsEventImpl.java +++ b/core/src/main/java/org/geysermc/geyser/event/type/GeyserDefineCustomItemsEventImpl.java @@ -51,7 +51,7 @@ public abstract class GeyserDefineCustomItemsEventImpl implements GeyserDefineCu * @return a multimap of all the already registered custom items */ @Override - public Map> getExistingCustomItems() { + public @NonNull Map> getExistingCustomItems() { return Collections.unmodifiableMap(this.customItems.asMap()); } @@ -61,7 +61,7 @@ public abstract class GeyserDefineCustomItemsEventImpl implements GeyserDefineCu * @return the list of the already registered non-vanilla custom items */ @Override - public List getExistingNonVanillaCustomItems() { + public @NonNull List getExistingNonVanillaCustomItems() { return Collections.unmodifiableList(this.nonVanillaCustomItems); } diff --git a/core/src/main/java/org/geysermc/geyser/inventory/AnvilContainer.java b/core/src/main/java/org/geysermc/geyser/inventory/AnvilContainer.java index e99b901a4..9e0b83768 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/AnvilContainer.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/AnvilContainer.java @@ -29,12 +29,11 @@ import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundRenameItemPacket; import lombok.Getter; import lombok.Setter; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.util.ItemUtils; -import javax.annotation.Nullable; - /** * Used to determine if rename packets should be sent and stores * the expected level cost for AnvilInventoryUpdater diff --git a/core/src/main/java/org/geysermc/geyser/inventory/Container.java b/core/src/main/java/org/geysermc/geyser/inventory/Container.java index 569802a5a..79fa67da1 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/Container.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/Container.java @@ -27,12 +27,11 @@ package org.geysermc.geyser.inventory; import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; import lombok.Getter; +import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.inventory.InventoryTranslator; import org.jetbrains.annotations.Range; -import javax.annotation.Nonnull; - /** * Combination of {@link Inventory} and {@link PlayerInventory} */ @@ -67,7 +66,7 @@ public class Container extends Inventory { } @Override - public void setItem(int slot, @Nonnull GeyserItemStack newItem, GeyserSession session) { + public void setItem(int slot, @NonNull GeyserItemStack newItem, GeyserSession session) { if (slot < this.size) { super.setItem(slot, newItem, session); } else { diff --git a/core/src/main/java/org/geysermc/geyser/inventory/Generic3X3Container.java b/core/src/main/java/org/geysermc/geyser/inventory/Generic3X3Container.java index 8dbc9b722..6518dce7c 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/Generic3X3Container.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/Generic3X3Container.java @@ -33,7 +33,7 @@ import org.geysermc.geyser.translator.inventory.Generic3X3InventoryTranslator; public class Generic3X3Container extends Container { /** * Whether we need to set the container type as {@link org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType#DROPPER}. - * + *

* Used at {@link Generic3X3InventoryTranslator#openInventory(GeyserSession, Inventory)} */ @Getter diff --git a/core/src/main/java/org/geysermc/geyser/inventory/GeyserEnchantOption.java b/core/src/main/java/org/geysermc/geyser/inventory/GeyserEnchantOption.java index d34ee2cbb..23365e392 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/GeyserEnchantOption.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/GeyserEnchantOption.java @@ -40,7 +40,7 @@ import java.util.List; public class GeyserEnchantOption { private static final List EMPTY = Collections.emptyList(); /** - * This: https://cdn.discordapp.com/attachments/613168850925649981/791030657169227816/unknown.png + * This text * is controlled by the server. * So, of course, we have to throw in some easter eggs. ;) */ diff --git a/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java b/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java index b159193e3..a67516c5c 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java @@ -28,18 +28,18 @@ package org.geysermc.geyser.inventory; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import lombok.AccessLevel; +import lombok.Data; import lombok.EqualsAndHashCode; import lombok.Getter; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; -import lombok.Data; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.inventory.item.ItemTranslator; -import javax.annotation.Nonnull; - @Data public class GeyserItemStack { public static final GeyserItemStack EMPTY = new GeyserItemStack(0, 0, null); @@ -64,7 +64,7 @@ public class GeyserItemStack { this.netId = netId; } - public static @Nonnull GeyserItemStack from(ItemStack itemStack) { + public static @NonNull GeyserItemStack from(ItemStack itemStack) { return itemStack == null ? EMPTY : new GeyserItemStack(itemStack.getId(), itemStack.getAmount(), itemStack.getNbt()); } @@ -76,7 +76,7 @@ public class GeyserItemStack { return isEmpty() ? 0 : amount; } - public CompoundTag getNbt() { + public @Nullable CompoundTag getNbt() { return isEmpty() ? null : nbt; } @@ -96,7 +96,7 @@ public class GeyserItemStack { return getItemStack(amount); } - public ItemStack getItemStack(int newAmount) { + public @Nullable ItemStack getItemStack(int newAmount) { return isEmpty() ? null : new ItemStack(javaId, newAmount, nbt); } diff --git a/core/src/main/java/org/geysermc/geyser/inventory/Inventory.java b/core/src/main/java/org/geysermc/geyser/inventory/Inventory.java index 91e8c4e94..3376d6c26 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/Inventory.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/Inventory.java @@ -29,6 +29,7 @@ import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; import com.github.steveice10.opennbt.tag.builtin.ByteTag; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.Tag; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3i; import lombok.Getter; import lombok.Setter; @@ -40,7 +41,6 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.inventory.item.ItemTranslator; import org.jetbrains.annotations.Range; -import javax.annotation.Nonnull; import java.util.Arrays; @ToString @@ -126,7 +126,7 @@ public abstract class Inventory { public abstract int getOffsetForHotbar(@Range(from = 0, to = 8) int slot); - public void setItem(int slot, @Nonnull GeyserItemStack newItem, GeyserSession session) { + public void setItem(int slot, @NonNull GeyserItemStack newItem, GeyserSession session) { if (slot > this.size) { session.getGeyser().getLogger().debug("Tried to set an item out of bounds! " + this); return; diff --git a/core/src/main/java/org/geysermc/geyser/inventory/PlayerInventory.java b/core/src/main/java/org/geysermc/geyser/inventory/PlayerInventory.java index 7b1064c8f..bda09a4ed 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/PlayerInventory.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/PlayerInventory.java @@ -28,12 +28,11 @@ package org.geysermc.geyser.inventory; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import lombok.Getter; import lombok.Setter; +import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.session.GeyserSession; import org.jetbrains.annotations.Range; -import javax.annotation.Nonnull; - public class PlayerInventory extends Inventory { /** * Stores the held item slot, starting at index 0. @@ -44,7 +43,7 @@ public class PlayerInventory extends Inventory { private int heldItemSlot; @Getter - @Nonnull + @NonNull private GeyserItemStack cursor = GeyserItemStack.EMPTY; public PlayerInventory() { @@ -57,12 +56,12 @@ public class PlayerInventory extends Inventory { return slot + 36; } - public void setCursor(@Nonnull GeyserItemStack newCursor, GeyserSession session) { + public void setCursor(@NonNull GeyserItemStack newCursor, GeyserSession session) { updateItemNetId(cursor, newCursor, session); cursor = newCursor; } - public GeyserItemStack getItemInHand(@Nonnull Hand hand) { + public GeyserItemStack getItemInHand(@NonNull Hand hand) { return hand == Hand.OFF_HAND ? getOffhand() : getItemInHand(); } @@ -74,7 +73,7 @@ public class PlayerInventory extends Inventory { return items[36 + heldItemSlot]; } - public void setItemInHand(@Nonnull GeyserItemStack item) { + public void setItemInHand(@NonNull GeyserItemStack item) { if (36 + heldItemSlot > this.size) { GeyserImpl.getInstance().getLogger().debug("Held item slot was larger than expected!"); return; diff --git a/core/src/main/java/org/geysermc/geyser/inventory/StonecutterContainer.java b/core/src/main/java/org/geysermc/geyser/inventory/StonecutterContainer.java index 6e04e6741..f99a0c71e 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/StonecutterContainer.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/StonecutterContainer.java @@ -27,8 +27,8 @@ package org.geysermc.geyser.inventory; import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; import lombok.Getter; -import lombok.NonNull; import lombok.Setter; +import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.session.GeyserSession; public class StonecutterContainer extends Container { diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/Enchantment.java b/core/src/main/java/org/geysermc/geyser/inventory/item/Enchantment.java index bcbfe3e17..5fa2a5784 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/item/Enchantment.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/item/Enchantment.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.inventory.item; import lombok.Getter; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Locale; @@ -78,7 +79,7 @@ public enum Enchantment { this.javaIdentifier = "minecraft:" + this.name().toLowerCase(Locale.ENGLISH); } - public static Enchantment getByJavaIdentifier(String javaIdentifier) { + public static @Nullable Enchantment getByJavaIdentifier(String javaIdentifier) { for (Enchantment enchantment : VALUES) { if (enchantment.javaIdentifier.equals(javaIdentifier) || enchantment.name().toLowerCase(Locale.ENGLISH).equalsIgnoreCase(javaIdentifier)) { return enchantment; @@ -87,7 +88,7 @@ public enum Enchantment { return null; } - public static Enchantment getByBedrockId(int bedrockId) { + public static @Nullable Enchantment getByBedrockId(int bedrockId) { if (bedrockId >= 0 && bedrockId < VALUES.length) { return VALUES[bedrockId]; } @@ -149,7 +150,7 @@ public enum Enchantment { */ public static final String[] ALL_JAVA_IDENTIFIERS; - public static JavaEnchantment getByJavaIdentifier(String javaIdentifier) { + public static @Nullable JavaEnchantment getByJavaIdentifier(String javaIdentifier) { if (!javaIdentifier.startsWith("minecraft:")) { javaIdentifier = "minecraft:" + javaIdentifier; } diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/Potion.java b/core/src/main/java/org/geysermc/geyser/inventory/item/Potion.java index 8d2b52aa2..7ce0ee278 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/item/Potion.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/item/Potion.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.inventory.item; import lombok.Getter; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Locale; @@ -84,7 +85,7 @@ public enum Potion { this.bedrockId = (short) bedrockId; } - public static Potion getByJavaIdentifier(String javaIdentifier) { + public static @Nullable Potion getByJavaIdentifier(String javaIdentifier) { for (Potion potion : VALUES) { if (potion.javaIdentifier.equals(javaIdentifier)) { return potion; @@ -93,7 +94,7 @@ public enum Potion { return null; } - public static Potion getByBedrockId(int bedrockId) { + public static @Nullable Potion getByBedrockId(int bedrockId) { for (Potion potion : VALUES) { if (potion.bedrockId == bedrockId) { return potion; diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java b/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java index 16fd7cde6..6bb786896 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java @@ -27,11 +27,11 @@ package org.geysermc.geyser.inventory.item; import lombok.Getter; import lombok.experimental.Accessors; +import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.registry.type.ItemMapping; -import javax.annotation.Nonnull; import java.util.Map; /** @@ -70,7 +70,7 @@ public class StoredItemMappings { this.writableBook = load(itemMappings, Items.WRITABLE_BOOK); } - @Nonnull + @NonNull private ItemMapping load(Map itemMappings, Item item) { ItemMapping mapping = itemMappings.get(item); if (mapping == null) { diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/TippedArrowPotion.java b/core/src/main/java/org/geysermc/geyser/inventory/item/TippedArrowPotion.java index e45667fe2..3ba0ad56f 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/item/TippedArrowPotion.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/item/TippedArrowPotion.java @@ -26,12 +26,13 @@ package org.geysermc.geyser.inventory.item; import lombok.Getter; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Locale; /** * Potion identifiers and their respective Bedrock IDs used with arrows. - * https://minecraft.wiki/w/Arrow#Data_values + * See here */ @Getter public enum TippedArrowPotion { @@ -93,7 +94,7 @@ public enum TippedArrowPotion { this.javaColor = arrowParticleColor.getColor(); } - public static TippedArrowPotion getByJavaIdentifier(String javaIdentifier) { + public static @Nullable TippedArrowPotion getByJavaIdentifier(String javaIdentifier) { for (TippedArrowPotion potion : VALUES) { if (potion.javaIdentifier.equals(javaIdentifier)) { return potion; @@ -102,7 +103,7 @@ public enum TippedArrowPotion { return null; } - public static TippedArrowPotion getByBedrockId(int bedrockId) { + public static @Nullable TippedArrowPotion getByBedrockId(int bedrockId) { for (TippedArrowPotion potion : VALUES) { if (potion.bedrockId == bedrockId) { return potion; @@ -115,7 +116,7 @@ public enum TippedArrowPotion { * @param color the potion color to look up * @return the tipped arrow potion that most closely resembles that color. */ - public static TippedArrowPotion getByJavaColor(int color) { + public static @Nullable TippedArrowPotion getByJavaColor(int color) { for (TippedArrowPotion potion : VALUES) { if (potion.javaColor == color) { return potion; diff --git a/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java b/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java index aa7897038..5adee0c20 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java @@ -64,7 +64,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater { super.updateInventory(translator, session, inventory); AnvilContainer anvilContainer = (AnvilContainer) inventory; updateInventoryState(session, anvilContainer); - int targetSlot = getTargetSlot(session, anvilContainer); + int targetSlot = getTargetSlot(anvilContainer); for (int i = 0; i < translator.size; i++) { final int bedrockSlot = translator.javaSlotToBedrock(i); if (bedrockSlot == 50) @@ -89,7 +89,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater { updateInventoryState(session, anvilContainer); int lastTargetSlot = anvilContainer.getLastTargetSlot(); - int targetSlot = getTargetSlot(session, anvilContainer); + int targetSlot = getTargetSlot(anvilContainer); if (targetSlot != javaSlot) { // Update the requested slot InventorySlotPacket slotPacket = new InventorySlotPacket(); @@ -136,7 +136,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater { * @param anvilContainer the anvil inventory * @return the slot to change the repair cost */ - private int getTargetSlot(GeyserSession session, AnvilContainer anvilContainer) { + private int getTargetSlot(AnvilContainer anvilContainer) { GeyserItemStack input = anvilContainer.getInput(); GeyserItemStack material = anvilContainer.getMaterial(); @@ -433,6 +433,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater { return !Objects.equals(originalName, ItemUtils.getCustomName(anvilContainer.getResult().getNbt())); } + @SuppressWarnings("SameParameterValue") private int getTagIntValueOr(GeyserItemStack itemStack, String tagName, int defaultValue) { if (itemStack.getNbt() != null) { Tag tag = itemStack.getNbt().get(tagName); diff --git a/core/src/main/java/org/geysermc/geyser/item/GeyserCustomItemOptions.java b/core/src/main/java/org/geysermc/geyser/item/GeyserCustomItemOptions.java index cebad261e..1434c49d9 100644 --- a/core/src/main/java/org/geysermc/geyser/item/GeyserCustomItemOptions.java +++ b/core/src/main/java/org/geysermc/geyser/item/GeyserCustomItemOptions.java @@ -30,15 +30,13 @@ import org.geysermc.geyser.api.util.TriState; import java.util.OptionalInt; +@SuppressWarnings("OptionalUsedAsFieldOrParameterType") public record GeyserCustomItemOptions(TriState unbreakable, OptionalInt customModelData, OptionalInt damagePredicate, boolean defaultItem) implements CustomItemOptions { - public GeyserCustomItemOptions(TriState unbreakable, OptionalInt customModelData, OptionalInt damagePredicate) { - this(unbreakable, customModelData, damagePredicate, false); - } - + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") public static class CustomItemOptionsBuilder implements CustomItemOptions.Builder { private TriState unbreakable = TriState.NOT_SET; private OptionalInt customModelData = OptionalInt.empty(); diff --git a/core/src/main/java/org/geysermc/geyser/item/GeyserCustomMappingData.java b/core/src/main/java/org/geysermc/geyser/item/GeyserCustomMappingData.java index 37bf9e02c..d71f2e548 100644 --- a/core/src/main/java/org/geysermc/geyser/item/GeyserCustomMappingData.java +++ b/core/src/main/java/org/geysermc/geyser/item/GeyserCustomMappingData.java @@ -27,7 +27,6 @@ package org.geysermc.geyser.item; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData; -import org.cloudburstmc.protocol.bedrock.packet.StartGamePacket; public record GeyserCustomMappingData(ComponentItemData componentItemData, ItemDefinition itemDefinition, String stringId, int integerId) { } diff --git a/core/src/main/java/org/geysermc/geyser/item/GeyserNonVanillaCustomItemData.java b/core/src/main/java/org/geysermc/geyser/item/GeyserNonVanillaCustomItemData.java index 47b5aed33..52b0ee7d0 100644 --- a/core/src/main/java/org/geysermc/geyser/item/GeyserNonVanillaCustomItemData.java +++ b/core/src/main/java/org/geysermc/geyser/item/GeyserNonVanillaCustomItemData.java @@ -32,11 +32,11 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.api.item.custom.CustomItemOptions; import org.geysermc.geyser.api.item.custom.CustomRenderOffsets; import org.geysermc.geyser.api.item.custom.NonVanillaCustomItemData; -import org.jetbrains.annotations.NotNull; import java.util.OptionalInt; import java.util.Set; +@SuppressWarnings("OptionalUsedAsFieldOrParameterType") @EqualsAndHashCode(callSuper = true) @ToString public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData implements NonVanillaCustomItemData { @@ -84,7 +84,7 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i } @Override - public @NotNull String identifier() { + public @NonNull String identifier() { return identifier; } @@ -134,7 +134,7 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i } @Override - public @NotNull OptionalInt creativeCategory() { + public @NonNull OptionalInt creativeCategory() { return creativeCategory; } diff --git a/core/src/main/java/org/geysermc/geyser/item/components/ToolTier.java b/core/src/main/java/org/geysermc/geyser/item/components/ToolTier.java index ee144acc6..8484eb185 100644 --- a/core/src/main/java/org/geysermc/geyser/item/components/ToolTier.java +++ b/core/src/main/java/org/geysermc/geyser/item/components/ToolTier.java @@ -26,7 +26,6 @@ package org.geysermc.geyser.item.components; import com.google.common.base.Suppliers; -import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.Item; @@ -66,14 +65,4 @@ public enum ToolTier { public String toString() { return this.name().toLowerCase(Locale.ROOT); } - - public static ToolTier getByName(@NonNull String name) { - String upperCase = name.toUpperCase(Locale.ROOT); - for (ToolTier tier : VALUES) { - if (tier.name().equals(upperCase)) { - return tier; - } - } - return null; - } } diff --git a/core/src/main/java/org/geysermc/geyser/item/exception/InvalidCustomMappingsFileException.java b/core/src/main/java/org/geysermc/geyser/item/exception/InvalidCustomMappingsFileException.java index 5878f5cc7..99ca463d7 100644 --- a/core/src/main/java/org/geysermc/geyser/item/exception/InvalidCustomMappingsFileException.java +++ b/core/src/main/java/org/geysermc/geyser/item/exception/InvalidCustomMappingsFileException.java @@ -25,16 +25,14 @@ package org.geysermc.geyser.item.exception; +import java.io.Serial; + public class InvalidCustomMappingsFileException extends Exception { - public InvalidCustomMappingsFileException(Throwable cause) { - super(cause); - } + + @Serial + private static final long serialVersionUID = 1L; public InvalidCustomMappingsFileException(String message) { super(message); } - - public InvalidCustomMappingsFileException(String message, Throwable cause) { - super(message, cause); - } } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java index 9a93eeac8..938d4a79a 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java @@ -27,6 +27,7 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import com.github.steveice10.opennbt.tag.builtin.StringTag; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.inventory.item.TippedArrowPotion; import org.geysermc.geyser.item.Items; @@ -38,7 +39,8 @@ public class ArrowItem extends Item { super(javaIdentifier, builder); } - public ItemStack translateToJava(ItemData itemData, ItemMapping mapping, ItemMappings mappings) { + @Override + public @NonNull ItemStack translateToJava(@NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) { TippedArrowPotion tippedArrowPotion = TippedArrowPotion.getByBedrockId(itemData.getDamage()); ItemStack itemStack = super.translateToJava(itemData, mapping, mappings); if (tippedArrowPotion != null) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/AxolotlBucketItem.java b/core/src/main/java/org/geysermc/geyser/item/type/AxolotlBucketItem.java index cd53cf904..81d7bf116 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/AxolotlBucketItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/AxolotlBucketItem.java @@ -28,9 +28,9 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.opennbt.tag.builtin.ByteTag; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; +import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.MinecraftLocale; -import org.jetbrains.annotations.NotNull; public class AxolotlBucketItem extends Item { public AxolotlBucketItem(String javaIdentifier, Builder builder) { @@ -38,7 +38,7 @@ public class AxolotlBucketItem extends Item { } @Override - public void translateNbtToBedrock(@NotNull GeyserSession session, @NotNull CompoundTag tag) { + public void translateNbtToBedrock(@NonNull GeyserSession session, @NonNull CompoundTag tag) { super.translateNbtToBedrock(session, tag); // Bedrock Edition displays the properties of the axolotl. Java does not. diff --git a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java index 920f9e168..344668836 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java @@ -29,14 +29,13 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.Tag; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtList; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtType; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; -import org.jetbrains.annotations.NotNull; -import javax.annotation.Nonnull; import java.util.ArrayList; import java.util.List; @@ -45,7 +44,7 @@ import static org.geysermc.erosion.util.BannerUtils.getJavaPatternTag; public class BannerItem extends BlockItem { /** * Holds what a Java ominous banner pattern looks like. - * + *

* Translating the patterns over to Bedrock does not work effectively, but Bedrock has a dedicated type for * ominous banners that we set instead. This variable is used to detect Java ominous banner patterns, and apply * the correct ominous banner pattern if Bedrock pulls the item from creative. @@ -86,7 +85,7 @@ public class BannerItem extends BlockItem { * @param pattern Java edition pattern nbt * @return The Bedrock edition format pattern nbt */ - @Nonnull + @NonNull private static NbtMap getBedrockBannerPattern(CompoundTag pattern) { return NbtMap.builder() .putInt("Color", 15 - (int) pattern.get("Color").getValue()) @@ -121,7 +120,7 @@ public class BannerItem extends BlockItem { } @Override - public void translateNbtToBedrock(@NotNull GeyserSession session, @NotNull CompoundTag tag) { + public void translateNbtToBedrock(@NonNull GeyserSession session, @NonNull CompoundTag tag) { super.translateNbtToBedrock(session, tag); CompoundTag blockEntityTag = tag.remove("BlockEntityTag"); @@ -137,7 +136,7 @@ public class BannerItem extends BlockItem { } @Override - public void translateNbtToJava(@NotNull CompoundTag tag, @NotNull ItemMapping mapping) { + public void translateNbtToJava(@NonNull CompoundTag tag, @NonNull ItemMapping mapping) { super.translateNbtToJava(tag, mapping); if (tag.get("Type") instanceof IntTag type && type.getValue() == 1) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java b/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java index d1ed6f6b8..87da96447 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java @@ -30,6 +30,7 @@ import com.github.steveice10.opennbt.tag.builtin.ByteTag; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.Tag; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; @@ -57,7 +58,7 @@ public class CompassItem extends Item { } @Override - public void translateNbtToBedrock(GeyserSession session, CompoundTag tag) { + public void translateNbtToBedrock(@NonNull GeyserSession session, @NonNull CompoundTag tag) { super.translateNbtToBedrock(session, tag); Tag lodestoneTag = tag.get("LodestoneTracked"); @@ -77,7 +78,7 @@ public class CompassItem extends Item { } @Override - public ItemStack translateToJava(ItemData itemData, ItemMapping mapping, ItemMappings mappings) { + public @NonNull ItemStack translateToJava(@NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) { if (mapping.getBedrockIdentifier().equals("minecraft:lodestone_compass")) { // Revert the entry back to the compass mapping = mappings.getStoredItems().compass(); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/CrossbowItem.java b/core/src/main/java/org/geysermc/geyser/item/type/CrossbowItem.java index 756cd69ba..e409dccfb 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/CrossbowItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/CrossbowItem.java @@ -28,11 +28,11 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import com.github.steveice10.opennbt.tag.builtin.*; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.inventory.item.ItemTranslator; -import org.jetbrains.annotations.Nullable; public class CrossbowItem extends Item { public CrossbowItem(String javaIdentifier, Builder builder) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java b/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java index f7743e430..ac0751c73 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java @@ -28,6 +28,7 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.Tag; +import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.session.GeyserSession; import java.util.ArrayList; @@ -39,7 +40,7 @@ public class EnchantedBookItem extends Item { } @Override - public void translateNbtToBedrock(GeyserSession session, CompoundTag tag) { + public void translateNbtToBedrock(@NonNull GeyserSession session, @NonNull CompoundTag tag) { super.translateNbtToBedrock(session, tag); List newTags = new ArrayList<>(); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/FishingRodItem.java b/core/src/main/java/org/geysermc/geyser/item/type/FishingRodItem.java index 96241deb3..f63a1ec5a 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/FishingRodItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/FishingRodItem.java @@ -28,6 +28,7 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.Tag; +import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.session.GeyserSession; public class FishingRodItem extends Item { @@ -36,7 +37,7 @@ public class FishingRodItem extends Item { } @Override - public void translateNbtToBedrock(GeyserSession session, CompoundTag tag) { + public void translateNbtToBedrock(@NonNull GeyserSession session, @NonNull CompoundTag tag) { super.translateNbtToBedrock(session, tag); // Fix damage inconsistency diff --git a/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java b/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java index 4c21be833..aacb906c9 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java @@ -27,6 +27,7 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import com.github.steveice10.opennbt.tag.builtin.StringTag; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.registry.type.ItemMapping; @@ -71,7 +72,7 @@ public class GoatHornItem extends Item { } @Override - public ItemStack translateToJava(ItemData itemData, ItemMapping mapping, ItemMappings mappings) { + public @NonNull ItemStack translateToJava(@NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) { ItemStack itemStack = super.translateToJava(itemData, mapping, mappings); int damage = itemData.getDamage(); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/Item.java b/core/src/main/java/org/geysermc/geyser/item/type/Item.java index eef02ff0e..a7a59f6af 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/Item.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/Item.java @@ -29,6 +29,7 @@ import com.github.steveice10.mc.protocol.data.game.Identifier; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import com.github.steveice10.opennbt.tag.builtin.*; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.inventory.item.Enchantment; @@ -99,8 +100,7 @@ public class Item { return builder; } - public ItemStack translateToJava(ItemData itemData, ItemMapping mapping, ItemMappings mappings) { - if (itemData == null) return null; + public @NonNull ItemStack translateToJava(@NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) { if (itemData.getTag() == null) { return new ItemStack(javaId, itemData.getCount(), new CompoundTag("")); } @@ -206,7 +206,7 @@ public class Item { } } - protected final CompoundTag remapEnchantment(GeyserSession session, CompoundTag tag, CompoundTag rootTag) { + protected final @Nullable CompoundTag remapEnchantment(GeyserSession session, CompoundTag tag, CompoundTag rootTag) { Tag javaEnchId = tag.get("id"); if (!(javaEnchId instanceof StringTag)) return null; diff --git a/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java b/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java index cd63a3799..4405b66ad 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.opennbt.tag.builtin.*; +import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; @@ -35,7 +36,7 @@ public class MapItem extends Item { } @Override - public void translateNbtToBedrock(GeyserSession session, CompoundTag tag) { + public void translateNbtToBedrock(@NonNull GeyserSession session, @NonNull CompoundTag tag) { super.translateNbtToBedrock(session, tag); Tag mapId = tag.remove("map"); @@ -49,7 +50,7 @@ public class MapItem extends Item { } @Override - public void translateNbtToJava(CompoundTag tag, ItemMapping mapping) { + public void translateNbtToJava(@NonNull CompoundTag tag, @NonNull ItemMapping mapping) { super.translateNbtToJava(tag, mapping); IntTag mapNameIndex = tag.remove("map_name_index"); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java b/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java index 359639437..24dd56ef2 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java @@ -28,6 +28,7 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.Tag; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.GeyserImpl; @@ -69,7 +70,7 @@ public class PotionItem extends Item { } @Override - public ItemStack translateToJava(ItemData itemData, ItemMapping mapping, ItemMappings mappings) { + public @NonNull ItemStack translateToJava(@NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) { Potion potion = Potion.getByBedrockId(itemData.getDamage()); ItemStack itemStack = super.translateToJava(itemData, mapping, mappings); if (potion != null) { diff --git a/core/src/main/java/org/geysermc/geyser/level/BedrockMapIcon.java b/core/src/main/java/org/geysermc/geyser/level/BedrockMapIcon.java index 9bb317996..eac8aca09 100644 --- a/core/src/main/java/org/geysermc/geyser/level/BedrockMapIcon.java +++ b/core/src/main/java/org/geysermc/geyser/level/BedrockMapIcon.java @@ -27,6 +27,7 @@ package org.geysermc.geyser.level; import com.github.steveice10.mc.protocol.data.game.level.map.MapIconType; import lombok.Getter; +import org.checkerframework.checker.nullness.qual.Nullable; public enum BedrockMapIcon { ICON_WHITE_ARROW(MapIconType.WHITE_ARROW, 0), @@ -87,7 +88,7 @@ public enum BedrockMapIcon { * @param iconType A MapIconType * @return The mapping for a BedrockMapIcon */ - public static BedrockMapIcon fromType(MapIconType iconType) { + public static @Nullable BedrockMapIcon fromType(MapIconType iconType) { for (BedrockMapIcon icon : VALUES) { if (icon.iconType.equals(iconType)) { return icon; diff --git a/core/src/main/java/org/geysermc/geyser/level/FireworkColor.java b/core/src/main/java/org/geysermc/geyser/level/FireworkColor.java index e005ab2d8..2ee8509a0 100644 --- a/core/src/main/java/org/geysermc/geyser/level/FireworkColor.java +++ b/core/src/main/java/org/geysermc/geyser/level/FireworkColor.java @@ -27,6 +27,7 @@ package org.geysermc.geyser.level; import net.kyori.adventure.text.format.TextColor; import net.kyori.adventure.util.HSVLike; +import org.checkerframework.checker.nullness.qual.NonNull; public enum FireworkColor { BLACK(1973019), @@ -75,7 +76,7 @@ public enum FireworkColor { * @return nearest named color. will always return a value * @since 4.0.0 */ - private static FireworkColor nearestTo(final HSVLike any) { + private static @NonNull FireworkColor nearestTo(final HSVLike any) { float matchedDistance = Float.MAX_VALUE; FireworkColor match = VALUES[0]; for (final FireworkColor potential : VALUES) { diff --git a/core/src/main/java/org/geysermc/geyser/level/GeyserAdvancement.java b/core/src/main/java/org/geysermc/geyser/level/GeyserAdvancement.java index 936248afe..e09cad19c 100644 --- a/core/src/main/java/org/geysermc/geyser/level/GeyserAdvancement.java +++ b/core/src/main/java/org/geysermc/geyser/level/GeyserAdvancement.java @@ -26,7 +26,7 @@ package org.geysermc.geyser.level; import com.github.steveice10.mc.protocol.data.game.advancement.Advancement; -import lombok.NonNull; +import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.session.cache.AdvancementsCache; import org.geysermc.geyser.text.ChatColor; @@ -73,7 +73,7 @@ public class GeyserAdvancement { return displayData != null && displayData.getFrameType() == Advancement.DisplayData.FrameType.CHALLENGE ? ChatColor.LIGHT_PURPLE : ChatColor.GREEN; } - public String getRootId(AdvancementsCache advancementsCache) { + public @NonNull String getRootId(AdvancementsCache advancementsCache) { if (rootId == null) { if (this.advancement.getParentId() == null) { // We are the root ID diff --git a/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java b/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java index a8e2d00ae..44c3b94b3 100644 --- a/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java +++ b/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java @@ -31,6 +31,8 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; @@ -39,9 +41,7 @@ import org.geysermc.erosion.util.BlockPositionIterator; import org.geysermc.erosion.util.LecternUtils; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.BlockEntityUtils; -import org.jetbrains.annotations.Nullable; -import javax.annotation.Nonnull; import java.util.List; import java.util.concurrent.CompletableFuture; @@ -99,6 +99,7 @@ public class GeyserWorldManager extends WorldManager { return; } List vectors = new ObjectArrayList<>(blockEntityInfos.size()); + //noinspection ForLoopReplaceableByForEach - avoid constructing iterator for (int i = 0; i < blockEntityInfos.size(); i++) { BlockEntityInfo info = blockEntityInfos.get(i); vectors.add(Vector3i.from(info.getX(), info.getY(), info.getZ())); @@ -171,7 +172,7 @@ public class GeyserWorldManager extends WorldManager { return false; } - @Nonnull + @NonNull @Override public CompletableFuture<@Nullable CompoundTag> getPickItemNbt(GeyserSession session, int x, int y, int z, boolean addNbtData) { var erosionHandler = session.getErosionHandler().getAsActive(); diff --git a/core/src/main/java/org/geysermc/geyser/level/WorldManager.java b/core/src/main/java/org/geysermc/geyser/level/WorldManager.java index a4de993d2..be7e2c139 100644 --- a/core/src/main/java/org/geysermc/geyser/level/WorldManager.java +++ b/core/src/main/java/org/geysermc/geyser/level/WorldManager.java @@ -29,12 +29,12 @@ import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityInfo; import com.github.steveice10.mc.protocol.data.game.setting.Difficulty; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3i; import org.geysermc.erosion.util.BlockPositionIterator; import org.geysermc.geyser.session.GeyserSession; -import org.jetbrains.annotations.Nullable; -import javax.annotation.Nonnull; import java.util.List; import java.util.Locale; import java.util.concurrent.CompletableFuture; @@ -107,7 +107,7 @@ public abstract class WorldManager { * * We solve this problem by querying all loaded lecterns, where possible, and sending their information in a block entity * tag. - * + *

* Note that the lectern data may be sent asynchronously. * * @param session the session of the player @@ -210,8 +210,7 @@ public abstract class WorldManager { /** * Returns a list of biome identifiers available on the server. */ - @Nullable - public String[] getBiomeIdentifiers(boolean withTags) { + public String @Nullable [] getBiomeIdentifiers(boolean withTags) { return null; } @@ -220,7 +219,7 @@ public abstract class WorldManager { * * @return expected NBT for this item. */ - @Nonnull + @NonNull public CompletableFuture<@Nullable CompoundTag> getPickItemNbt(GeyserSession session, int x, int y, int z, boolean addNbtData) { return CompletableFuture.completedFuture(null); } diff --git a/core/src/main/java/org/geysermc/geyser/level/block/DoubleChestValue.java b/core/src/main/java/org/geysermc/geyser/level/block/DoubleChestValue.java index 8024af650..97c861df7 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/DoubleChestValue.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/DoubleChestValue.java @@ -27,19 +27,14 @@ package org.geysermc.geyser.level.block; /** * This stores all values of double chests that are part of the Java block state. + * + * @param isFacingEast If true, then chest is facing east/west; if false, south/north + * @param isDirectionPositive If true, direction is positive (east/south); if false, direction is negative (west/north) + * @param isLeft If true, chest is the left of a pair; if false, chest is the right of a pair. */ public record DoubleChestValue( - /** - * If true, then chest is facing east/west; if false, south/north - */ boolean isFacingEast, - /** - * If true, direction is positive (east/south); if false, direction is negative (west/north) - */ boolean isDirectionPositive, - /** - * If true, chest is the left of a pair; if false, chest is the right of a pair. - */ boolean isLeft) { } diff --git a/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockData.java b/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockData.java index 413a4d1ed..dd58ebcb7 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockData.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockData.java @@ -28,6 +28,7 @@ package org.geysermc.geyser.level.block; import it.unimi.dsi.fastutil.objects.*; import lombok.RequiredArgsConstructor; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.Constants; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.block.custom.CustomBlockData; @@ -37,9 +38,6 @@ import org.geysermc.geyser.api.block.custom.component.CustomBlockComponents; import org.geysermc.geyser.api.block.custom.property.CustomBlockProperty; import org.geysermc.geyser.api.block.custom.property.PropertyType; import org.geysermc.geyser.api.util.CreativeCategory; -import org.jetbrains.annotations.NotNull; - -import javax.annotation.Nullable; import java.util.List; import java.util.Map; @@ -142,7 +140,7 @@ public class GeyserCustomBlockData implements CustomBlockData { } @Override - public CustomBlockState.@NotNull Builder blockStateBuilder() { + public CustomBlockState.@NonNull Builder blockStateBuilder() { return new GeyserCustomBlockState.CustomBlockStateBuilder(this); } diff --git a/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockState.java b/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockState.java index 576bd9743..d147ffedc 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockState.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockState.java @@ -54,7 +54,7 @@ public class GeyserCustomBlockState implements CustomBlockState { @SuppressWarnings("unchecked") @Override - public @NonNull T property(String propertyName) { + public @NonNull T property(@NonNull String propertyName) { return (T) properties.get(propertyName); } diff --git a/core/src/main/java/org/geysermc/geyser/level/block/GeyserJavaBlockState.java b/core/src/main/java/org/geysermc/geyser/level/block/GeyserJavaBlockState.java index 725afe6df..5604a543e 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/GeyserJavaBlockState.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/GeyserJavaBlockState.java @@ -52,7 +52,7 @@ public class GeyserJavaBlockState implements JavaBlockState { } @Override - public @NonNull boolean waterlogged() { + public boolean waterlogged() { return waterlogged; } @@ -62,7 +62,7 @@ public class GeyserJavaBlockState implements JavaBlockState { } @Override - public @NonNull boolean canBreakWithHand() { + public boolean canBreakWithHand() { return canBreakWithHand; } @@ -77,7 +77,7 @@ public class GeyserJavaBlockState implements JavaBlockState { } @Override - public @Nullable boolean hasBlockEntity() { + public boolean hasBlockEntity() { return hasBlockEntity; } @@ -118,7 +118,7 @@ public class GeyserJavaBlockState implements JavaBlockState { } @Override - public Builder waterlogged(@NonNull boolean waterlogged) { + public Builder waterlogged(boolean waterlogged) { this.waterlogged = waterlogged; return this; } @@ -130,7 +130,7 @@ public class GeyserJavaBlockState implements JavaBlockState { } @Override - public Builder canBreakWithHand(@NonNull boolean canBreakWithHand) { + public Builder canBreakWithHand(boolean canBreakWithHand) { this.canBreakWithHand = canBreakWithHand; return this; } @@ -148,7 +148,7 @@ public class GeyserJavaBlockState implements JavaBlockState { } @Override - public Builder hasBlockEntity(@Nullable boolean hasBlockEntity) { + public Builder hasBlockEntity(boolean hasBlockEntity) { this.hasBlockEntity = hasBlockEntity; return this; } diff --git a/core/src/main/java/org/geysermc/geyser/level/chunk/bitarray/BitArrayVersion.java b/core/src/main/java/org/geysermc/geyser/level/chunk/bitarray/BitArrayVersion.java index d95767b97..fbfd82144 100644 --- a/core/src/main/java/org/geysermc/geyser/level/chunk/bitarray/BitArrayVersion.java +++ b/core/src/main/java/org/geysermc/geyser/level/chunk/bitarray/BitArrayVersion.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.level.chunk.bitarray; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.util.MathUtils; public enum BitArrayVersion { @@ -61,7 +62,7 @@ public enum BitArrayVersion { throw new IllegalArgumentException("Invalid palette version: " + version); } - public static BitArrayVersion forBitsCeil(int bits) { + public static @Nullable BitArrayVersion forBitsCeil(int bits) { for (int i = VALUES.length - 1; i >= 0; i--) { BitArrayVersion version = VALUES[i]; if (version.bits >= bits) { @@ -79,10 +80,6 @@ public enum BitArrayVersion { return maxEntryValue; } - public int getWordsForSize(int size) { - return MathUtils.ceil((float) size / entriesPerWord); - } - public BitArrayVersion next() { return next; } diff --git a/core/src/main/java/org/geysermc/geyser/level/physics/CollisionManager.java b/core/src/main/java/org/geysermc/geyser/level/physics/CollisionManager.java index b983da8b4..2c3da3c41 100644 --- a/core/src/main/java/org/geysermc/geyser/level/physics/CollisionManager.java +++ b/core/src/main/java/org/geysermc/geyser/level/physics/CollisionManager.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.level.physics; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.GenericMath; import org.cloudburstmc.math.vector.Vector3d; import org.cloudburstmc.math.vector.Vector3f; @@ -133,7 +134,7 @@ public class CollisionManager { * @param teleported whether the Bedrock player has teleported to a new position. If true, movement correction is skipped. * @return the position to send to the Java server, or null to cancel sending the packet */ - public Vector3d adjustBedrockPosition(Vector3f bedrockPosition, boolean onGround, boolean teleported) { + public @Nullable Vector3d adjustBedrockPosition(Vector3f bedrockPosition, boolean onGround, boolean teleported) { PistonCache pistonCache = session.getPistonCache(); // Bedrock clients tend to fall off of honey blocks, so we need to teleport them to the new position if (pistonCache.isPlayerAttachedToHoney()) { diff --git a/core/src/main/java/org/geysermc/geyser/level/physics/Direction.java b/core/src/main/java/org/geysermc/geyser/level/physics/Direction.java index fa5201db9..09ff89800 100644 --- a/core/src/main/java/org/geysermc/geyser/level/physics/Direction.java +++ b/core/src/main/java/org/geysermc/geyser/level/physics/Direction.java @@ -25,10 +25,9 @@ package org.geysermc.geyser.level.physics; -import org.cloudburstmc.math.vector.Vector3i; import lombok.Getter; - -import javax.annotation.Nonnull; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.math.vector.Vector3i; public enum Direction { DOWN(1, Vector3i.from(0, -1, 0), Axis.Y, com.github.steveice10.mc.protocol.data.game.entity.object.Direction.DOWN), @@ -66,8 +65,7 @@ public enum Direction { return axis == Axis.X || axis == Axis.Z; } - @Nonnull - public static Direction fromPistonValue(com.github.steveice10.mc.protocol.data.game.entity.object.Direction pistonValue) { + public static @NonNull Direction fromPistonValue(com.github.steveice10.mc.protocol.data.game.entity.object.Direction pistonValue) { for (Direction direction : VALUES) { if (direction.pistonValue == pistonValue) { return direction; diff --git a/core/src/main/java/org/geysermc/geyser/level/physics/PistonBehavior.java b/core/src/main/java/org/geysermc/geyser/level/physics/PistonBehavior.java index a6b25d01e..fa28e7cb8 100644 --- a/core/src/main/java/org/geysermc/geyser/level/physics/PistonBehavior.java +++ b/core/src/main/java/org/geysermc/geyser/level/physics/PistonBehavior.java @@ -25,6 +25,8 @@ package org.geysermc.geyser.level.physics; +import org.checkerframework.checker.nullness.qual.NonNull; + import java.util.Locale; public enum PistonBehavior { @@ -35,7 +37,7 @@ public enum PistonBehavior { private static final PistonBehavior[] VALUES = values(); - public static PistonBehavior getByName(String name) { + public static @NonNull PistonBehavior getByName(String name) { String upperCase = name.toUpperCase(Locale.ROOT); for (PistonBehavior type : VALUES) { if (type.name().equals(upperCase)) { diff --git a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java index 4ffdbcf48..11c7bc11e 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java @@ -27,6 +27,7 @@ package org.geysermc.geyser.network; import com.github.steveice10.mc.protocol.codec.MinecraftCodec; import com.github.steveice10.mc.protocol.codec.PacketCodec; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; import org.cloudburstmc.protocol.bedrock.codec.v589.Bedrock_v589; import org.cloudburstmc.protocol.bedrock.codec.v594.Bedrock_v594; @@ -82,7 +83,7 @@ public final class GameProtocol { * @param protocolVersion The protocol version to attempt to find * @return The packet codec, or null if the client's protocol is unsupported */ - public static BedrockCodec getBedrockCodec(int protocolVersion) { + public static @Nullable BedrockCodec getBedrockCodec(int protocolVersion) { for (BedrockCodec packetCodec : SUPPORTED_BEDROCK_CODECS) { if (packetCodec.getProtocolVersion() == protocolVersion) { return packetCodec; diff --git a/core/src/main/java/org/geysermc/geyser/network/GeyserServerInitializer.java b/core/src/main/java/org/geysermc/geyser/network/GeyserServerInitializer.java index f19a46e6a..bb8e87440 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GeyserServerInitializer.java +++ b/core/src/main/java/org/geysermc/geyser/network/GeyserServerInitializer.java @@ -28,6 +28,7 @@ package org.geysermc.geyser.network; import io.netty.channel.Channel; import io.netty.channel.DefaultEventLoopGroup; import io.netty.util.concurrent.DefaultThreadFactory; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.protocol.bedrock.BedrockPeer; import org.cloudburstmc.protocol.bedrock.BedrockServerSession; import org.cloudburstmc.protocol.bedrock.netty.initializer.BedrockServerInitializer; @@ -35,7 +36,6 @@ import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.event.bedrock.SessionInitializeEvent; import org.geysermc.geyser.session.GeyserSession; -import javax.annotation.Nonnull; import java.net.InetSocketAddress; public class GeyserServerInitializer extends BedrockServerInitializer { @@ -52,7 +52,7 @@ public class GeyserServerInitializer extends BedrockServerInitializer { } @Override - public void initSession(@Nonnull BedrockServerSession bedrockServerSession) { + public void initSession(@NonNull BedrockServerSession bedrockServerSession) { try { if (this.geyser.getGeyserServer().getProxiedAddresses() != null) { InetSocketAddress address = this.geyser.getGeyserServer().getProxiedAddresses().get((InetSocketAddress) bedrockServerSession.getSocketAddress()); diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/ChannelWrapper.java b/core/src/main/java/org/geysermc/geyser/network/netty/ChannelWrapper.java index 26015a96f..a756c70eb 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/ChannelWrapper.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/ChannelWrapper.java @@ -29,6 +29,7 @@ import io.netty.buffer.ByteBufAllocator; import io.netty.channel.*; import io.netty.util.Attribute; import io.netty.util.AttributeKey; +import org.checkerframework.checker.nullness.qual.NonNull; import java.net.SocketAddress; @@ -259,7 +260,7 @@ public class ChannelWrapper implements Channel { } @Override - public int compareTo(Channel o) { + public int compareTo(@NonNull Channel o) { return source.compareTo(o); } } diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/LocalChannelWrapper.java b/core/src/main/java/org/geysermc/geyser/network/netty/LocalChannelWrapper.java index 258fa69eb..53221274f 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/LocalChannelWrapper.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/LocalChannelWrapper.java @@ -30,25 +30,20 @@ import io.netty.channel.local.LocalChannel; import io.netty.channel.local.LocalServerChannel; import java.net.InetSocketAddress; +import java.util.Objects; public class LocalChannelWrapper extends LocalChannel { + private final ChannelWrapper wrapper; + /** * {@link #newChannelPipeline()} is called during super, so this exists until the wrapper can be initialized. */ private volatile ChannelWrapper tempWrapper; - public LocalChannelWrapper() { - wrapper = new ChannelWrapper(this); - } - public LocalChannelWrapper(LocalServerChannel parent, LocalChannel peer) { super(parent, peer); - if (tempWrapper == null) { - this.wrapper = new ChannelWrapper(this); - } else { - this.wrapper = tempWrapper; - } + this.wrapper = Objects.requireNonNullElseGet(tempWrapper, () -> new ChannelWrapper(this)); wrapper.remoteAddress(new InetSocketAddress(0)); } diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java b/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java index 551bc1deb..a2951116f 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java @@ -37,6 +37,7 @@ import io.netty.buffer.ByteBufAllocator; import io.netty.channel.*; import io.netty.channel.unix.PreferredDirectByteBufAllocator; import io.netty.handler.codec.haproxy.*; +import org.checkerframework.checker.nullness.qual.NonNull; import java.net.Inet4Address; import java.net.InetSocketAddress; @@ -75,7 +76,7 @@ public final class LocalSession extends TcpSession { bootstrap.channel(LocalChannelWithRemoteAddress.class); bootstrap.handler(new ChannelInitializer() { @Override - public void initChannel(LocalChannelWithRemoteAddress channel) { + public void initChannel(@NonNull LocalChannelWithRemoteAddress channel) { channel.spoofedRemoteAddress(new InetSocketAddress(clientIp, 0)); PacketProtocol protocol = getPacketProtocol(); protocol.newClientSession(LocalSession.this); @@ -119,7 +120,7 @@ public final class LocalSession extends TcpSession { if (getFlag(BuiltinFlags.ENABLE_CLIENT_PROXY_PROTOCOL, false) && clientAddress != null) { pipeline.addFirst("proxy-protocol-packet-sender", new ChannelInboundHandlerAdapter() { @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { + public void channelActive(@NonNull ChannelHandlerContext ctx) throws Exception { HAProxyProxiedProtocol proxiedProtocol = clientAddress.getAddress() instanceof Inet4Address ? HAProxyProxiedProtocol.TCP4 : HAProxyProxiedProtocol.TCP6; InetSocketAddress remoteAddress; if (ctx.channel().remoteAddress() instanceof InetSocketAddress) { diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/handler/RakConnectionRequestHandler.java b/core/src/main/java/org/geysermc/geyser/network/netty/handler/RakConnectionRequestHandler.java index 8c0412240..26bda9f2b 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/handler/RakConnectionRequestHandler.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/handler/RakConnectionRequestHandler.java @@ -49,7 +49,7 @@ public class RakConnectionRequestHandler extends ChannelInboundHandlerAdapter { private final GeyserServer server; @Override - public void channelRead(@NonNull ChannelHandlerContext ctx, @NonNull Object msg) throws Exception { + public void channelRead(@NonNull ChannelHandlerContext ctx, @NonNull Object msg) { if (!(msg instanceof DatagramPacket packet)) { ctx.fireChannelRead(msg); return; diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/proxy/ProxyProtocolDecoder.java b/core/src/main/java/org/geysermc/geyser/network/netty/proxy/ProxyProtocolDecoder.java index b14006336..67fb3ecdd 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/proxy/ProxyProtocolDecoder.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/proxy/ProxyProtocolDecoder.java @@ -30,6 +30,7 @@ import io.netty.handler.codec.ProtocolDetectionResult; import io.netty.handler.codec.haproxy.*; import io.netty.util.ByteProcessor; import io.netty.util.CharsetUtil; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Objects; @@ -75,7 +76,7 @@ public final class ProxyProtocolDecoder { /** * Protocol specification version */ - private int decodingVersion = -1; + private final int decodingVersion; /** * The latest v2 spec (2014/05/18) allows for additional data to be sent in the proxy protocol header beyond the @@ -87,7 +88,7 @@ public final class ProxyProtocolDecoder { this.decodingVersion = version; } - public static HAProxyMessage decode(ByteBuf packet, int version) { + public static @Nullable HAProxyMessage decode(ByteBuf packet, int version) { if (version == -1) { return null; } @@ -95,7 +96,7 @@ public final class ProxyProtocolDecoder { return decoder.decodeHeader(packet); } - private HAProxyMessage decodeHeader(ByteBuf in) { + private @Nullable HAProxyMessage decodeHeader(ByteBuf in) { final ByteBuf decoded = decodingVersion == 1 ? decodeLine(in) : decodeStruct(in); if (decoded == null) { return null; @@ -233,8 +234,8 @@ public final class ProxyProtocolDecoder { dstPort = header.readUnsignedShort(); } + //noinspection StatementWithEmptyBody while (skipNextTLV(header)) { - } return new HAProxyMessage(ver, cmd, protAndFam, srcAddress, dstAddress, srcPort, dstPort); } @@ -479,7 +480,7 @@ public final class ProxyProtocolDecoder { * @return frame the {@link ByteBuf} which represent the frame or {@code null} if no frame could * be created */ - public ByteBuf extract(ByteBuf buffer) { + public @Nullable ByteBuf extract(ByteBuf buffer) { final int eoh = findEndOfHeader(buffer); if (!discarding) { if (eoh >= 0) { diff --git a/core/src/main/java/org/geysermc/geyser/pack/GeyserResourcePackManifest.java b/core/src/main/java/org/geysermc/geyser/pack/GeyserResourcePackManifest.java index ddcee6ad5..25a0f0ee0 100644 --- a/core/src/main/java/org/geysermc/geyser/pack/GeyserResourcePackManifest.java +++ b/core/src/main/java/org/geysermc/geyser/pack/GeyserResourcePackManifest.java @@ -30,8 +30,8 @@ import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.api.pack.ResourcePackManifest; -import org.jetbrains.annotations.NotNull; import java.io.IOException; import java.util.Collection; @@ -49,7 +49,7 @@ public record GeyserResourcePackManifest(@JsonProperty("format_version") int for public record Version(int major, int minor, int patch) implements ResourcePackManifest.Version { @Override - public @NotNull String toString() { + public @NonNull String toString() { return major + "." + minor + "." + patch; } diff --git a/core/src/main/java/org/geysermc/geyser/pack/SkullResourcePackManager.java b/core/src/main/java/org/geysermc/geyser/pack/SkullResourcePackManager.java index f59ae8026..e7a9f4f1e 100644 --- a/core/src/main/java/org/geysermc/geyser/pack/SkullResourcePackManager.java +++ b/core/src/main/java/org/geysermc/geyser/pack/SkullResourcePackManager.java @@ -27,6 +27,7 @@ package org.geysermc.geyser.pack; import it.unimi.dsi.fastutil.Pair; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.Constants; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.pack.ResourcePackManifest; @@ -63,7 +64,7 @@ public class SkullResourcePackManager { public static final Map SKULL_SKINS = new Object2ObjectOpenHashMap<>(); @SuppressWarnings("ResultOfMethodCallIgnored") - public static Path createResourcePack() { + public static @Nullable Path createResourcePack() { Path cachePath = GeyserImpl.getInstance().getBootstrap().getConfigFolder().resolve("cache"); try { Files.createDirectories(cachePath); @@ -165,7 +166,7 @@ public class SkullResourcePackManager { } private static void addBaseResources(ZipOutputStream zipOS) throws IOException { - try (BufferedReader reader = new BufferedReader(new InputStreamReader(GeyserImpl.getInstance().getBootstrap().getResource("bedrock/skull_resource_pack_files.txt")))) { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(GeyserImpl.getInstance().getBootstrap().getResourceOrThrow("bedrock/skull_resource_pack_files.txt")))) { List lines = reader.lines().toList(); for (String path : lines) { ZipEntry entry = new ZipEntry(path); diff --git a/core/src/main/java/org/geysermc/geyser/ping/GeyserLegacyPingPassthrough.java b/core/src/main/java/org/geysermc/geyser/ping/GeyserLegacyPingPassthrough.java index e3c72c174..64ad2c445 100644 --- a/core/src/main/java/org/geysermc/geyser/ping/GeyserLegacyPingPassthrough.java +++ b/core/src/main/java/org/geysermc/geyser/ping/GeyserLegacyPingPassthrough.java @@ -27,6 +27,7 @@ package org.geysermc.geyser.ping; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.JsonMappingException; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.nbt.util.VarInts; import io.netty.handler.codec.haproxy.HAProxyCommand; import io.netty.handler.codec.haproxy.HAProxyProxiedProtocol; @@ -57,7 +58,7 @@ public class GeyserLegacyPingPassthrough implements IGeyserPingPassthrough, Runn * @param geyser Geyser * @return GeyserPingPassthrough, or null if not initialized */ - public static IGeyserPingPassthrough init(GeyserImpl geyser) { + public static @Nullable IGeyserPingPassthrough init(GeyserImpl geyser) { if (geyser.getConfig().isPassthroughMotd() || geyser.getConfig().isPassthroughPlayerCounts()) { GeyserLegacyPingPassthrough pingPassthrough = new GeyserLegacyPingPassthrough(geyser); // Ensure delay is not zero diff --git a/core/src/main/java/org/geysermc/geyser/ping/IGeyserPingPassthrough.java b/core/src/main/java/org/geysermc/geyser/ping/IGeyserPingPassthrough.java index b6095cce2..318035e32 100644 --- a/core/src/main/java/org/geysermc/geyser/ping/IGeyserPingPassthrough.java +++ b/core/src/main/java/org/geysermc/geyser/ping/IGeyserPingPassthrough.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.ping; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.net.InetSocketAddress; /** diff --git a/core/src/main/java/org/geysermc/geyser/registry/AbstractMappedRegistry.java b/core/src/main/java/org/geysermc/geyser/registry/AbstractMappedRegistry.java index fc4e3d022..aea7d539e 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/AbstractMappedRegistry.java +++ b/core/src/main/java/org/geysermc/geyser/registry/AbstractMappedRegistry.java @@ -25,9 +25,9 @@ package org.geysermc.geyser.registry; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.registry.loader.RegistryLoader; -import javax.annotation.Nullable; import java.util.Map; import java.util.Optional; import java.util.function.Function; diff --git a/core/src/main/java/org/geysermc/geyser/registry/ArrayRegistry.java b/core/src/main/java/org/geysermc/geyser/registry/ArrayRegistry.java index 124aea713..3df3ded58 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/ArrayRegistry.java +++ b/core/src/main/java/org/geysermc/geyser/registry/ArrayRegistry.java @@ -25,9 +25,9 @@ package org.geysermc.geyser.registry; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.registry.loader.RegistryLoader; -import javax.annotation.Nullable; import java.util.function.Supplier; /** diff --git a/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java b/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java index 49fd90cf7..aa9d6fc36 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java +++ b/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java @@ -33,7 +33,6 @@ import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.geysermc.geyser.api.block.custom.CustomBlockData; import org.geysermc.geyser.api.block.custom.CustomBlockState; -import org.geysermc.geyser.api.block.custom.nonvanilla.JavaBlockItem; import org.geysermc.geyser.api.block.custom.nonvanilla.JavaBlockState; import org.geysermc.geyser.registry.loader.CollisionRegistryLoader; import org.geysermc.geyser.registry.loader.RegistryLoaders; diff --git a/core/src/main/java/org/geysermc/geyser/registry/IntMappedRegistry.java b/core/src/main/java/org/geysermc/geyser/registry/IntMappedRegistry.java index 892f4a6df..981ed0f8c 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/IntMappedRegistry.java +++ b/core/src/main/java/org/geysermc/geyser/registry/IntMappedRegistry.java @@ -26,8 +26,8 @@ package org.geysermc.geyser.registry; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.registry.loader.RegistryLoader; -import org.jetbrains.annotations.Nullable; import java.util.function.Supplier; diff --git a/core/src/main/java/org/geysermc/geyser/registry/Registry.java b/core/src/main/java/org/geysermc/geyser/registry/Registry.java index f6be19af2..8836502b3 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/Registry.java +++ b/core/src/main/java/org/geysermc/geyser/registry/Registry.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.registry; -import org.cloudburstmc.nbt.NbtMap; import org.geysermc.geyser.registry.loader.RegistryLoader; import java.util.function.Consumer; diff --git a/core/src/main/java/org/geysermc/geyser/registry/VersionedRegistry.java b/core/src/main/java/org/geysermc/geyser/registry/VersionedRegistry.java index cfed73d24..ec7665ff0 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/VersionedRegistry.java +++ b/core/src/main/java/org/geysermc/geyser/registry/VersionedRegistry.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.registry; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.registry.loader.RegistryLoader; import java.util.Map; @@ -53,7 +54,9 @@ public class VersionedRegistry extends AbstractMappedRegistry current = null; for (Int2ObjectMap.Entry entry : this.mappings.int2ObjectEntrySet()) { @@ -69,7 +72,10 @@ public class VersionedRegistry extends AbstractMappedRegistry implements Regi this.mapper = mapper; } + @SuppressWarnings("unchecked") @Override public Map load(String input) { Map entries = new Object2ObjectOpenHashMap<>(); diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/BiomeIdentifierRegistryLoader.java b/core/src/main/java/org/geysermc/geyser/registry/loader/BiomeIdentifierRegistryLoader.java index f7fb708fb..3205004e4 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/loader/BiomeIdentifierRegistryLoader.java +++ b/core/src/main/java/org/geysermc/geyser/registry/loader/BiomeIdentifierRegistryLoader.java @@ -47,7 +47,7 @@ public class BiomeIdentifierRegistryLoader implements RegistryLoader> biomeEntriesType = new TypeReference<>() { }; Map biomeEntries; - try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResource("mappings/biomes.json")) { + try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow("mappings/biomes.json")) { biomeEntries = GeyserImpl.JSON_MAPPER.readValue(stream, biomeEntriesType); } catch (IOException e) { throw new AssertionError("Unable to load Bedrock runtime biomes", e); diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/CollisionRegistryLoader.java b/core/src/main/java/org/geysermc/geyser/registry/loader/CollisionRegistryLoader.java index bf2d72b27..95e8bd2c1 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/loader/CollisionRegistryLoader.java +++ b/core/src/main/java/org/geysermc/geyser/registry/loader/CollisionRegistryLoader.java @@ -32,6 +32,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import lombok.AllArgsConstructor; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.level.physics.BoundingBox; import org.geysermc.geyser.registry.BlockRegistries; @@ -66,7 +67,7 @@ public class CollisionRegistryLoader extends MultiResourceRegistryLoader collisionList; - try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResource(input.value())) { + try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow(input.value())) { ArrayNode collisionNode = (ArrayNode) GeyserImpl.JSON_MAPPER.readTree(stream); collisionList = loadBoundingBoxes(collisionNode); } catch (Exception e) { @@ -101,7 +102,7 @@ public class CollisionRegistryLoader extends MultiResourceRegistryLoader, CollisionInfo> annotationMap, List collisionList) { + private @Nullable BlockCollision instantiateCollision(BlockMapping mapping, Map, CollisionInfo> annotationMap, List collisionList) { String[] blockIdParts = mapping.getJavaIdentifier().split("\\["); String blockName = blockIdParts[0].replace("minecraft:", ""); String params = ""; diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/EffectRegistryLoader.java b/core/src/main/java/org/geysermc/geyser/registry/loader/EffectRegistryLoader.java index 9e1bbc6aa..aa95c1d56 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/loader/EffectRegistryLoader.java +++ b/core/src/main/java/org/geysermc/geyser/registry/loader/EffectRegistryLoader.java @@ -43,7 +43,7 @@ public abstract class EffectRegistryLoader implements RegistryLoader load(String input) { JsonNode enchantmentsNode; - try (InputStream enchantmentsStream = GeyserImpl.getInstance().getBootstrap().getResource(input)) { + try (InputStream enchantmentsStream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow(input)) { enchantmentsNode = GeyserImpl.JSON_MAPPER.readTree(enchantmentsStream); } catch (Exception e) { throw new AssertionError("Unable to load enchantment data", e); diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/NbtRegistryLoader.java b/core/src/main/java/org/geysermc/geyser/registry/loader/NbtRegistryLoader.java index fcdbfcab3..c1f0d4fee 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/loader/NbtRegistryLoader.java +++ b/core/src/main/java/org/geysermc/geyser/registry/loader/NbtRegistryLoader.java @@ -37,7 +37,7 @@ public class NbtRegistryLoader implements RegistryLoader { @Override public NbtMap load(String input) { - try (NBTInputStream nbtInputStream = NbtUtils.createNetworkReader(GeyserImpl.getInstance().getBootstrap().getResource(input), true, true)) { + try (NBTInputStream nbtInputStream = NbtUtils.createNetworkReader(GeyserImpl.getInstance().getBootstrap().getResourceOrThrow(input), true, true)) { return (NbtMap) nbtInputStream.readTag(); } catch (Exception e) { throw new AssertionError("Failed to load registrations for " + input, e); diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/PotionMixRegistryLoader.java b/core/src/main/java/org/geysermc/geyser/registry/loader/PotionMixRegistryLoader.java index 7d5061382..0eec7cdb6 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/loader/PotionMixRegistryLoader.java +++ b/core/src/main/java/org/geysermc/geyser/registry/loader/PotionMixRegistryLoader.java @@ -27,6 +27,7 @@ package org.geysermc.geyser.registry.loader; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.PotionMixData; import org.geysermc.geyser.inventory.item.Potion; import org.geysermc.geyser.item.Items; @@ -44,7 +45,7 @@ import java.util.Set; * Generates a collection of {@link PotionMixData} that enables the * Bedrock client to place brewing items into the brewing stand. * (Does not contain actual potion mixes.) - * + *

* Designed to replicate Java Edition behavior. * (Ex: Bedrock cannot normally place glass bottles or fully upgraded * potions into the brewing stand, but Java can.) diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/SoundRegistryLoader.java b/core/src/main/java/org/geysermc/geyser/registry/loader/SoundRegistryLoader.java index 6703726ea..318cc08d7 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/loader/SoundRegistryLoader.java +++ b/core/src/main/java/org/geysermc/geyser/registry/loader/SoundRegistryLoader.java @@ -43,7 +43,7 @@ public class SoundRegistryLoader implements RegistryLoader load(String input) { JsonNode soundsTree; - try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResource(input)) { + try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow(input)) { soundsTree = GeyserImpl.JSON_MAPPER.readTree(stream); } catch (IOException e) { throw new AssertionError("Unable to load sound mappings", e); diff --git a/core/src/main/java/org/geysermc/geyser/registry/mappings/MappingsConfigReader.java b/core/src/main/java/org/geysermc/geyser/registry/mappings/MappingsConfigReader.java index 039412957..d09e0b5a1 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/mappings/MappingsConfigReader.java +++ b/core/src/main/java/org/geysermc/geyser/registry/mappings/MappingsConfigReader.java @@ -28,6 +28,7 @@ package org.geysermc.geyser.registry.mappings; import com.fasterxml.jackson.databind.JsonNode; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.item.custom.CustomItemData; import org.geysermc.geyser.registry.mappings.util.CustomBlockMapping; @@ -57,6 +58,8 @@ public class MappingsConfigReader { } } + + @SuppressWarnings("BooleanMethodIsAlwaysInverted") public boolean ensureMappingsDirectory(Path mappingsDirectory) { if (!Files.exists(mappingsDirectory)) { try { @@ -92,7 +95,7 @@ public class MappingsConfigReader { } } - public JsonNode getMappingsRoot(Path file) { + public @Nullable JsonNode getMappingsRoot(Path file) { JsonNode mappingsRoot; try { mappingsRoot = GeyserImpl.JSON_MAPPER.readTree(file.toFile()); @@ -121,9 +124,13 @@ public class MappingsConfigReader { public void readItemMappingsFromJson(Path file, BiConsumer consumer) { JsonNode mappingsRoot = getMappingsRoot(file); + if (mappingsRoot == null) { + return; + } + int formatVersion = getFormatVersion(mappingsRoot, file); - if (formatVersion < 0 || mappingsRoot == null) { + if (formatVersion < 0) { return; } @@ -133,9 +140,13 @@ public class MappingsConfigReader { public void readBlockMappingsFromJson(Path file, BiConsumer consumer) { JsonNode mappingsRoot = getMappingsRoot(file); + if (mappingsRoot == null) { + return; + } + int formatVersion = getFormatVersion(mappingsRoot, file); - if (formatVersion < 0 || mappingsRoot == null) { + if (formatVersion < 0) { return; } diff --git a/core/src/main/java/org/geysermc/geyser/registry/mappings/util/CustomBlockMapping.java b/core/src/main/java/org/geysermc/geyser/registry/mappings/util/CustomBlockMapping.java index 3dbb7908e..10108cc9c 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/mappings/util/CustomBlockMapping.java +++ b/core/src/main/java/org/geysermc/geyser/registry/mappings/util/CustomBlockMapping.java @@ -25,11 +25,11 @@ package org.geysermc.geyser.registry.mappings.util; -import java.util.Map; - import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.api.block.custom.CustomBlockData; +import java.util.Map; + /** * This class is used to store a custom block mappings, which contain all of the * data required to register a custom block that overrides a group of java block @@ -38,7 +38,7 @@ import org.geysermc.geyser.api.block.custom.CustomBlockData; * @param data The custom block data * @param states The custom block state mappings * @param javaIdentifier The java identifier of the block - * @param overrideItem Whether or not the custom block should override the java item + * @param overrideItem Whether the custom block should override the java item */ public record CustomBlockMapping(@NonNull CustomBlockData data, @NonNull Map states, @NonNull String javaIdentifier, boolean overrideItem) { } diff --git a/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader.java b/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader.java index e76df2834..b2bdd5a01 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader.java +++ b/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.registry.mappings.versions; import com.fasterxml.jackson.databind.JsonNode; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.api.item.custom.CustomItemData; import org.geysermc.geyser.api.item.custom.CustomRenderOffsets; import org.geysermc.geyser.item.exception.InvalidCustomMappingsFileException; @@ -41,7 +42,7 @@ public abstract class MappingsReader { public abstract CustomItemData readItemMappingEntry(JsonNode node) throws InvalidCustomMappingsFileException; public abstract CustomBlockMapping readBlockMappingEntry(String identifier, JsonNode node) throws InvalidCustomMappingsFileException; - protected CustomRenderOffsets fromJsonNode(JsonNode node) { + protected @Nullable CustomRenderOffsets fromJsonNode(JsonNode node) { if (node == null || !node.isObject()) { return null; } @@ -52,7 +53,7 @@ public abstract class MappingsReader { ); } - protected CustomRenderOffsets.Hand getHandOffsets(JsonNode node, String hand) { + protected CustomRenderOffsets.@Nullable Hand getHandOffsets(JsonNode node, String hand) { JsonNode tmpNode = node.get(hand); if (tmpNode == null || !tmpNode.isObject()) { return null; @@ -64,7 +65,7 @@ public abstract class MappingsReader { ); } - protected CustomRenderOffsets.Offset getPerspectiveOffsets(JsonNode node, String perspective) { + protected CustomRenderOffsets.@Nullable Offset getPerspectiveOffsets(JsonNode node, String perspective) { JsonNode tmpNode = node.get(perspective); if (tmpNode == null || !tmpNode.isObject()) { return null; @@ -77,7 +78,7 @@ public abstract class MappingsReader { ); } - protected CustomRenderOffsets.OffsetXYZ getOffsetXYZ(JsonNode node, String offsetType) { + protected CustomRenderOffsets.@Nullable OffsetXYZ getOffsetXYZ(JsonNode node, String offsetType) { JsonNode tmpNode = node.get(offsetType); if (tmpNode == null || !tmpNode.isObject()) { return null; diff --git a/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java b/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java index fb4a6acbe..1a498c3fa 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java +++ b/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java @@ -30,6 +30,7 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import com.github.steveice10.mc.protocol.data.game.Identifier; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.block.custom.CustomBlockData; import org.geysermc.geyser.api.block.custom.CustomBlockPermutation; @@ -405,7 +406,9 @@ public class MappingsReader_v1 extends MappingsReader { if (boneVisibility.isObject()) { Map boneVisibilityMap = new Object2ObjectOpenHashMap<>(); boneVisibility.fields().forEachRemaining(entry -> { - boneVisibilityMap.put(entry.getKey(), entry.getValue().isBoolean() ? (entry.getValue().asBoolean() ? "1" : "0") : entry.getValue().asText()); + String key = entry.getKey(); + String value = entry.getValue().isBoolean() ? (entry.getValue().asBoolean() ? "1" : "0") : entry.getValue().asText(); + boneVisibilityMap.put(key, value); }); geometryBuilder.boneVisibility(boneVisibilityMap); } @@ -483,7 +486,7 @@ public class MappingsReader_v1 extends MappingsReader { String key = entry.getKey(); JsonNode value = entry.getValue(); if (value.isObject()) { - MaterialInstance materialInstance = createMaterialInstanceComponent(value, name); + MaterialInstance materialInstance = createMaterialInstanceComponent(value); builder.materialInstance(key, materialInstance); } }); @@ -583,7 +586,7 @@ public class MappingsReader_v1 extends MappingsReader { * @param javaId the block's Java ID * @return the {@link BoxComponent} or null if the block's collision box would not exceed 16 y units */ - private BoxComponent createExtendedBoxComponent(int javaId) { + private @Nullable BoxComponent createExtendedBoxComponent(int javaId) { BlockCollision blockCollision = BlockUtils.getCollision(javaId); if (blockCollision == null) { return null; @@ -603,7 +606,7 @@ public class MappingsReader_v1 extends MappingsReader { * @param node the JSON node * @return the {@link BoxComponent} */ - private BoxComponent createBoxComponent(JsonNode node) { + private @Nullable BoxComponent createBoxComponent(JsonNode node) { if (node != null && node.isObject()) { if (node.has("origin") && node.has("size")) { JsonNode origin = node.get("origin"); @@ -627,10 +630,9 @@ public class MappingsReader_v1 extends MappingsReader { * The name is used as a fallback if no texture is provided by the node * * @param node the material instance node - * @param name the custom block name * @return the {@link MaterialInstance} */ - private MaterialInstance createMaterialInstanceComponent(JsonNode node, String name) { + private MaterialInstance createMaterialInstanceComponent(JsonNode node) { // Set default values, and use what the user provides if they have provided something String texture = null; if (node.has("texture")) { 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 e3f4e685d..328f61500 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 @@ -79,7 +79,7 @@ public final class BlockRegistryPopulator { PRE_INIT, INIT_JAVA, INIT_BEDROCK, - POST_INIT; + POST_INIT } @FunctionalInterface @@ -103,10 +103,10 @@ public final class BlockRegistryPopulator { public static void populate(Stage stage) { switch (stage) { - case PRE_INIT, POST_INIT -> { nullifyBlocksNode(); } - case INIT_JAVA -> { registerJavaBlocks(); } - case INIT_BEDROCK -> { registerBedrockBlocks(); } - default -> { throw new IllegalArgumentException("Unknown stage: " + stage); } + case PRE_INIT, POST_INIT -> nullifyBlocksNode(); + case INIT_JAVA -> registerJavaBlocks(); + case INIT_BEDROCK -> registerBedrockBlocks(); + default -> throw new IllegalArgumentException("Unknown stage: " + stage); } } @@ -137,14 +137,15 @@ public final class BlockRegistryPopulator { // We can keep this strong as nothing should be garbage collected // Safe to intern since Cloudburst NBT is immutable + //noinspection UnstableApiUsage Interner statesInterner = Interners.newStrongInterner(); for (ObjectIntPair palette : blockMappers.keySet()) { int protocolVersion = palette.valueInt(); List vanillaBlockStates; List blockStates; - try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResource(String.format("bedrock/block_palette.%s.nbt", palette.key())); - NBTInputStream nbtInputStream = new NBTInputStream(new DataInputStream(new GZIPInputStream(stream)), true, true)) { + try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow(String.format("bedrock/block_palette.%s.nbt", palette.key())); + NBTInputStream nbtInputStream = new NBTInputStream(new DataInputStream(new GZIPInputStream(stream)), true, true)) { NbtMap blockPalette = (NbtMap) nbtInputStream.readTag(); vanillaBlockStates = new ArrayList<>(blockPalette.getList("blocks", NbtType.COMPOUND)); @@ -153,6 +154,7 @@ public final class BlockRegistryPopulator { builder.remove("version"); // Remove all nbt tags which are not needed for differentiating states builder.remove("name_hash"); // Quick workaround - was added in 1.19.20 builder.remove("network_id"); // Added in 1.19.80 - ???? + //noinspection UnstableApiUsage builder.putCompound("states", statesInterner.intern((NbtMap) builder.remove("states"))); vanillaBlockStates.set(i, builder.build()); } @@ -323,7 +325,7 @@ public final class BlockRegistryPopulator { builder.bedrockMovingBlock(movingBlockDefinition); Map nonVanillaStateOverrides = BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get(); - if (nonVanillaStateOverrides.size() > 0) { + if (!nonVanillaStateOverrides.isEmpty()) { // First ensure all non vanilla runtime IDs at minimum are air in case they aren't consecutive Arrays.fill(javaToVanillaBedrockBlocks, MIN_CUSTOM_RUNTIME_ID, javaToVanillaBedrockBlocks.length, airDefinition); Arrays.fill(javaToBedrockBlocks, MIN_CUSTOM_RUNTIME_ID, javaToBedrockBlocks.length, airDefinition); @@ -374,7 +376,7 @@ public final class BlockRegistryPopulator { private static void registerJavaBlocks() { JsonNode blocksJson; - try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResource("mappings/blocks.json")) { + try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow("mappings/blocks.json")) { blocksJson = GeyserImpl.JSON_MAPPER.readTree(stream); } catch (Exception e) { throw new AssertionError("Unable to load Java block mappings", e); @@ -382,9 +384,9 @@ public final class BlockRegistryPopulator { JAVA_BLOCKS_SIZE = blocksJson.size(); - if (BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().size() > 0) { - MIN_CUSTOM_RUNTIME_ID = BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().keySet().stream().min(Comparator.comparing(JavaBlockState::javaId)).get().javaId(); - int maxCustomRuntimeID = BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().keySet().stream().max(Comparator.comparing(JavaBlockState::javaId)).get().javaId(); + if (!BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().isEmpty()) { + MIN_CUSTOM_RUNTIME_ID = BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().keySet().stream().min(Comparator.comparing(JavaBlockState::javaId)).orElseThrow().javaId(); + int maxCustomRuntimeID = BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().keySet().stream().max(Comparator.comparing(JavaBlockState::javaId)).orElseThrow().javaId(); if (MIN_CUSTOM_RUNTIME_ID < blocksJson.size()) { throw new RuntimeException("Non vanilla custom block state overrides runtime ID must start after the last vanilla block state (" + JAVA_BLOCKS_SIZE + ")"); @@ -531,7 +533,7 @@ public final class BlockRegistryPopulator { } BlockStateValues.JAVA_WATER_ID = waterRuntimeId; - if (BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().size() > 0) { + if (!BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().isEmpty()) { Set usedNonVanillaRuntimeIDs = new HashSet<>(); for (JavaBlockState javaBlockState : BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().keySet()) { @@ -543,6 +545,7 @@ public final class BlockRegistryPopulator { String javaId = javaBlockState.identifier(); int stateRuntimeId = javaBlockState.javaId(); + String pistonBehavior = javaBlockState.pistonBehavior(); BlockMapping blockMapping = BlockMapping.builder() .canBreakWithHand(javaBlockState.canBreakWithHand()) .pickItem(javaBlockState.pickItem()) @@ -550,7 +553,7 @@ public final class BlockRegistryPopulator { .javaIdentifier(javaId) .javaBlockId(javaBlockState.stateGroupId()) .hardness(javaBlockState.blockHardness()) - .pistonBehavior(javaBlockState.pistonBehavior() == null ? PistonBehavior.NORMAL : PistonBehavior.getByName(javaBlockState.pistonBehavior())) + .pistonBehavior(pistonBehavior == null ? PistonBehavior.NORMAL : PistonBehavior.getByName(pistonBehavior)) .isBlockEntity(javaBlockState.hasBlockEntity()) .build(); @@ -576,7 +579,7 @@ public final class BlockRegistryPopulator { BLOCKS_JSON = blocksJson; JsonNode blockInteractionsJson; - try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResource("mappings/interactions.json")) { + try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow("mappings/interactions.json")) { blockInteractionsJson = GeyserImpl.JSON_MAPPER.readTree(stream); } catch (Exception e) { throw new AssertionError("Unable to load Java block interaction mappings", e); 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 index 6944bbcc3..d27a2ed49 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/CreativeItemRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/CreativeItemRegistryPopulator.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.registry.populator; import com.fasterxml.jackson.databind.JsonNode; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtUtils; @@ -61,7 +62,7 @@ public class CreativeItemRegistryPopulator { // Load creative items JsonNode creativeItemEntries; - try (InputStream stream = bootstrap.getResource(String.format("bedrock/creative_items.%s.json", palette.version()))) { + try (InputStream stream = bootstrap.getResourceOrThrow(String.format("bedrock/creative_items.%s.json", palette.version()))) { creativeItemEntries = GeyserImpl.JSON_MAPPER.readTree(stream).get("items"); } catch (Exception e) { throw new AssertionError("Unable to load creative items", e); @@ -78,10 +79,10 @@ public class CreativeItemRegistryPopulator { } } - private static ItemData.Builder createItemData(JsonNode itemNode, BlockMappings blockMappings, Map definitions) { + private static ItemData.@Nullable Builder createItemData(JsonNode itemNode, BlockMappings blockMappings, Map definitions) { int count = 1; int damage = 0; - int bedrockBlockRuntimeId = -1; + int bedrockBlockRuntimeId; NbtMap tag = null; String identifier = itemNode.get("id").textValue(); diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java index e4bf43b93..e4f45ac85 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java @@ -48,7 +48,7 @@ public class CustomBlockRegistryPopulator { DEFINITION, VANILLA_REGISTRATION, NON_VANILLA_REGISTRATION, - CUSTOM_REGISTRATION; + CUSTOM_REGISTRATION } /** @@ -62,11 +62,11 @@ public class CustomBlockRegistryPopulator { } switch (stage) { - case DEFINITION -> { populateBedrock(); } - case VANILLA_REGISTRATION -> { populateVanilla(); } - case NON_VANILLA_REGISTRATION -> { populateNonVanilla(); } - case CUSTOM_REGISTRATION -> { registration(); } - default -> { throw new IllegalArgumentException("Unknown stage: " + stage); } + case DEFINITION -> populateBedrock(); + case VANILLA_REGISTRATION -> populateVanilla(); + case NON_VANILLA_REGISTRATION -> populateNonVanilla(); + case CUSTOM_REGISTRATION -> registration(); + default -> throw new IllegalArgumentException("Unknown stage: " + stage); } } @@ -479,7 +479,7 @@ public class CustomBlockRegistryPopulator { } private static CustomBlockData createExtendedCollisionBlock(BoxComponent boxComponent, int extendedCollisionBlock) { - CustomBlockData customBlockData = new CustomBlockDataBuilder() + return new CustomBlockDataBuilder() .name("extended_collision_" + extendedCollisionBlock) .components( new CustomBlockComponentsBuilder() @@ -497,6 +497,5 @@ public class CustomBlockRegistryPopulator { .build()) .build()) .build(); - return customBlockData; } } 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 638e41a5e..6be1aac4c 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 @@ -27,6 +27,7 @@ package org.geysermc.geyser.registry.populator; import com.google.common.collect.Multimap; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; @@ -48,7 +49,6 @@ import org.geysermc.geyser.registry.type.GeyserMappingItem; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.NonVanillaItemRegistration; -import javax.annotation.Nullable; import java.util.*; public class CustomItemRegistryPopulator { @@ -171,7 +171,7 @@ public class CustomItemRegistryPopulator { boolean canDestroyInCreative = true; if (mapping.getToolType() != null) { // This is not using the isTool boolean because it is not just a render type here. - canDestroyInCreative = computeToolProperties(mapping.getToolTier(), mapping.getToolType(), itemProperties, componentBuilder); + canDestroyInCreative = computeToolProperties(mapping.getToolType(), itemProperties, componentBuilder); } itemProperties.putBoolean("can_destroy_in_creative", canDestroyInCreative); @@ -192,18 +192,11 @@ public class CustomItemRegistryPopulator { } switch (mapping.getBedrockIdentifier()) { - case "minecraft:fire_charge", "minecraft:flint_and_steel" -> { - computeBlockItemProperties("minecraft:fire", componentBuilder); - } - case "minecraft:bow", "minecraft:crossbow", "minecraft:trident" -> { - computeChargeableProperties(itemProperties, componentBuilder); - } - case "minecraft:honey_bottle", "minecraft:milk_bucket", "minecraft:potion" -> { - computeConsumableProperties(itemProperties, componentBuilder, 2, true); - } - case "minecraft:experience_bottle", "minecraft:egg", "minecraft:ender_pearl", "minecraft:ender_eye", "minecraft:lingering_potion", "minecraft:snowball", "minecraft:splash_potion" -> { - computeThrowableProperties(componentBuilder); - } + case "minecraft:fire_charge", "minecraft:flint_and_steel" -> computeBlockItemProperties("minecraft:fire", componentBuilder); + case "minecraft:bow", "minecraft:crossbow", "minecraft:trident" -> computeChargeableProperties(itemProperties, componentBuilder); + case "minecraft:honey_bottle", "minecraft:milk_bucket", "minecraft:potion" -> computeConsumableProperties(itemProperties, componentBuilder, 2, true); + case "minecraft:experience_bottle", "minecraft:egg", "minecraft:ender_pearl", "minecraft:ender_eye", "minecraft:lingering_potion", "minecraft:snowball", "minecraft:splash_potion" -> + computeThrowableProperties(componentBuilder); } computeRenderOffsets(false, customItemData, componentBuilder); @@ -214,6 +207,7 @@ public class CustomItemRegistryPopulator { return builder; } + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") private static NbtMapBuilder createComponentNbt(NonVanillaCustomItemData customItemData, String customItemName, int customItemId, OptionalInt creativeCategory, String creativeGroup, boolean isHat, boolean displayHandheld) { @@ -228,7 +222,7 @@ public class CustomItemRegistryPopulator { boolean canDestroyInCreative = true; if (customItemData.toolType() != null) { // This is not using the isTool boolean because it is not just a render type here. - canDestroyInCreative = computeToolProperties(customItemData.toolTier(), customItemData.toolType(), itemProperties, componentBuilder); + canDestroyInCreative = computeToolProperties(customItemData.toolType(), itemProperties, componentBuilder); } itemProperties.putBoolean("can_destroy_in_creative", canDestroyInCreative); @@ -300,7 +294,7 @@ public class CustomItemRegistryPopulator { /** * @return can destroy in creative */ - private static boolean computeToolProperties(String toolTier, String toolType, NbtMapBuilder itemProperties, NbtMapBuilder componentBuilder) { + private static boolean computeToolProperties(String toolType, NbtMapBuilder itemProperties, NbtMapBuilder componentBuilder) { boolean canDestroyInCreative = true; float miningSpeed = 1.0f; @@ -467,7 +461,7 @@ public class CustomItemRegistryPopulator { return builder.build(); } - private static NbtMap toNbtMap(CustomRenderOffsets.Hand hand) { + private static @Nullable NbtMap toNbtMap(CustomRenderOffsets.Hand hand) { NbtMap firstPerson = toNbtMap(hand.firstPerson()); NbtMap thirdPerson = toNbtMap(hand.thirdPerson()); @@ -486,7 +480,7 @@ public class CustomItemRegistryPopulator { return builder.build(); } - private static NbtMap toNbtMap(@Nullable CustomRenderOffsets.Offset offset) { + private static @Nullable NbtMap toNbtMap(CustomRenderOffsets.@Nullable Offset offset) { if (offset == null) { return null; } diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomSkullRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomSkullRegistryPopulator.java index f66d21572..02d9a75ec 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomSkullRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomSkullRegistryPopulator.java @@ -27,7 +27,8 @@ package org.geysermc.geyser.registry.populator; import it.unimi.dsi.fastutil.objects.Object2ObjectMaps; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import lombok.NonNull; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.event.lifecycle.GeyserDefineCustomSkullsEvent; @@ -139,7 +140,7 @@ public class CustomSkullRegistryPopulator { * @param profile the base64 encoded profile * @return the skin hash or null if the profile is invalid */ - private static String getSkinHash(String profile) { + private static @Nullable String getSkinHash(String profile) { try { SkinManager.GameProfileData profileData = SkinManager.GameProfileData.loadFromJson(profile); if (profileData == null) { @@ -159,7 +160,7 @@ public class CustomSkullRegistryPopulator { * @param username the player username * @return the base64 encoded profile or null if the request failed */ - private static String getProfileFromUsername(String username) { + private static @Nullable String getProfileFromUsername(String username) { try { return SkinProvider.requestTexturesFromUsername(username).get(); } catch (InterruptedException | ExecutionException e) { @@ -173,7 +174,7 @@ public class CustomSkullRegistryPopulator { * @param uuid the player UUID * @return the base64 encoded profile or null if the request failed */ - private static String getProfileFromUuid(String uuid) { + private static @Nullable String getProfileFromUuid(String uuid) { try { String uuidDigits = uuid.replace("-", ""); if (uuidDigits.length() != 32) { 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 fe6e21e6f..f46a49c3a 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 @@ -139,7 +139,7 @@ public class ItemRegistryPopulator { TypeReference> mappingItemsType = new TypeReference<>() { }; Map items; - try (InputStream stream = bootstrap.getResource("mappings/items.json")) { + try (InputStream stream = bootstrap.getResourceOrThrow("mappings/items.json")) { // Load item mappings from Java Edition to Bedrock Edition items = GeyserImpl.JSON_MAPPER.readValue(stream, mappingItemsType); } catch (Exception e) { @@ -166,7 +166,7 @@ public class ItemRegistryPopulator { TypeReference> paletteEntriesType = new TypeReference<>() {}; List itemEntries; - try (InputStream stream = bootstrap.getResource(String.format("bedrock/runtime_item_states.%s.json", palette.version()))) { + try (InputStream stream = bootstrap.getResourceOrThrow(String.format("bedrock/runtime_item_states.%s.json", palette.version()))) { itemEntries = GeyserImpl.JSON_MAPPER.readValue(stream, paletteEntriesType); } catch (Exception e) { throw new AssertionError("Unable to load Bedrock runtime item IDs", e); 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 3e9e2c257..f8929c900 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 @@ -64,7 +64,7 @@ public class RecipeRegistryPopulator { public static void populate() { JsonNode items; - try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResource("mappings/recipes.json")) { + try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow("mappings/recipes.json")) { items = GeyserImpl.JSON_MAPPER.readTree(stream); } catch (Exception e) { throw new AssertionError(GeyserLocale.getLocaleStringLog("geyser.toolbox.fail.runtime_java"), e); diff --git a/core/src/main/java/org/geysermc/geyser/registry/type/BlockMapping.java b/core/src/main/java/org/geysermc/geyser/registry/type/BlockMapping.java index 9745a8859..0196ac22f 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/type/BlockMapping.java +++ b/core/src/main/java/org/geysermc/geyser/registry/type/BlockMapping.java @@ -27,16 +27,15 @@ package org.geysermc.geyser.registry.type; import lombok.Builder; import lombok.Value; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.level.physics.PistonBehavior; import org.geysermc.geyser.util.BlockUtils; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - @Builder @Value public class BlockMapping { - public static BlockMapping DEFAULT = BlockMapping.builder().javaIdentifier("minecraft:air").pistonBehavior(PistonBehavior.NORMAL).build();; + public static BlockMapping DEFAULT = BlockMapping.builder().javaIdentifier("minecraft:air").pistonBehavior(PistonBehavior.NORMAL).build(); String javaIdentifier; /** @@ -53,8 +52,7 @@ public class BlockMapping { int collisionIndex; @Nullable String pickItem; - @Nonnull - PistonBehavior pistonBehavior; + @NonNull PistonBehavior pistonBehavior; boolean isBlockEntity; boolean isNonVanilla; 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 3d06cecac..8c0414a6d 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 @@ -29,6 +29,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import lombok.Builder; import lombok.Value; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.protocol.bedrock.data.BlockPropertyData; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; @@ -96,14 +97,14 @@ public class BlockMappings implements DefinitionRegistry { } @Override - public GeyserBedrockBlock getDefinition(int bedrockId) { + public @Nullable GeyserBedrockBlock getDefinition(int bedrockId) { if (bedrockId < 0 || bedrockId >= this.bedrockRuntimeMap.length) { return null; } return bedrockRuntimeMap[bedrockId]; } - public GeyserBedrockBlock getDefinition(NbtMap tag) { + public @Nullable GeyserBedrockBlock getDefinition(NbtMap tag) { if (tag == null) { return null; } diff --git a/core/src/main/java/org/geysermc/geyser/registry/type/ParticleMapping.java b/core/src/main/java/org/geysermc/geyser/registry/type/ParticleMapping.java index f8aeb78ee..4108fba1f 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/type/ParticleMapping.java +++ b/core/src/main/java/org/geysermc/geyser/registry/type/ParticleMapping.java @@ -25,10 +25,8 @@ package org.geysermc.geyser.registry.type; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.data.LevelEventType; -import javax.annotation.ParametersAreNullableByDefault; - -@ParametersAreNullableByDefault -public record ParticleMapping(LevelEventType levelEventType, String identifier) { +public record ParticleMapping(@Nullable LevelEventType levelEventType, @Nullable String identifier) { } \ No newline at end of file diff --git a/core/src/main/java/org/geysermc/geyser/scoreboard/Objective.java b/core/src/main/java/org/geysermc/geyser/scoreboard/Objective.java index 688666c73..fd9e0fbf3 100644 --- a/core/src/main/java/org/geysermc/geyser/scoreboard/Objective.java +++ b/core/src/main/java/org/geysermc/geyser/scoreboard/Objective.java @@ -29,6 +29,7 @@ import com.github.steveice10.mc.protocol.data.game.scoreboard.ScoreboardPosition import com.github.steveice10.mc.protocol.data.game.scoreboard.TeamColor; import lombok.Getter; import lombok.Setter; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -150,7 +151,7 @@ public final class Objective { updateType = UpdateType.REMOVE; } - public TeamColor getTeamColor() { + public @Nullable TeamColor getTeamColor() { return switch (displaySlot) { case SIDEBAR_TEAM_RED -> TeamColor.RED; case SIDEBAR_TEAM_AQUA -> TeamColor.AQUA; diff --git a/core/src/main/java/org/geysermc/geyser/scoreboard/Scoreboard.java b/core/src/main/java/org/geysermc/geyser/scoreboard/Scoreboard.java index c49e8afc4..1e0ea5eb1 100644 --- a/core/src/main/java/org/geysermc/geyser/scoreboard/Scoreboard.java +++ b/core/src/main/java/org/geysermc/geyser/scoreboard/Scoreboard.java @@ -26,13 +26,14 @@ package org.geysermc.geyser.scoreboard; import com.github.steveice10.mc.protocol.data.game.scoreboard.ScoreboardPosition; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import lombok.Getter; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.data.ScoreInfo; import org.cloudburstmc.protocol.bedrock.data.command.CommandEnumConstraint; import org.cloudburstmc.protocol.bedrock.packet.RemoveObjectivePacket; import org.cloudburstmc.protocol.bedrock.packet.SetDisplayObjectivePacket; import org.cloudburstmc.protocol.bedrock.packet.SetScorePacket; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import lombok.Getter; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserLogger; import org.geysermc.geyser.entity.type.Entity; @@ -41,14 +42,16 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.GeyserLocale; import org.jetbrains.annotations.Contract; -import javax.annotation.Nullable; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicLong; import java.util.function.Function; import java.util.stream.Collectors; -import static org.geysermc.geyser.scoreboard.UpdateType.*; +import static org.geysermc.geyser.scoreboard.UpdateType.ADD; +import static org.geysermc.geyser.scoreboard.UpdateType.NOTHING; +import static org.geysermc.geyser.scoreboard.UpdateType.REMOVE; +import static org.geysermc.geyser.scoreboard.UpdateType.UPDATE; public final class Scoreboard { private static final boolean SHOW_SCOREBOARD_LOGS = Boolean.parseBoolean(System.getProperty("Geyser.ShowScoreboardLogs", "true")); @@ -89,7 +92,7 @@ public final class Scoreboard { } } - public Objective registerNewObjective(String objectiveId) { + public @Nullable Objective registerNewObjective(String objectiveId) { Objective objective = objectives.get(objectiveId); if (objective != null) { // we have no other choice, or we have to make a new map? diff --git a/core/src/main/java/org/geysermc/geyser/scoreboard/ScoreboardUpdater.java b/core/src/main/java/org/geysermc/geyser/scoreboard/ScoreboardUpdater.java index fed3054b4..8c1ef5296 100644 --- a/core/src/main/java/org/geysermc/geyser/scoreboard/ScoreboardUpdater.java +++ b/core/src/main/java/org/geysermc/geyser/scoreboard/ScoreboardUpdater.java @@ -173,6 +173,7 @@ public final class ScoreboardUpdater extends Thread { @Getter public static final class ScoreboardSession { private final GeyserSession session; + @SuppressWarnings("WriteOnlyObject") private final AtomicInteger pendingPacketsPerSecond = new AtomicInteger(0); private int packetsPerSecond; private long lastUpdate; diff --git a/core/src/main/java/org/geysermc/geyser/scoreboard/Team.java b/core/src/main/java/org/geysermc/geyser/scoreboard/Team.java index e985ca803..9164fec1d 100644 --- a/core/src/main/java/org/geysermc/geyser/scoreboard/Team.java +++ b/core/src/main/java/org/geysermc/geyser/scoreboard/Team.java @@ -32,9 +32,9 @@ import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; import lombok.experimental.Accessors; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.HashSet; import java.util.Set; @@ -46,7 +46,7 @@ public final class Team { @Getter(AccessLevel.PACKAGE) private final Set entities; - @Nonnull private NameTagVisibility nameTagVisibility = NameTagVisibility.ALWAYS; + @NonNull private NameTagVisibility nameTagVisibility = NameTagVisibility.ALWAYS; @Setter private TeamColor color; private final TeamData currentData; diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 9bfb4e01c..2f0d47b38 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -147,7 +147,6 @@ import org.geysermc.geyser.util.ChunkUtils; import org.geysermc.geyser.util.DimensionUtils; import org.geysermc.geyser.util.EntityUtils; import org.geysermc.geyser.util.LoginEncryptionUtils; -import org.jetbrains.annotations.NotNull; import java.net.ConnectException; import java.net.InetSocketAddress; @@ -181,7 +180,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { @Setter private List certChainData; - @NotNull + @NonNull @Setter private AbstractGeyserboundPacketHandler erosionHandler; @@ -336,7 +335,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { /** * Tracks the original speed attribute. - * + *

* We need to do this in order to emulate speeds when sneaking under 1.5-blocks-tall areas if the player isn't sneaking, * and when crawling. */ @@ -461,7 +460,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { /** * Store the last time the player interacted. Used to fix a right-click spam bug. - * See https://github.com/GeyserMC/Geyser/issues/503 for context. + * See this for context. */ @Setter private long lastInteractionTime; @@ -1318,7 +1317,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { * * @return not null if attributes should be updated. */ - public AttributeData adjustSpeed() { + public @Nullable AttributeData adjustSpeed() { AttributeData currentPlayerSpeed = playerEntity.getAttributes().get(GeyserAttributeType.MOVEMENT_SPEED); if (currentPlayerSpeed != null) { if ((pose.equals(Pose.SNEAKING) && !sneaking && collisionManager.mustPlayerSneakHere()) || @@ -1370,7 +1369,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { } /** - * For https://github.com/GeyserMC/Geyser/issues/2113 and combating arm ticking activating being delayed in + * For issue 2113 and combating arm ticking activating being delayed in * BedrockAnimateTranslator. */ public void armSwingPending() { @@ -1405,7 +1404,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { } @Override - public void sendMessage(String message) { + public void sendMessage(@NonNull String message) { TextPacket textPacket = new TextPacket(); textPacket.setPlatformChatId(""); textPacket.setSourceName(""); @@ -1911,7 +1910,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { } @Override - public String bedrockUsername() { + public @NonNull String bedrockUsername() { return authData.name(); } @@ -1926,7 +1925,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { } @Override - public String xuid() { + public @NonNull String xuid() { return authData.xuid(); } diff --git a/core/src/main/java/org/geysermc/geyser/session/PendingMicrosoftAuthentication.java b/core/src/main/java/org/geysermc/geyser/session/PendingMicrosoftAuthentication.java index 93200dcb6..132de67cb 100644 --- a/core/src/main/java/org/geysermc/geyser/session/PendingMicrosoftAuthentication.java +++ b/core/src/main/java/org/geysermc/geyser/session/PendingMicrosoftAuthentication.java @@ -32,13 +32,13 @@ import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import lombok.Getter; -import lombok.NonNull; import lombok.Setter; import lombok.SneakyThrows; +import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserLogger; -import javax.annotation.Nonnull; +import java.io.Serial; import java.util.concurrent.*; /** @@ -63,12 +63,12 @@ public class PendingMicrosoftAuthentication { }); } - public AuthenticationTask getTask(@Nonnull String userKey) { + public AuthenticationTask getTask(@NonNull String userKey) { return authentications.getIfPresent(userKey); } @SneakyThrows(ExecutionException.class) - public AuthenticationTask getOrCreateTask(@Nonnull String userKey) { + public AuthenticationTask getOrCreateTask(@NonNull String userKey) { return authentications.get(userKey); } @@ -189,6 +189,10 @@ public class PendingMicrosoftAuthentication { * @see PendingMicrosoftAuthentication */ public static class TaskTimeoutException extends Exception { + + @Serial + private static final long serialVersionUID = 1L; + TaskTimeoutException() { super("It took too long to authorize Geyser to access your Microsoft account. " + "Please request new code and try again."); diff --git a/core/src/main/java/org/geysermc/geyser/session/SessionManager.java b/core/src/main/java/org/geysermc/geyser/session/SessionManager.java index 7e5982ab5..14881d059 100644 --- a/core/src/main/java/org/geysermc/geyser/session/SessionManager.java +++ b/core/src/main/java/org/geysermc/geyser/session/SessionManager.java @@ -28,9 +28,10 @@ package org.geysermc.geyser.session; import com.google.common.collect.ImmutableList; import lombok.AccessLevel; import lombok.Getter; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.text.GeyserLocale; -import javax.annotation.Nonnull; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -69,7 +70,7 @@ public final class SessionManager { } } - public GeyserSession sessionByXuid(@Nonnull String xuid) { + public @Nullable GeyserSession sessionByXuid(@NonNull String xuid) { Objects.requireNonNull(xuid); for (GeyserSession session : sessions.values()) { if (session.xuid().equals(xuid)) { diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/AdvancementsCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/AdvancementsCache.java index db0321147..3562f0d4d 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/AdvancementsCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/AdvancementsCache.java @@ -140,7 +140,7 @@ public class AdvancementsCache { session.sendDownstreamGamePacket(new ServerboundSeenAdvancementsPacket()); }).validResultHandler((response) -> { - if (response.getClickedButtonId() < visibleAdvancements.size()) { + if (response.clickedButtonId() < visibleAdvancements.size()) { GeyserAdvancement advancement = visibleAdvancements.get(response.clickedButtonId()); buildAndShowInfoForm(advancement); } else { diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/BookEditCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/BookEditCache.java index d1ebd0c78..6a9025bc0 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/BookEditCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/BookEditCache.java @@ -33,7 +33,7 @@ import org.geysermc.geyser.session.GeyserSession; /** * Manages updating the current writable book. - * + *

* Java sends book updates less frequently than Bedrock, and this can cause issues with servers that rate limit * book packets. Because of this, we need to ensure packets are only send every second or so at maximum. */ diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/LodestoneCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/LodestoneCache.java index 41f73863e..f118195b9 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/LodestoneCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/LodestoneCache.java @@ -30,9 +30,9 @@ import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.inventory.GeyserItemStack; -import javax.annotation.Nullable; import java.util.Map; import java.util.WeakHashMap; @@ -54,6 +54,10 @@ public final class LodestoneCache { public void cacheInventoryItem(GeyserItemStack itemStack) { CompoundTag tag = itemStack.getNbt(); + if (tag == null) { + // invalid + return; + } CompoundTag lodestonePos = tag.get("LodestonePos"); if (lodestonePos == null) { // invalid diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/PreferencesCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/PreferencesCache.java index 9e8597b0f..2aeb83fa8 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/PreferencesCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/PreferencesCache.java @@ -67,10 +67,10 @@ public class PreferencesCache { /** * Tell the client to hide or show the coordinates. - * + *

* If {@link #prefersShowCoordinates} is true, coordinates will be shown, unless either of the following conditions apply:
*
- * {@link GeyserSession#reducedDebugInfo} is enabled + * {@link GeyserSession#isReducedDebugInfo()} is enabled * {@link GeyserConfiguration#isShowCoordinates()} is disabled */ public void updateShowCoordinates() { diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/SkullCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/SkullCache.java index d6e376d8f..5b208a41f 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/SkullCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/SkullCache.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.session.cache; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; @@ -247,7 +248,7 @@ public class SkullCache { lastPlayerPosition = null; } - private BlockDefinition translateCustomSkull(String skinHash, int blockState) { + private @Nullable BlockDefinition translateCustomSkull(String skinHash, int blockState) { CustomSkull customSkull = BlockRegistries.CUSTOM_SKULLS.get(skinHash); if (customSkull != null) { byte floorRotation = BlockStateValues.getSkullRotation(blockState); diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/WorldBorder.java b/core/src/main/java/org/geysermc/geyser/session/cache/WorldBorder.java index d9b9d8a54..8cb590f57 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/WorldBorder.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/WorldBorder.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.session.cache; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.GenericMath; import org.cloudburstmc.math.vector.Vector2d; import org.cloudburstmc.math.vector.Vector3f; @@ -37,13 +38,11 @@ import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.type.player.PlayerEntity; import org.geysermc.geyser.session.GeyserSession; -import javax.annotation.Nonnull; - public class WorldBorder { private static final double DEFAULT_WORLD_BORDER_SIZE = 5.9999968E7D; @Setter - private @Nonnull Vector2d center = Vector2d.ZERO; + private @NonNull Vector2d center = Vector2d.ZERO; /** * The diameter in blocks of the world border before it got changed or similar to newDiameter if not changed. */ diff --git a/core/src/main/java/org/geysermc/geyser/skin/FakeHeadProvider.java b/core/src/main/java/org/geysermc/geyser/skin/FakeHeadProvider.java index 95a2dcb1a..4ae30be19 100644 --- a/core/src/main/java/org/geysermc/geyser/skin/FakeHeadProvider.java +++ b/core/src/main/java/org/geysermc/geyser/skin/FakeHeadProvider.java @@ -34,13 +34,13 @@ import com.google.common.cache.LoadingCache; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; +import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.entity.type.LivingEntity; import org.geysermc.geyser.entity.type.player.PlayerEntity; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.GeyserLocale; -import javax.annotation.Nonnull; import java.awt.*; import java.awt.image.BufferedImage; import java.io.IOException; @@ -58,7 +58,7 @@ public class FakeHeadProvider { .maximumSize(10000) .build(new CacheLoader<>() { @Override - public SkinProvider.SkinData load(@Nonnull FakeHeadEntry fakeHeadEntry) throws Exception { + public SkinProvider.SkinData load(@NonNull FakeHeadEntry fakeHeadEntry) throws Exception { SkinProvider.SkinData skinData = SkinProvider.getOrDefault(SkinProvider.requestSkinData(fakeHeadEntry.getEntity()), null, 5); if (skinData == null) { diff --git a/core/src/main/java/org/geysermc/geyser/skin/SkinManager.java b/core/src/main/java/org/geysermc/geyser/skin/SkinManager.java index f7d6d7510..33a51fe8f 100644 --- a/core/src/main/java/org/geysermc/geyser/skin/SkinManager.java +++ b/core/src/main/java/org/geysermc/geyser/skin/SkinManager.java @@ -29,6 +29,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.data.skin.ImageData; import org.cloudburstmc.protocol.bedrock.data.skin.SerializedSkin; import org.cloudburstmc.protocol.bedrock.packet.PlayerListPacket; @@ -40,7 +41,6 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.auth.BedrockClientData; import org.geysermc.geyser.text.GeyserLocale; -import javax.annotation.Nullable; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.Base64; @@ -277,7 +277,7 @@ public class SkinManager { return null; } - public static GameProfileData loadFromJson(String encodedJson) throws IOException, IllegalArgumentException { + public static @Nullable GameProfileData loadFromJson(String encodedJson) throws IOException, IllegalArgumentException { JsonNode skinObject; try { skinObject = GeyserImpl.JSON_MAPPER.readTree(new String(Base64.getDecoder().decode(encodedJson), StandardCharsets.UTF_8)); diff --git a/core/src/main/java/org/geysermc/geyser/skin/SkinProvider.java b/core/src/main/java/org/geysermc/geyser/skin/SkinProvider.java index f491473be..23985c33f 100644 --- a/core/src/main/java/org/geysermc/geyser/skin/SkinProvider.java +++ b/core/src/main/java/org/geysermc/geyser/skin/SkinProvider.java @@ -32,6 +32,8 @@ import it.unimi.dsi.fastutil.bytes.ByteArrays; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.entity.type.player.PlayerEntity; @@ -40,8 +42,6 @@ import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.util.FileUtils; import org.geysermc.geyser.util.WebUtils; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; @@ -217,7 +217,7 @@ public class SkinProvider { /** * Used as a fallback if an official Java cape doesn't exist for this user. */ - @Nonnull + @NonNull private static Cape getCachedBedrockCape(UUID uuid) { GeyserSession session = GeyserImpl.getInstance().connectionByUuid(uuid); if (session != null) { @@ -545,7 +545,7 @@ public class SkinProvider { BufferedImage image = null; // First see if we have a cached file. We also update the modification stamp so we know when the file was last used - File imageFile = GeyserImpl.getInstance().getBootstrap().getConfigFolder().resolve("cache").resolve("images").resolve(UUID.nameUUIDFromBytes(imageUrl.getBytes()).toString() + ".png").toFile(); + File imageFile = GeyserImpl.getInstance().getBootstrap().getConfigFolder().resolve("cache").resolve("images").resolve(UUID.nameUUIDFromBytes(imageUrl.getBytes()) + ".png").toFile(); if (imageFile.exists()) { try { GeyserImpl.getInstance().getLogger().debug("Reading cached image from file " + imageFile.getPath() + " for " + imageUrl); @@ -617,7 +617,7 @@ public class SkinProvider { * @param uuid the player's UUID without any hyphens * @return a completable GameProfile with textures included */ - public static CompletableFuture requestTexturesFromUUID(String uuid) { + public static CompletableFuture<@Nullable String> requestTexturesFromUUID(String uuid) { return CompletableFuture.supplyAsync(() -> { try { JsonNode node = WebUtils.getJson("https://sessionserver.mojang.com/session/minecraft/profile/" + uuid); @@ -643,7 +643,7 @@ public class SkinProvider { * @param username the player's username * @return a completable GameProfile with textures included */ - public static CompletableFuture requestTexturesFromUsername(String username) { + public static CompletableFuture<@Nullable String> requestTexturesFromUsername(String username) { return CompletableFuture.supplyAsync(() -> { try { // Offline skin, or no present UUID @@ -669,20 +669,25 @@ public class SkinProvider { } private static BufferedImage downloadImage(String imageUrl, CapeProvider provider) throws IOException { - if (provider == CapeProvider.FIVEZIG) - return readFiveZigCape(imageUrl); + BufferedImage image; + if (provider == CapeProvider.FIVEZIG) { + image = readFiveZigCape(imageUrl); + } else { + HttpURLConnection con = (HttpURLConnection) new URL(imageUrl).openConnection(); + con.setRequestProperty("User-Agent", "Geyser-" + GeyserImpl.getInstance().getPlatformType().toString() + "/" + GeyserImpl.VERSION); + con.setConnectTimeout(10000); + con.setReadTimeout(10000); - HttpURLConnection con = (HttpURLConnection) new URL(imageUrl).openConnection(); - con.setRequestProperty("User-Agent", "Geyser-" + GeyserImpl.getInstance().getPlatformType().toString() + "/" + GeyserImpl.VERSION); - con.setConnectTimeout(10000); - con.setReadTimeout(10000); + image = ImageIO.read(con.getInputStream()); + } - BufferedImage image = ImageIO.read(con.getInputStream()); - if (image == null) throw new NullPointerException(); + if (image == null) { + throw new IllegalArgumentException("Failed to read image from: %s (cape provider=%s)".formatted(imageUrl, provider)); + } return image; } - private static BufferedImage readFiveZigCape(String url) throws IOException { + private static @Nullable BufferedImage readFiveZigCape(String url) throws IOException { JsonNode element = GeyserImpl.JSON_MAPPER.readTree(WebUtils.getBody(url)); if (element != null && element.isObject()) { JsonNode capeElement = element.get("d"); diff --git a/core/src/main/java/org/geysermc/geyser/text/AsteriskSerializer.java b/core/src/main/java/org/geysermc/geyser/text/AsteriskSerializer.java index 69dbb558e..702fded92 100644 --- a/core/src/main/java/org/geysermc/geyser/text/AsteriskSerializer.java +++ b/core/src/main/java/org/geysermc/geyser/text/AsteriskSerializer.java @@ -35,6 +35,7 @@ import com.fasterxml.jackson.databind.ser.ContextualSerializer; import com.fasterxml.jackson.databind.ser.std.StdSerializer; import java.io.IOException; +import java.io.Serial; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -43,6 +44,9 @@ import java.util.Optional; public class AsteriskSerializer extends StdSerializer implements ContextualSerializer { + @Serial + private static final long serialVersionUID = 1L; + public static final String[] NON_SENSITIVE_ADDRESSES = {"", "0.0.0.0", "localhost", "127.0.0.1", "auto", "unknown"}; public static boolean showSensitive = false; @@ -64,10 +68,6 @@ public class AsteriskSerializer extends StdSerializer implements Context String asterisk; boolean isIp; - public AsteriskSerializer() { - super(Object.class); - } - public AsteriskSerializer(String asterisk, boolean isIp) { super(Object.class); this.asterisk = asterisk; @@ -79,7 +79,7 @@ public class AsteriskSerializer extends StdSerializer implements Context Optional anno = Optional.ofNullable(property) .map(prop -> prop.getAnnotation(Asterisk.class)); - return new AsteriskSerializer(anno.map(Asterisk::value).orElse(null), anno.map(Asterisk::isIp).orElse(null)); + return new AsteriskSerializer(anno.map(Asterisk::value).orElse(null), anno.map(Asterisk::isIp).orElse(false)); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/text/ChatTypeEntry.java b/core/src/main/java/org/geysermc/geyser/text/ChatTypeEntry.java index 41528c1e4..500f44d0b 100644 --- a/core/src/main/java/org/geysermc/geyser/text/ChatTypeEntry.java +++ b/core/src/main/java/org/geysermc/geyser/text/ChatTypeEntry.java @@ -26,13 +26,12 @@ package org.geysermc.geyser.text; import com.github.steveice10.mc.protocol.data.game.chat.BuiltinChatType; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.packet.TextPacket; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public record ChatTypeEntry(@Nonnull TextPacket.Type bedrockChatType, @Nullable TextDecoration textDecoration) { +public record ChatTypeEntry(TextPacket.@NonNull Type bedrockChatType, @Nullable TextDecoration textDecoration) { private static final ChatTypeEntry CHAT = new ChatTypeEntry(TextPacket.Type.CHAT, null); private static final ChatTypeEntry RAW = new ChatTypeEntry(TextPacket.Type.RAW, null); diff --git a/core/src/main/java/org/geysermc/geyser/text/DummyLegacyHoverEventSerializer.java b/core/src/main/java/org/geysermc/geyser/text/DummyLegacyHoverEventSerializer.java index e934fc124..a6edffcd3 100644 --- a/core/src/main/java/org/geysermc/geyser/text/DummyLegacyHoverEventSerializer.java +++ b/core/src/main/java/org/geysermc/geyser/text/DummyLegacyHoverEventSerializer.java @@ -30,7 +30,7 @@ import net.kyori.adventure.text.Component; import net.kyori.adventure.text.event.HoverEvent; import net.kyori.adventure.text.serializer.json.LegacyHoverEventSerializer; import net.kyori.adventure.util.Codec; -import org.jetbrains.annotations.NotNull; +import org.checkerframework.checker.nullness.qual.NonNull; import java.nio.charset.StandardCharsets; import java.util.UUID; @@ -46,23 +46,23 @@ public final class DummyLegacyHoverEventSerializer implements LegacyHoverEventSe } @Override - public HoverEvent.@NotNull ShowItem deserializeShowItem(@NotNull Component input) { + public HoverEvent.@NonNull ShowItem deserializeShowItem(@NonNull Component input) { return dummyShowItem; } @Override - public HoverEvent.@NotNull ShowEntity deserializeShowEntity(@NotNull Component input, + public HoverEvent.@NonNull ShowEntity deserializeShowEntity(@NonNull Component input, Codec.Decoder componentDecoder) { return dummyShowEntity; } @Override - public @NotNull Component serializeShowItem(HoverEvent.@NotNull ShowItem input) { + public @NonNull Component serializeShowItem(HoverEvent.@NonNull ShowItem input) { return Component.empty(); } @Override - public @NotNull Component serializeShowEntity(HoverEvent.@NotNull ShowEntity input, + public @NonNull Component serializeShowEntity(HoverEvent.@NonNull ShowEntity input, Codec.Encoder componentEncoder) { return Component.empty(); } diff --git a/core/src/main/java/org/geysermc/geyser/text/GeyserLocale.java b/core/src/main/java/org/geysermc/geyser/text/GeyserLocale.java index 340674119..c6a58e75e 100644 --- a/core/src/main/java/org/geysermc/geyser/text/GeyserLocale.java +++ b/core/src/main/java/org/geysermc/geyser/text/GeyserLocale.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.text; import it.unimi.dsi.fastutil.objects.ObjectArrays; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; @@ -110,7 +111,7 @@ public class GeyserLocale { loadGeyserLocale(locale, geyser.getBootstrap()); } - private static String loadGeyserLocale(String locale, GeyserBootstrap bootstrap) { + private static @Nullable String loadGeyserLocale(String locale, GeyserBootstrap bootstrap) { locale = formatLocale(locale); // Don't load the locale if it's already loaded. if (LOCALE_MAPPINGS.containsKey(locale)) { diff --git a/core/src/main/java/org/geysermc/geyser/text/GsonComponentSerializerWrapper.java b/core/src/main/java/org/geysermc/geyser/text/GsonComponentSerializerWrapper.java index 2140dcc88..aaf100009 100644 --- a/core/src/main/java/org/geysermc/geyser/text/GsonComponentSerializerWrapper.java +++ b/core/src/main/java/org/geysermc/geyser/text/GsonComponentSerializerWrapper.java @@ -30,7 +30,7 @@ import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; -import org.jetbrains.annotations.NotNull; +import org.checkerframework.checker.nullness.qual.NonNull; import java.util.function.UnaryOperator; @@ -40,28 +40,28 @@ import java.util.function.UnaryOperator; public record GsonComponentSerializerWrapper(GsonComponentSerializer source) implements GsonComponentSerializer { @Override - public @NotNull Gson serializer() { + public @NonNull Gson serializer() { return this.source.serializer(); } @Override - public @NotNull UnaryOperator populator() { + public @NonNull UnaryOperator populator() { return this.source.populator(); } @Override - public @NotNull Component deserializeFromTree(@NotNull JsonElement input) { + public @NonNull Component deserializeFromTree(@NonNull JsonElement input) { // This has yet to be an issue, so it won't be overridden unless we have to return this.source.deserializeFromTree(input); } @Override - public @NotNull JsonElement serializeToTree(@NotNull Component component) { + public @NonNull JsonElement serializeToTree(@NonNull Component component) { return this.source.serializeToTree(component); } @Override - public @NotNull Component deserialize(@NotNull String input) { + public @NonNull Component deserialize(@NonNull String input) { // See https://github.com/KyoriPowered/adventure/issues/447 Component component = this.serializer().fromJson(input, Component.class); if (component == null) { @@ -72,12 +72,12 @@ public record GsonComponentSerializerWrapper(GsonComponentSerializer source) imp } @Override - public @NotNull String serialize(@NotNull Component component) { + public @NonNull String serialize(@NonNull Component component) { return this.source.serialize(component); } @Override - public @NotNull Builder toBuilder() { + public @NonNull Builder toBuilder() { return this.source.toBuilder(); } } diff --git a/core/src/main/java/org/geysermc/geyser/text/MinecraftLocale.java b/core/src/main/java/org/geysermc/geyser/text/MinecraftLocale.java index 00866eda3..fa1b322a5 100644 --- a/core/src/main/java/org/geysermc/geyser/text/MinecraftLocale.java +++ b/core/src/main/java/org/geysermc/geyser/text/MinecraftLocale.java @@ -26,12 +26,12 @@ package org.geysermc.geyser.text; import com.fasterxml.jackson.databind.JsonNode; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.util.AssetUtils; import org.geysermc.geyser.util.FileUtils; import org.geysermc.geyser.util.WebUtils; -import javax.annotation.Nullable; import java.io.*; import java.nio.file.Files; import java.nio.file.Path; @@ -217,8 +217,7 @@ public class MinecraftLocale { * @param locale Locale to translate to * @return Translated string or null if it was not found in the given locale */ - @Nullable - public static String getLocaleStringIfPresent(String messageText, String locale) { + public static @Nullable String getLocaleStringIfPresent(String messageText, String locale) { Map localeStrings = LOCALE_MAPPINGS.get(locale.toLowerCase(Locale.ROOT)); if (localeStrings != null) { return localeStrings.get(messageText); diff --git a/core/src/main/java/org/geysermc/geyser/text/MinecraftTranslationRegistry.java b/core/src/main/java/org/geysermc/geyser/text/MinecraftTranslationRegistry.java index 3310859d0..b59b4db8e 100644 --- a/core/src/main/java/org/geysermc/geyser/text/MinecraftTranslationRegistry.java +++ b/core/src/main/java/org/geysermc/geyser/text/MinecraftTranslationRegistry.java @@ -26,9 +26,9 @@ package org.geysermc.geyser.text; import net.kyori.adventure.text.renderer.TranslatableComponentRenderer; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.text.MessageFormat; import java.util.Locale; import java.util.regex.Matcher; @@ -44,12 +44,12 @@ public class MinecraftTranslationRegistry extends TranslatableComponentRenderer< // Exists to maintain compatibility with Velocity's older Adventure version @Override - public @Nullable MessageFormat translate(@Nonnull String key, @Nonnull String locale) { + public @Nullable MessageFormat translate(@NonNull String key, @NonNull String locale) { return this.translate(key, null, locale); } @Override - protected @Nullable MessageFormat translate(@Nonnull String key, @Nullable String fallback, @Nonnull String locale) { + protected @Nullable MessageFormat translate(@NonNull String key, @Nullable String fallback, @NonNull String locale) { // Get the locale string String localeString = MinecraftLocale.getLocaleStringIfPresent(key, locale); if (localeString == null) { @@ -66,7 +66,7 @@ public class MinecraftTranslationRegistry extends TranslatableComponentRenderer< // Replace the `%s` with numbered inserts `{0}` Pattern p = stringReplacement; Matcher m = p.matcher(localeString); - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); int i = 0; while (m.find()) { m.appendReplacement(sb, "{" + (i++) + "}"); @@ -76,7 +76,7 @@ public class MinecraftTranslationRegistry extends TranslatableComponentRenderer< // Replace the `%x$s` with numbered inserts `{x}` p = positionalStringReplacement; m = p.matcher(sb.toString()); - sb = new StringBuffer(); + sb = new StringBuilder(); while (m.find()) { i = Integer.parseInt(m.group(1)) - 1; m.appendReplacement(sb, "{" + i + "}"); diff --git a/core/src/main/java/org/geysermc/geyser/translator/collision/BlockCollision.java b/core/src/main/java/org/geysermc/geyser/translator/collision/BlockCollision.java index f7e39718b..e82b994c7 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/collision/BlockCollision.java +++ b/core/src/main/java/org/geysermc/geyser/translator/collision/BlockCollision.java @@ -54,7 +54,7 @@ public class BlockCollision { /** * This is used to control the maximum distance a face of a bounding box can push the player away */ - protected double pushAwayTolerance = CollisionManager.COLLISION_TOLERANCE * 1.1; + protected final double pushAwayTolerance = CollisionManager.COLLISION_TOLERANCE * 1.1; protected BlockCollision(BoundingBox[] boxes) { this.boundingBoxes = boxes; diff --git a/core/src/main/java/org/geysermc/geyser/translator/collision/SpawnerCollision.java b/core/src/main/java/org/geysermc/geyser/translator/collision/SpawnerCollision.java deleted file mode 100644 index 7d4dfedc2..000000000 --- a/core/src/main/java/org/geysermc/geyser/translator/collision/SpawnerCollision.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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.translator.collision; - -import lombok.EqualsAndHashCode; - -@EqualsAndHashCode(callSuper = true) -@CollisionRemapper(regex = "^spawner$") -public class SpawnerCollision extends SolidCollision { - public SpawnerCollision(String params) { - super(params); - // Increase pushAwayTolerance to work around https://bugs.mojang.com/browse/MCPE-41996 - pushAwayTolerance = 0.0002; - } -} diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java index 106613e25..5262f048b 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java @@ -129,7 +129,7 @@ public abstract class InventoryTranslator { /** * Should be overwritten in cases where specific inventories should reject an item being in a specific spot. * For examples, looms use this to reject items that are dyes in Bedrock but not in Java. - * + *

* The source/destination slot will be -1 if the cursor is the slot * * @return true if this transfer should be rejected 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 336809e8a..856b22c9b 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 @@ -68,7 +68,6 @@ import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.translator.text.MessageTranslator; -import javax.annotation.Nonnull; import java.text.DecimalFormat; import java.util.*; @@ -98,7 +97,7 @@ public final class ItemTranslator { ItemStack itemStack = javaItem.translateToJava(data, bedrockItem, mappings); - if (itemStack != null && itemStack.getNbt() != null) { + if (itemStack.getNbt() != null) { javaItem.translateNbtToJava(itemStack.getNbt(), bedrockItem); if (itemStack.getNbt().isEmpty()) { // Otherwise, seems to cause issues with villagers accepting books, and I don't see how this will break anything else. - Camotoy @@ -108,8 +107,7 @@ public final class ItemTranslator { return itemStack; } - @Nonnull - public static ItemData.Builder translateToBedrock(GeyserSession session, int javaId, int count, CompoundTag tag) { + public static ItemData.@NonNull Builder translateToBedrock(GeyserSession session, int javaId, int count, CompoundTag tag) { ItemMapping bedrockItem = session.getItemMappings().getMapping(javaId); if (bedrockItem == ItemMapping.AIR) { session.getGeyser().getLogger().debug("ItemMapping returned air: " + javaId); @@ -118,7 +116,7 @@ public final class ItemTranslator { return translateToBedrock(session, Registries.JAVA_ITEMS.get().get(javaId), bedrockItem, count, tag); } - @Nonnull + @NonNull public static ItemData translateToBedrock(GeyserSession session, ItemStack stack) { if (stack == null) { return ItemData.AIR; @@ -134,8 +132,7 @@ public final class ItemTranslator { .build(); } - @Nonnull - private static ItemData.Builder translateToBedrock(GeyserSession session, Item javaItem, ItemMapping bedrockItem, int count, CompoundTag tag) { + private static ItemData.@NonNull Builder translateToBedrock(GeyserSession session, Item javaItem, ItemMapping bedrockItem, int count, CompoundTag tag) { CompoundTag nbt = tag != null ? tag.clone() : null; if (nbt != null) { @@ -365,7 +362,7 @@ public final class ItemTranslator { * @param canModifyJava the list of items in Java * @return the new list of items in Bedrock */ - private static String[] getCanModify(ListTag canModifyJava) { + private static String @Nullable [] getCanModify(ListTag canModifyJava) { if (canModifyJava != null && canModifyJava.size() > 0) { String[] canModifyBedrock = new String[canModifyJava.size()]; for (int i = 0; i < canModifyBedrock.length; i++) { @@ -384,7 +381,7 @@ public final class ItemTranslator { * Given an item stack, determine the Bedrock item definition that should be applied to Bedrock players. */ @NonNull - public static ItemDefinition getBedrockItemDefinition(GeyserSession session, @Nonnull GeyserItemStack itemStack) { + public static ItemDefinition getBedrockItemDefinition(GeyserSession session, @NonNull GeyserItemStack itemStack) { if (itemStack.isEmpty()) { return ItemDefinition.AIR; } @@ -429,7 +426,7 @@ public final class ItemTranslator { return NbtMap.EMPTY; } - private static Object translateToBedrockNBT(Tag tag) { + private static @Nullable Object translateToBedrockNBT(Tag tag) { if (tag instanceof CompoundTag compoundTag) { return translateNbtToBedrock(compoundTag); } @@ -443,6 +440,7 @@ public final class ItemTranslator { if (!tagList.isEmpty()) { type = NbtType.byClass(tagList.get(0).getClass()); } + //noinspection unchecked,rawtypes return new NbtList(type, tagList); } @@ -473,7 +471,7 @@ public final class ItemTranslator { return javaTag; } - private static Tag translateToJavaNBT(String name, Object object) { + private static @Nullable Tag translateToJavaNBT(String name, Object object) { if (object instanceof int[]) { return new IntArrayTag(name, (int[]) object); } @@ -610,7 +608,7 @@ public final class ItemTranslator { builder.blockDefinition(blockDefinition); } - private static CustomSkull getCustomSkull(GeyserSession session, CompoundTag nbt) { + private static @Nullable CustomSkull getCustomSkull(GeyserSession session, CompoundTag nbt) { if (nbt != null && nbt.contains("SkullOwner")) { if (!(nbt.get("SkullOwner") instanceof CompoundTag skullOwner)) { // It's a username give up d: 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 c43dfe8bc..07b075690 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 @@ -25,6 +25,7 @@ package org.geysermc.geyser.translator.level.block.entity; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtList; import org.cloudburstmc.nbt.NbtMap; @@ -57,7 +58,7 @@ public interface BedrockOnlyBlockEntity extends RequiresBlockState { * @param blockState Java BlockState of block. * @return Bedrock tag, or null if not a Bedrock-only Block Entity */ - static NbtMap getTag(GeyserSession session, Vector3i position, int blockState) { + static @Nullable NbtMap getTag(GeyserSession session, Vector3i position, int blockState) { if (FlowerPotBlockEntityTranslator.isFlowerBlock(blockState)) { return FlowerPotBlockEntityTranslator.getTag(session, blockState, position); } else if (PistonBlockEntityTranslator.isBlock(blockState)) { diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/ShulkerBoxBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/ShulkerBoxBlockEntityTranslator.java index db7b3073f..bbe6a0725 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/ShulkerBoxBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/ShulkerBoxBlockEntityTranslator.java @@ -27,12 +27,11 @@ package org.geysermc.geyser.translator.level.block.entity; import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.translator.inventory.ShulkerInventoryTranslator; -import javax.annotation.Nullable; - @BlockEntity(type = BlockEntityType.SHULKER_BOX) public class ShulkerBoxBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState { /** diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java index 7f87f9465..9ac9126db 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java @@ -30,6 +30,7 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.IntArrayTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket; import org.geysermc.geyser.GeyserImpl; @@ -99,7 +100,7 @@ public class SkullBlockEntityTranslator extends BlockEntityTranslator implements return CompletableFuture.completedFuture(texture.getValue()); } - public static BlockDefinition translateSkull(GeyserSession session, CompoundTag tag, Vector3i blockPosition, int blockState) { + public static @Nullable BlockDefinition translateSkull(GeyserSession session, CompoundTag tag, Vector3i blockPosition, int blockState) { CompoundTag owner = tag.get("SkullOwner"); if (owner == null) { session.getSkullCache().removeSkull(blockPosition); 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 bf437311d..29a78daf3 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 @@ -635,16 +635,16 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator * The position between the intended click position and the player can be determined with two triangles. * First, we compute the difference of the X and Z coordinates: - * + *

* Player position (0, 0) * | * | * | * |_____________ Intended target (-3, 2) - * + *

* We then use the Pythagorean Theorem to find the direct line (hypotenuse) on the XZ plane. Finding the angle of the * triangle from there, closest to the player, gives us our yaw rotation value * Then doing the same using the new XZ distance and Y difference, we can find the direct line of sight from the diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockItemFrameDropItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockItemFrameDropItemTranslator.java index f11fd202c..8632dc4e1 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockItemFrameDropItemTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockItemFrameDropItemTranslator.java @@ -37,7 +37,7 @@ import org.geysermc.geyser.translator.protocol.Translator; /** * Pre-1.16.210: used for both survival and creative item frame item removal - * + *

* 1.16.210: only used in creative. */ @Translator(packet = ItemFrameDropItemPacket.class) diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/BedrockEntityEventTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/BedrockEntityEventTranslator.java index 58d5c2018..17a80aa39 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/BedrockEntityEventTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/BedrockEntityEventTranslator.java @@ -60,6 +60,6 @@ public class BedrockEntityEventTranslator extends PacketTranslatorissue 3411. Not a perfect solution. */ private static String getEnumDataName(CommandNode node) { if (node.getProperties() instanceof ResourceProperties properties) { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginDisconnectTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginDisconnectTranslator.java index 56309c058..daf42a68e 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginDisconnectTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginDisconnectTranslator.java @@ -83,8 +83,8 @@ public class JavaLoginDisconnectTranslator extends PacketTranslator children = component.children(); - for (int i = 0; i < children.size(); i++) { - if (children.get(i) instanceof TextComponent child && child.content().startsWith("Outdated server!")) { + for (Component value : children) { + if (value instanceof TextComponent child && child.content().startsWith("Outdated server!")) { // Reproduced on Paper 1.17.1 return true; } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java index 71cb6019a..344e06c96 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java @@ -68,6 +68,7 @@ import static org.geysermc.geyser.util.InventoryUtils.LAST_RECIPE_NET_ID; /** * Used to send all valid recipes from Java to Bedrock. + *

* Bedrock REQUIRES a CraftingDataPacket to be sent in order to craft anything. */ @Translator(packet = ClientboundUpdateRecipesPacket.class) diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaAnimateTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaAnimateTranslator.java index 7df6b710c..1aa147314 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaAnimateTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaAnimateTranslator.java @@ -56,13 +56,13 @@ public class JavaAnimateTranslator extends PacketTranslator { animatePacket.setAction(AnimatePacket.Action.SWING_ARM); if (entity.getEntityId() == session.getPlayerEntity().getEntityId()) { session.activateArmAnimationTicking(); } - break; - case SWING_OFFHAND: + } + case SWING_OFFHAND -> { // Use the OptionalPack to trigger the animation AnimateEntityPacket offHandPacket = new AnimateEntityPacket(); offHandPacket.setAnimation("animation.player.attack.rotations.offhand"); @@ -71,14 +71,13 @@ public class JavaAnimateTranslator extends PacketTranslator animatePacket.setAction(AnimatePacket.Action.CRITICAL_HIT); + case ENCHANTMENT_CRITICAL_HIT -> { animatePacket.setAction(AnimatePacket.Action.MAGIC_CRITICAL_HIT); // Unsure if this does anything + // Spawn custom particle SpawnParticleEffectPacket stringPacket = new SpawnParticleEffectPacket(); stringPacket.setIdentifier("geyseropt:enchanted_hit_multiple"); @@ -87,13 +86,12 @@ public class JavaAnimateTranslator extends PacketTranslator animatePacket.setAction(AnimatePacket.Action.WAKE_UP); + default -> { session.getGeyser().getLogger().debug("Unhandled java animation: " + animation); return; + } } session.sendUpstreamPacket(animatePacket); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaTakeItemEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaTakeItemEntityTranslator.java index 3b93f0df8..cc2b4b030 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaTakeItemEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaTakeItemEntityTranslator.java @@ -27,7 +27,6 @@ package org.geysermc.geyser.translator.protocol.java.entity; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundTakeItemEntityPacket; import org.cloudburstmc.protocol.bedrock.data.LevelEvent; -import org.cloudburstmc.protocol.bedrock.data.LevelEventType; import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket; import org.cloudburstmc.protocol.bedrock.packet.TakeItemEntityPacket; import org.geysermc.geyser.entity.type.Entity; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerCombatKillTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerCombatKillTranslator.java index 4e8bd89b3..4b0cafed3 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerCombatKillTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerCombatKillTranslator.java @@ -28,7 +28,6 @@ package org.geysermc.geyser.translator.protocol.java.entity.player; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.player.ClientboundPlayerCombatKillPacket; import org.cloudburstmc.protocol.bedrock.packet.DeathInfoPacket; import net.kyori.adventure.text.Component; -import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockDestructionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockDestructionTranslator.java index fc5d69443..49d043c62 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockDestructionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockDestructionTranslator.java @@ -28,7 +28,6 @@ package org.geysermc.geyser.translator.protocol.java.level; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundBlockDestructionPacket; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.cloudburstmc.protocol.bedrock.data.LevelEvent; -import org.cloudburstmc.protocol.bedrock.data.LevelEventType; import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.type.ItemMapping; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelParticlesTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelParticlesTranslator.java index 6adb053d7..11d9dbddf 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelParticlesTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelParticlesTranslator.java @@ -35,6 +35,7 @@ import com.github.steveice10.mc.protocol.data.game.level.particle.VibrationParti import com.github.steveice10.mc.protocol.data.game.level.particle.positionsource.BlockPositionSource; import com.github.steveice10.mc.protocol.data.game.level.particle.positionsource.EntityPositionSource; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundLevelParticlesPacket; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.LevelEvent; @@ -92,7 +93,7 @@ public class JavaLevelParticlesTranslator extends PacketTranslator createParticle(GeyserSession session, Particle particle) { + private @Nullable Function createParticle(GeyserSession session, Particle particle) { switch (particle.getType()) { case BLOCK -> { int blockState = session.getBlockMappings().getBedrockBlockId(((BlockParticleData) particle.getData()).getBlockState()); diff --git a/core/src/main/java/org/geysermc/geyser/translator/sound/SoundTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/sound/SoundTranslator.java index 0146c534e..7b42790ac 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/sound/SoundTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/sound/SoundTranslator.java @@ -38,7 +38,7 @@ public @interface SoundTranslator { /** * The identifier(s) that the placed block must contain * one of. Leave empty to ignore. - * + *

* Only applies to interaction handlers that are an * instance of {@link BlockSoundInteractionTranslator}. * diff --git a/core/src/main/java/org/geysermc/geyser/translator/sound/block/ComparatorSoundInteractionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/sound/block/ComparatorSoundInteractionTranslator.java index 450078362..e77539e6e 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/sound/block/ComparatorSoundInteractionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/sound/block/ComparatorSoundInteractionTranslator.java @@ -27,7 +27,6 @@ package org.geysermc.geyser.translator.sound.block; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.LevelEvent; -import org.cloudburstmc.protocol.bedrock.data.LevelEventType; import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.sound.BlockSoundInteractionTranslator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/sound/block/DoorSoundInteractionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/sound/block/DoorSoundInteractionTranslator.java index 107807fe0..8f8ab8bf6 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/sound/block/DoorSoundInteractionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/sound/block/DoorSoundInteractionTranslator.java @@ -27,7 +27,6 @@ package org.geysermc.geyser.translator.sound.block; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.LevelEvent; -import org.cloudburstmc.protocol.bedrock.data.LevelEventType; import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.sound.BlockSoundInteractionTranslator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/sound/block/LeverSoundInteractionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/sound/block/LeverSoundInteractionTranslator.java index 08a8792e8..17b8768bc 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/sound/block/LeverSoundInteractionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/sound/block/LeverSoundInteractionTranslator.java @@ -27,7 +27,6 @@ package org.geysermc.geyser.translator.sound.block; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.LevelEvent; -import org.cloudburstmc.protocol.bedrock.data.LevelEventType; import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.sound.BlockSoundInteractionTranslator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java index 5f811ab49..d93123cff 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java @@ -201,7 +201,7 @@ public class MessageTranslator { /** * Verifies the message is valid JSON in case it's plaintext. Works around GsonComponentSerializer not using lenient mode. - * See https://wiki.vg/Chat for messages sent in lenient mode, and for a description on leniency. + * See here for messages sent in lenient mode, and for a description on leniency. * * @param message Potentially lenient JSON message * @param locale Locale to use for translation strings diff --git a/core/src/main/java/org/geysermc/geyser/util/AttributeUtils.java b/core/src/main/java/org/geysermc/geyser/util/AttributeUtils.java index 17502eae8..e1fe6e6f2 100644 --- a/core/src/main/java/org/geysermc/geyser/util/AttributeUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/AttributeUtils.java @@ -32,7 +32,7 @@ import com.github.steveice10.mc.protocol.data.game.entity.attribute.ModifierOper public class AttributeUtils { /** * Retrieve the base attribute value with all modifiers applied. - * https://minecraft.wiki/w/Attribute#Modifiers + * See here * @param attribute The attribute to calculate the total value. * @return The finished attribute with all modifiers applied. */ diff --git a/core/src/main/java/org/geysermc/geyser/util/BlockEntityUtils.java b/core/src/main/java/org/geysermc/geyser/util/BlockEntityUtils.java index 9964ed08b..31a2ddee9 100644 --- a/core/src/main/java/org/geysermc/geyser/util/BlockEntityUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/BlockEntityUtils.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.util; import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; +import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket; @@ -35,7 +36,6 @@ import org.geysermc.geyser.translator.level.block.entity.BedrockOnlyBlockEntity; import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator; import org.geysermc.geyser.translator.level.block.entity.FlowerPotBlockEntityTranslator; -import javax.annotation.Nonnull; import java.util.List; import java.util.Locale; import java.util.Map; @@ -83,7 +83,7 @@ public class BlockEntityUtils { return Registries.BLOCK_ENTITIES.get(type); } - public static void updateBlockEntity(GeyserSession session, @Nonnull NbtMap blockEntity, Vector3i position) { + public static void updateBlockEntity(GeyserSession session, @NonNull NbtMap blockEntity, Vector3i position) { BlockEntityDataPacket blockEntityPacket = new BlockEntityDataPacket(); blockEntityPacket.setBlockPosition(position); blockEntityPacket.setData(blockEntity); diff --git a/core/src/main/java/org/geysermc/geyser/util/BlockUtils.java b/core/src/main/java/org/geysermc/geyser/util/BlockUtils.java index 23949d020..81a67a521 100644 --- a/core/src/main/java/org/geysermc/geyser/util/BlockUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/BlockUtils.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.util; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3i; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.PlayerInventory; @@ -36,8 +37,6 @@ import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.collision.BlockCollision; -import javax.annotation.Nullable; - public final class BlockUtils { private static boolean correctTool(GeyserSession session, BlockMapping blockMapping, String itemToolType) { diff --git a/core/src/main/java/org/geysermc/geyser/util/CooldownUtils.java b/core/src/main/java/org/geysermc/geyser/util/CooldownUtils.java index c00e389fd..60838686f 100644 --- a/core/src/main/java/org/geysermc/geyser/util/CooldownUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/CooldownUtils.java @@ -35,7 +35,7 @@ import java.util.concurrent.TimeUnit; /** * Manages the sending of a cooldown indicator to the Bedrock player as there is no cooldown indicator in Bedrock. - * Much of the work here is from the wonderful folks from ViaRewind: https://github.com/ViaVersion/ViaRewind + * Much of the work here is from the wonderful folks from ViaRewind */ public class CooldownUtils { private static CooldownType DEFAULT_SHOW_COOLDOWN; diff --git a/core/src/main/java/org/geysermc/geyser/util/CpuUtils.java b/core/src/main/java/org/geysermc/geyser/util/CpuUtils.java index 622722e5a..9f7bd9e61 100644 --- a/core/src/main/java/org/geysermc/geyser/util/CpuUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/CpuUtils.java @@ -49,7 +49,7 @@ public final class CpuUtils { /** * Much of the code here was copied from the OSHI project. This is simply stripped down to only get the CPU model. - * https://github.com/oshi/oshi/ + * See here */ private static String getLinuxProcessorName() throws Exception { List lines = Files.readAllLines(Paths.get("/proc/cpuinfo"), StandardCharsets.UTF_8); @@ -64,7 +64,7 @@ public final class CpuUtils { } /** - * https://stackoverflow.com/a/6327663 + * See here */ private static String getWindowsProcessorName() throws Exception { final String cpuNameCmd = "reg query \"HKLM\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\" /v ProcessorNameString"; @@ -83,7 +83,7 @@ public final class CpuUtils { int p = result.indexOf(regstrToken); if (p == -1) { - return null; + return "unknown"; } return result.substring(p + regstrToken.length()).trim(); diff --git a/core/src/main/java/org/geysermc/geyser/util/FileUtils.java b/core/src/main/java/org/geysermc/geyser/util/FileUtils.java index 99e8f8d7d..c8cd31058 100644 --- a/core/src/main/java/org/geysermc/geyser/util/FileUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/FileUtils.java @@ -79,7 +79,7 @@ public class FileUtils { //noinspection ResultOfMethodCallIgnored file.createNewFile(); try (FileOutputStream fos = new FileOutputStream(file)) { - try (InputStream input = bootstrap.getResource(name)) { + try (InputStream input = bootstrap.getResourceOrThrow(name)) { byte[] bytes = new byte[input.available()]; //noinspection ResultOfMethodCallIgnored @@ -170,7 +170,7 @@ public class FileUtils { * @return the byte array of an InputStream */ public static byte[] readAllBytes(String resource) { - try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResource(resource)) { + try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow(resource)) { return stream.readAllBytes(); } catch (IOException e) { throw new RuntimeException("Error while trying to read internal input stream!", e); @@ -225,7 +225,7 @@ public class FileUtils { * @return a set of all the classes annotated by the given annotation */ public static Set> getGeneratedClassesForAnnotation(String input) { - try (InputStream annotatedClass = GeyserImpl.getInstance().getBootstrap().getResource(input); + try (InputStream annotatedClass = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow(input); BufferedReader reader = new BufferedReader(new InputStreamReader(annotatedClass))) { return reader.lines().map(className -> { try { diff --git a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java index 0348eca11..f1bf03d90 100644 --- a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java @@ -31,6 +31,7 @@ import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundPickItemPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundSetCreativeModeSlotPacket; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; @@ -53,6 +54,7 @@ import org.geysermc.geyser.item.Items; import org.geysermc.geyser.level.BedrockDimension; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.type.ItemMapping; +import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.GeyserLocale; @@ -60,7 +62,6 @@ import org.geysermc.geyser.translator.inventory.InventoryTranslator; import org.geysermc.geyser.translator.inventory.LecternInventoryTranslator; import org.geysermc.geyser.translator.inventory.chest.DoubleChestInventoryTranslator; -import javax.annotation.Nullable; import java.util.Arrays; import java.util.Collections; import java.util.Objects; @@ -129,7 +130,7 @@ public class InventoryUtils { session.setOpenInventory(null); } - public static Inventory getInventory(GeyserSession session, int javaId) { + public static @Nullable Inventory getInventory(GeyserSession session, int javaId) { if (javaId == 0) { return session.getPlayerInventory(); } else { @@ -207,12 +208,13 @@ public class InventoryUtils { } private static ItemDefinition getUnusableSpaceBlockDefinition(int protocolVersion) { + ItemMappings mappings = Registries.ITEMS.forVersion(protocolVersion); String unusableSpaceBlock = GeyserImpl.getInstance().getConfig().getUnusableSpaceBlock(); - ItemDefinition itemDefinition = Registries.ITEMS.forVersion(protocolVersion).getDefinition(unusableSpaceBlock); + ItemDefinition itemDefinition = mappings.getDefinition(unusableSpaceBlock); if (itemDefinition == null) { GeyserImpl.getInstance().getLogger().error("Invalid value " + unusableSpaceBlock + ". Resorting to barrier block."); - return Registries.ITEMS.forVersion(protocolVersion).getStoredItems().barrier().getBedrockDefinition(); + return mappings.getStoredItems().barrier().getBedrockDefinition(); } else { return itemDefinition; } @@ -284,7 +286,7 @@ public class InventoryUtils { * If it is found in another part of the inventory, move it. * If it is not found and the user is in creative mode, create the item, * overriding the current item slot if no other hotbar slots are empty, or otherwise selecting the empty slot. - * + *

* This attempts to mimic Java Edition behavior as best as it can. * @param session the Bedrock client's session * @param itemName the Java identifier of the item to search/select @@ -455,6 +457,7 @@ public class InventoryUtils { for (int col = firstCol; col < width + firstCol; col++) { GeyserItemStack geyserItemStack = inventoryGetter.apply(col + (row * gridDimensions) + 1); if (geyserItemStack.isEmpty()) { + //noinspection ConstantValue inventoryHasItem = itemStack == null || itemStack.getId() == 0; if (inventoryHasItem) { break crafting; @@ -476,6 +479,7 @@ public class InventoryUtils { return null; } + @SuppressWarnings("BooleanMethodIsAlwaysInverted") private static boolean testShapedRecipe(final Ingredient[] ingredients, final IntFunction inventoryGetter, final int gridDimensions, final int firstRow, final int height, final int firstCol, final int width) { int ingredientIndex = 0; diff --git a/core/src/main/java/org/geysermc/geyser/util/ItemUtils.java b/core/src/main/java/org/geysermc/geyser/util/ItemUtils.java index c528de741..a116c5cf2 100644 --- a/core/src/main/java/org/geysermc/geyser/util/ItemUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/ItemUtils.java @@ -29,12 +29,11 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.Tag; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.FishingRodItem; import org.geysermc.geyser.item.type.Item; -import javax.annotation.Nullable; - public class ItemUtils { public static int getEnchantmentLevel(@Nullable CompoundTag itemNBTData, String enchantmentId) { @@ -74,7 +73,7 @@ public class ItemUtils { * @param itemTag the NBT tag of the item * @return the custom name of the item */ - public static String getCustomName(CompoundTag itemTag) { + public static @Nullable String getCustomName(CompoundTag itemTag) { if (itemTag != null) { if (itemTag.get("display") instanceof CompoundTag displayTag) { if (displayTag.get("Name") instanceof StringTag nameTag) { diff --git a/core/src/main/java/org/geysermc/geyser/util/JavaCodecUtil.java b/core/src/main/java/org/geysermc/geyser/util/JavaCodecUtil.java index f0b8ee6bc..795d45490 100644 --- a/core/src/main/java/org/geysermc/geyser/util/JavaCodecUtil.java +++ b/core/src/main/java/org/geysermc/geyser/util/JavaCodecUtil.java @@ -28,8 +28,8 @@ package org.geysermc.geyser.util; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.Tag; +import org.checkerframework.checker.nullness.qual.NonNull; -import javax.annotation.Nonnull; import java.util.Iterator; public final class JavaCodecUtil { @@ -41,7 +41,7 @@ public final class JavaCodecUtil { ListTag value = tag.get("value"); Iterator originalIterator = value.iterator(); return new Iterable<>() { - @Nonnull + @NonNull @Override public Iterator iterator() { return new Iterator<>() { diff --git a/core/src/main/java/org/geysermc/geyser/util/Metrics.java b/core/src/main/java/org/geysermc/geyser/util/Metrics.java index e88d5a971..a4ef301e3 100644 --- a/core/src/main/java/org/geysermc/geyser/util/Metrics.java +++ b/core/src/main/java/org/geysermc/geyser/util/Metrics.java @@ -29,6 +29,8 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.GeyserImpl; import javax.net.ssl.HttpsURLConnection; @@ -48,8 +50,8 @@ import java.util.zip.GZIPOutputStream; /** * bStats collects some data for plugin authors. - * - * Check out https://bStats.org/ to learn more about bStats! + *

+ * Check out bStats to learn more about bStats! */ public class Metrics { @@ -140,7 +142,7 @@ public class Metrics { } customCharts.add(chart); } - data.put("customCharts", customCharts); + data.set("customCharts", customCharts); return data; } @@ -233,10 +235,7 @@ public class Metrics { * @return The gzipped String. * @throws IOException If the compression failed. */ - private static byte[] compress(final String str) throws IOException { - if (str == null) { - return null; - } + private static byte @NonNull [] compress(final @NonNull String str) throws IOException { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); GZIPOutputStream gzip = new GZIPOutputStream(outputStream); gzip.write(str.getBytes(StandardCharsets.UTF_8)); @@ -264,7 +263,7 @@ public class Metrics { this.chartId = chartId; } - private ObjectNode getRequestJsonNode() { + private @Nullable ObjectNode getRequestJsonNode() { ObjectNode chart = new ObjectMapper().createObjectNode(); chart.put("chartId", chartId); try { @@ -308,7 +307,7 @@ public class Metrics { } @Override - protected ObjectNode getChartData() throws Exception { + protected @Nullable ObjectNode getChartData() throws Exception { ObjectNode data = mapper.createObjectNode(); String value = callable.call(); if (value == null || value.isEmpty()) { @@ -339,7 +338,7 @@ public class Metrics { } @Override - protected ObjectNode getChartData() throws Exception { + protected @Nullable ObjectNode getChartData() throws Exception { ObjectNode data = mapper.createObjectNode(); ObjectNode values = mapper.createObjectNode(); Map map = callable.call(); @@ -383,7 +382,7 @@ public class Metrics { } @Override - public ObjectNode getChartData() throws Exception { + public @Nullable ObjectNode getChartData() throws Exception { ObjectNode data = mapper.createObjectNode(); ObjectNode values = mapper.createObjectNode(); Map> map = callable.call(); @@ -432,7 +431,7 @@ public class Metrics { } @Override - protected ObjectNode getChartData() throws Exception { + protected @Nullable ObjectNode getChartData() throws Exception { ObjectNode data = mapper.createObjectNode(); int value = callable.call(); if (value == 0) { @@ -445,135 +444,4 @@ public class Metrics { } - /** - * Represents a custom multi line chart. - */ - public static class MultiLineChart extends CustomChart { - - private final Callable> callable; - - /** - * Class constructor. - * - * @param chartId The id of the chart. - * @param callable The callable which is used to request the chart data. - */ - public MultiLineChart(String chartId, Callable> callable) { - super(chartId); - this.callable = callable; - } - - @Override - protected ObjectNode getChartData() throws Exception { - ObjectNode data = mapper.createObjectNode(); - ObjectNode values = mapper.createObjectNode(); - Map map = callable.call(); - if (map == null || map.isEmpty()) { - // Null = skip the chart - return null; - } - boolean allSkipped = true; - for (Map.Entry entry : map.entrySet()) { - if (entry.getValue() == 0) { - continue; // Skip this invalid - } - allSkipped = false; - values.put(entry.getKey(), entry.getValue()); - } - if (allSkipped) { - // Null = skip the chart - return null; - } - data.putPOJO("values", values); - return data; - } - - } - - /** - * Represents a custom simple bar chart. - */ - public static class SimpleBarChart extends CustomChart { - - private final Callable> callable; - - /** - * Class constructor. - * - * @param chartId The id of the chart. - * @param callable The callable which is used to request the chart data. - */ - public SimpleBarChart(String chartId, Callable> callable) { - super(chartId); - this.callable = callable; - } - - @Override - protected ObjectNode getChartData() throws Exception { - ObjectNode data = mapper.createObjectNode(); - ObjectNode values = mapper.createObjectNode(); - Map map = callable.call(); - if (map == null || map.isEmpty()) { - // Null = skip the chart - return null; - } - for (Map.Entry entry : map.entrySet()) { - ArrayNode categoryValues = mapper.createArrayNode(); - categoryValues.add(entry.getValue()); - values.putPOJO(entry.getKey(), categoryValues); - } - data.putPOJO("values", values); - return data; - } - - } - - /** - * Represents a custom advanced bar chart. - */ - public static class AdvancedBarChart extends CustomChart { - - private final Callable> callable; - - /** - * Class constructor. - * - * @param chartId The id of the chart. - * @param callable The callable which is used to request the chart data. - */ - public AdvancedBarChart(String chartId, Callable> callable) { - super(chartId); - this.callable = callable; - } - - @Override - protected ObjectNode getChartData() throws Exception { - ObjectNode data = mapper.createObjectNode(); - ObjectNode values = mapper.createObjectNode(); - Map map = callable.call(); - if (map == null || map.isEmpty()) { - // Null = skip the chart - return null; - } - boolean allSkipped = true; - for (Map.Entry entry : map.entrySet()) { - if (entry.getValue().length == 0) { - continue; // Skip this invalid - } - allSkipped = false; - ArrayNode categoryValues = mapper.createArrayNode(); - for (int categoryValue : entry.getValue()) { - categoryValues.add(categoryValue); - } - values.putPOJO(entry.getKey(), categoryValues); - } - if (allSkipped) { - // Null = skip the chart - return null; - } - data.putPOJO("values", values); - return data; - } - - } } \ No newline at end of file diff --git a/core/src/main/java/org/geysermc/geyser/util/SignUtils.java b/core/src/main/java/org/geysermc/geyser/util/SignUtils.java index fd2d98ba9..3a4ec4f2c 100644 --- a/core/src/main/java/org/geysermc/geyser/util/SignUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/SignUtils.java @@ -25,8 +25,6 @@ package org.geysermc.geyser.util; -import org.geysermc.geyser.level.block.BlockStateValues; - /** * Provides utilities for interacting with signs. Mainly, it deals with the widths of each character. * Since Bedrock auto-wraps signs and Java does not, we have to take this into account when translating signs. diff --git a/core/src/main/java/org/geysermc/geyser/util/SoundUtils.java b/core/src/main/java/org/geysermc/geyser/util/SoundUtils.java index b56d9873b..4c5f6b68f 100644 --- a/core/src/main/java/org/geysermc/geyser/util/SoundUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/SoundUtils.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.util; import com.github.steveice10.mc.protocol.data.game.level.sound.Sound; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.LevelEvent; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; @@ -50,7 +51,7 @@ public final class SoundUtils { * @param sound the sound name * @return a sound event from the given sound */ - private static SoundEvent toSoundEvent(String sound) { + private static @Nullable SoundEvent toSoundEvent(String sound) { try { return SoundEvent.valueOf(sound.toUpperCase(Locale.ROOT).replace(".", "_")); } catch (Exception ex) { diff --git a/core/src/main/java/org/geysermc/geyser/util/VersionCheckUtils.java b/core/src/main/java/org/geysermc/geyser/util/VersionCheckUtils.java index c0fd10232..cf90a6bcd 100644 --- a/core/src/main/java/org/geysermc/geyser/util/VersionCheckUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/VersionCheckUtils.java @@ -31,6 +31,7 @@ import net.kyori.adventure.text.TextReplacementConfig; import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.TextDecoration; +import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.Constants; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserLogger; @@ -38,7 +39,6 @@ import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.text.GeyserLocale; -import javax.annotation.Nonnull; import java.util.OptionalInt; import java.util.concurrent.CompletableFuture; import java.util.function.Supplier; @@ -46,7 +46,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; public final class VersionCheckUtils { - private static @Nonnull OptionalInt LATEST_BEDROCK_RELEASE = OptionalInt.empty(); + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") + private static @NonNull OptionalInt LATEST_BEDROCK_RELEASE = OptionalInt.empty(); private static final int SUPPORTED_JAVA_VERSION = 17; public static void checkForOutdatedFloodgate(GeyserLogger logger) { @@ -125,7 +126,7 @@ public final class VersionCheckUtils { }); } - public static @Nonnull OptionalInt getLatestBedrockRelease() { + public static @NonNull OptionalInt getLatestBedrockRelease() { return LATEST_BEDROCK_RELEASE; } diff --git a/core/src/main/java/org/geysermc/geyser/util/WebUtils.java b/core/src/main/java/org/geysermc/geyser/util/WebUtils.java index e4a98b3fc..fbcbd4a3c 100644 --- a/core/src/main/java/org/geysermc/geyser/util/WebUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/WebUtils.java @@ -26,9 +26,9 @@ package org.geysermc.geyser.util; import com.fasterxml.jackson.databind.JsonNode; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.GeyserImpl; -import javax.annotation.Nullable; import javax.naming.directory.Attribute; import javax.naming.directory.InitialDirContext; import java.io.*; @@ -101,7 +101,7 @@ public class WebUtils { * @param reqURL URL to post to * @param postContent String data to post * @return String returned by the server - * @throws IOException + * @throws IOException If the request fails */ public static String post(String reqURL, String postContent) throws IOException { URL url = new URL(reqURL); @@ -123,7 +123,7 @@ public class WebUtils { * * @param con The connection to get the string from * @return The body of the returned page - * @throws IOException + * @throws IOException If the request fails */ private static String connectionToString(HttpURLConnection con) throws IOException { // Send the request (we dont use this but its required for getErrorStream() to work) @@ -156,7 +156,7 @@ public class WebUtils { * @param reqURL URL to post to * @param fields Form data to post * @return String returned by the server - * @throws IOException + * @throws IOException If the request fails */ public static String postForm(String reqURL, Map fields) throws IOException { URL url = new URL(reqURL); @@ -169,15 +169,14 @@ public class WebUtils { try (OutputStream out = con.getOutputStream()) { // Write the form data to the output for (Map.Entry field : fields.entrySet()) { - out.write((field.getKey() + "=" + URLEncoder.encode(field.getValue(), StandardCharsets.UTF_8.toString()) + "&").getBytes(StandardCharsets.UTF_8)); + out.write((field.getKey() + "=" + URLEncoder.encode(field.getValue(), StandardCharsets.UTF_8) + "&").getBytes(StandardCharsets.UTF_8)); } } return connectionToString(con); } - @Nullable - public static String[] findSrvRecord(GeyserImpl geyser, String remoteAddress) { + public static String @Nullable [] findSrvRecord(GeyserImpl geyser, String remoteAddress) { try { // Searches for a server address and a port from a SRV record of the specified host name InitialDirContext ctx = new InitialDirContext(); diff --git a/core/src/main/java/org/geysermc/geyser/util/collection/FixedInt2BooleanMap.java b/core/src/main/java/org/geysermc/geyser/util/collection/FixedInt2BooleanMap.java index 832a7bcae..dc4545529 100644 --- a/core/src/main/java/org/geysermc/geyser/util/collection/FixedInt2BooleanMap.java +++ b/core/src/main/java/org/geysermc/geyser/util/collection/FixedInt2BooleanMap.java @@ -28,7 +28,13 @@ package org.geysermc.geyser.util.collection; import it.unimi.dsi.fastutil.ints.AbstractInt2BooleanMap; import it.unimi.dsi.fastutil.objects.ObjectSet; +import java.io.Serial; + public class FixedInt2BooleanMap extends AbstractInt2BooleanMap { + + @Serial + private static final long serialVersionUID = 1L; + protected boolean[] value; protected int start = -1; diff --git a/core/src/main/java/org/geysermc/geyser/util/collection/FixedInt2ByteMap.java b/core/src/main/java/org/geysermc/geyser/util/collection/FixedInt2ByteMap.java index ee37d612f..46cb2a2ca 100644 --- a/core/src/main/java/org/geysermc/geyser/util/collection/FixedInt2ByteMap.java +++ b/core/src/main/java/org/geysermc/geyser/util/collection/FixedInt2ByteMap.java @@ -29,7 +29,13 @@ import it.unimi.dsi.fastutil.ints.AbstractInt2ByteMap; import it.unimi.dsi.fastutil.ints.Int2ByteMap; import it.unimi.dsi.fastutil.objects.ObjectSet; +import java.io.Serial; + public class FixedInt2ByteMap extends AbstractInt2ByteMap { + + @Serial + private static final long serialVersionUID = 1L; + protected byte[] value; protected int start = -1; diff --git a/core/src/main/java/org/geysermc/geyser/util/collection/FixedInt2IntMap.java b/core/src/main/java/org/geysermc/geyser/util/collection/FixedInt2IntMap.java index f5bd89d64..4a27d51a9 100644 --- a/core/src/main/java/org/geysermc/geyser/util/collection/FixedInt2IntMap.java +++ b/core/src/main/java/org/geysermc/geyser/util/collection/FixedInt2IntMap.java @@ -29,10 +29,15 @@ import it.unimi.dsi.fastutil.ints.AbstractInt2IntMap; import it.unimi.dsi.fastutil.ints.Int2IntMap; import it.unimi.dsi.fastutil.objects.ObjectSet; +import java.io.Serial; + public class FixedInt2IntMap extends AbstractInt2IntMap { protected int[] value; protected int start = -1; + @Serial + private static final long serialVersionUID = 1L; + @Override public int size() { return value.length; diff --git a/core/src/main/java/org/geysermc/geyser/util/collection/LecternHasBookMap.java b/core/src/main/java/org/geysermc/geyser/util/collection/LecternHasBookMap.java index bafb2924c..42d0da803 100644 --- a/core/src/main/java/org/geysermc/geyser/util/collection/LecternHasBookMap.java +++ b/core/src/main/java/org/geysermc/geyser/util/collection/LecternHasBookMap.java @@ -32,11 +32,16 @@ import org.geysermc.geyser.level.WorldManager; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.BlockEntityUtils; +import java.io.Serial; + /** * Map that takes advantage of its internals for fast operations on block states to determine if they are lecterns. */ public class LecternHasBookMap extends FixedInt2BooleanMap { + @Serial + private static final long serialVersionUID = 1L; + /** * Update a potential lectern within the world. This is a map method so it can use the internal fields to * optimize lectern determining. diff --git a/core/src/main/java/org/geysermc/geyser/util/collection/package-info.java b/core/src/main/java/org/geysermc/geyser/util/collection/package-info.java index e17a38877..46fa5df11 100644 --- a/core/src/main/java/org/geysermc/geyser/util/collection/package-info.java +++ b/core/src/main/java/org/geysermc/geyser/util/collection/package-info.java @@ -25,7 +25,7 @@ /** * Contains useful collections for use in Geyser. - * + *

* Of note are the fixed int maps. Designed for use with block states that are positive and sequential, they do not allow keys to be * added that are not greater by one versus the previous key. Because of this, speedy operations of {@link java.util.Map#get(java.lang.Object)} * and {@link java.util.Map#containsKey(java.lang.Object)} can be performed by simply checking the bounds of the map From c0f6a2b926900bfed8e99fb4ad25c978cf98bab3 Mon Sep 17 00:00:00 2001 From: chris Date: Wed, 6 Dec 2023 08:26:20 +0100 Subject: [PATCH 135/344] Add more info to Fabric's geyser dumps (#4175) * Added onlineMode, platformName, and Minecraft version to dump - renames platformVersion to loaderVersion since that is more fitting to modded structure * rename loaderVersion back to platformVersion * address review by @Konicai * Fix geyser dump creation (regression from the syntax/annotation PR) --- .../geyser/platform/fabric/GeyserFabricDumpInfo.java | 8 +++++++- .../java/org/geysermc/geyser/text/AsteriskSerializer.java | 5 +++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricDumpInfo.java b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricDumpInfo.java index ee986ee62..75da9125f 100644 --- a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricDumpInfo.java +++ b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricDumpInfo.java @@ -43,21 +43,27 @@ import java.util.stream.Collectors; @Getter public class GeyserFabricDumpInfo extends BootstrapDumpInfo { - private String platformVersion = null; + private final String platformName; + private String platformVersion; + private final String minecraftVersion; private final EnvType environmentType; @AsteriskSerializer.Asterisk(isIp = true) private final String serverIP; private final int serverPort; + private final boolean onlineMode; private final List mods; public GeyserFabricDumpInfo(MinecraftServer server) { + this.platformName = server.getServerModName(); FabricLoader.getInstance().getModContainer("fabricloader").ifPresent(mod -> this.platformVersion = mod.getMetadata().getVersion().getFriendlyString()); + this.minecraftVersion = server.getServerVersion(); this.environmentType = FabricLoader.getInstance().getEnvironmentType(); this.serverIP = server.getLocalIp() == null ? "unknown" : server.getLocalIp(); this.serverPort = server.getPort(); + this.onlineMode = server.usesAuthentication(); this.mods = new ArrayList<>(); for (ModContainer mod : FabricLoader.getInstance().getAllMods()) { diff --git a/core/src/main/java/org/geysermc/geyser/text/AsteriskSerializer.java b/core/src/main/java/org/geysermc/geyser/text/AsteriskSerializer.java index 702fded92..66b61dbff 100644 --- a/core/src/main/java/org/geysermc/geyser/text/AsteriskSerializer.java +++ b/core/src/main/java/org/geysermc/geyser/text/AsteriskSerializer.java @@ -68,6 +68,11 @@ public class AsteriskSerializer extends StdSerializer implements Context String asterisk; boolean isIp; + @SuppressWarnings("unused") // Used by Jackson for Geyser dumps + public AsteriskSerializer() { + super(Object.class); + } + public AsteriskSerializer(String asterisk, boolean isIp) { super(Object.class); this.asterisk = asterisk; From 94a1cbeb832fddd265711e798481c6cf17a691af Mon Sep 17 00:00:00 2001 From: TheFloyds4240 <80289503+TheFloyds4240@users.noreply.github.com> Date: Wed, 6 Dec 2023 03:50:16 -0500 Subject: [PATCH 136/344] Default motd and player count passthrough config values to true(#2523) * Update config.yml I will in no way be offended if this is not merged. Essentially, it makes Geyser slightly more configured at the start for plugin versions by forwarding more information about the server to Bedrock players. * remove unused --------- Co-authored-by: onebeastchris --- core/src/main/resources/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/resources/config.yml b/core/src/main/resources/config.yml index 218e13833..b10c2788e 100644 --- a/core/src/main/resources/config.yml +++ b/core/src/main/resources/config.yml @@ -90,9 +90,9 @@ command-suggestions: true # The following three options enable "ping passthrough" - the MOTD, player count and/or protocol name gets retrieved from the Java server. # Relay the MOTD from the remote server to Bedrock players. -passthrough-motd: false +passthrough-motd: true # Relay the player count and max players from the remote server to Bedrock players. -passthrough-player-counts: false +passthrough-player-counts: true # Enable LEGACY ping passthrough. There is no need to enable this unless your MOTD or player count does not appear properly. # This option does nothing on standalone. legacy-ping-passthrough: false From 9d6dd58fd83fdec2bdfc764902348fa885b06e31 Mon Sep 17 00:00:00 2001 From: chris Date: Wed, 6 Dec 2023 22:22:21 +0100 Subject: [PATCH 137/344] Ensure executor service isn't null by accessing it via the getter (#4328) --- .../main/java/org/geysermc/geyser/skin/FakeHeadProvider.java | 2 +- core/src/main/java/org/geysermc/geyser/skin/SkinProvider.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/skin/FakeHeadProvider.java b/core/src/main/java/org/geysermc/geyser/skin/FakeHeadProvider.java index 4ae30be19..c7bd235b2 100644 --- a/core/src/main/java/org/geysermc/geyser/skin/FakeHeadProvider.java +++ b/core/src/main/java/org/geysermc/geyser/skin/FakeHeadProvider.java @@ -134,7 +134,7 @@ public class FakeHeadProvider { session.getPlayerWithCustomHeads().add(entity.getUuid()); String texturesProperty = entity.getTexturesProperty(); - SkinProvider.EXECUTOR_SERVICE.execute(() -> { + SkinProvider.getExecutorService().execute(() -> { try { SkinProvider.SkinData mergedSkinData = MERGED_SKINS_LOADING_CACHE.get(new FakeHeadEntry(texturesProperty, fakeHeadSkinUrl, entity)); SkinManager.sendSkinPacket(session, entity, mergedSkinData); diff --git a/core/src/main/java/org/geysermc/geyser/skin/SkinProvider.java b/core/src/main/java/org/geysermc/geyser/skin/SkinProvider.java index 23985c33f..12a1e8b2b 100644 --- a/core/src/main/java/org/geysermc/geyser/skin/SkinProvider.java +++ b/core/src/main/java/org/geysermc/geyser/skin/SkinProvider.java @@ -58,7 +58,7 @@ import java.util.function.Predicate; public class SkinProvider { private static final boolean ALLOW_THIRD_PARTY_CAPES = GeyserImpl.getInstance().getConfig().isAllowThirdPartyCapes(); - static ExecutorService EXECUTOR_SERVICE; + private static ExecutorService EXECUTOR_SERVICE; static final Skin EMPTY_SKIN; static final Cape EMPTY_CAPE = new Cape("", "no-cape", ByteArrays.EMPTY_ARRAY, -1, true); @@ -133,7 +133,7 @@ public class SkinProvider { WEARING_CUSTOM_SKULL_SLIM = new SkinGeometry("{\"geometry\" :{\"default\" :\"geometry.humanoid.wearingCustomSkullSlim\"}}", wearingCustomSkullSlim, false); } - private static ExecutorService getExecutorService() { + public static ExecutorService getExecutorService() { if (EXECUTOR_SERVICE == null) { EXECUTOR_SERVICE = Executors.newFixedThreadPool(ALLOW_THIRD_PARTY_CAPES ? 21 : 14); } From 39716508566431e230578ba64f2d479f47a75cfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=83=E9=A3=9E=E5=A4=8F?= Date: Thu, 7 Dec 2023 16:57:30 +0800 Subject: [PATCH 138/344] Fix collision problem with glass pane and iron bars (#4302) * Fix collision problem,the wide for bedrock is 0.5 but for java is 0.5625 when only one side connect. * Fixed an issue where the collision box was abnormal at the corner when two sides of the glass panel were connected. * Merge similar methods, adjust code. * More lenient judgment; reduce redundant code to avoid repeated calls. --- .../GlassPaneAndIronBarsCollision.java | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 core/src/main/java/org/geysermc/geyser/translator/collision/GlassPaneAndIronBarsCollision.java diff --git a/core/src/main/java/org/geysermc/geyser/translator/collision/GlassPaneAndIronBarsCollision.java b/core/src/main/java/org/geysermc/geyser/translator/collision/GlassPaneAndIronBarsCollision.java new file mode 100644 index 000000000..14439645a --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/translator/collision/GlassPaneAndIronBarsCollision.java @@ -0,0 +1,112 @@ +/* + * 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.translator.collision; + +import lombok.EqualsAndHashCode; +import org.geysermc.geyser.level.physics.BoundingBox; +import org.geysermc.geyser.session.GeyserSession; + +@EqualsAndHashCode(callSuper = true) +@CollisionRemapper(regex = "glass_pane$|iron_bars$", usesParams = true, passDefaultBoxes = true) +public class GlassPaneAndIronBarsCollision extends BlockCollision { + /** + * 1 = north + * 2 = east + * 3 = south + * 4 = west + * 5 = north, east + * 6 = east, south + * 7 = south, west + * 8 = west, north + */ + private int facing; + + public GlassPaneAndIronBarsCollision(String params, BoundingBox[] defaultBoxes) { + super(defaultBoxes); + //east=true,north=true,south=true,west=true + if (params.contains("north=true") && params.contains("east=true")) { + facing = 5; + } else if (params.contains("east=true") && params.contains("south=true")) { + facing = 6; + } else if (params.contains("south=true") && params.contains("west=true")) { + facing = 7; + } else if (params.contains("west=true") && params.contains("north=true")) { + facing = 8; + } else if (params.contains("north=true")) { + facing = 1; + } else if (params.contains("east=true")) { + facing = 2; + } else if (params.contains("south=true")) { + facing = 3; + } else if (params.contains("west=true")) { + facing = 4; + } + } + + @Override + public boolean correctPosition(GeyserSession session, int x, int y, int z, BoundingBox playerCollision) { + boolean result = super.correctPosition(session, x, y, z, playerCollision); + playerCollision.setSizeX(playerCollision.getSizeX() - 0.0001); + playerCollision.setSizeY(playerCollision.getSizeY() - 0.0001); + playerCollision.setSizeZ(playerCollision.getSizeZ() - 0.0001); + + if (this.checkIntersection(x, y, z, playerCollision)) { + double newMiddleX = x; + double newMiddleZ = z; + + switch (facing) { + case 1 -> newMiddleZ += 0.8625; // North + case 2 -> newMiddleX += 0.1375; // East + case 3 -> newMiddleZ += 0.1375; // South + case 4 -> newMiddleX += 0.8625; // West + case 5 -> { // North, East + newMiddleZ += 0.8625; + newMiddleX += 0.1375; + } + case 6 -> { // East, South + newMiddleX += 0.1375; + newMiddleZ += 0.1375; + } + case 7 -> { // South, West + newMiddleZ += 0.1375; + newMiddleX += 0.8625; + } + case 8 -> { // West, North + newMiddleX += 0.8625; + newMiddleZ += 0.8625; + } + } + + playerCollision.setMiddleX(newMiddleX); + playerCollision.setMiddleZ(newMiddleZ); + } + + playerCollision.setSizeX(playerCollision.getSizeX() + 0.0001); + playerCollision.setSizeY(playerCollision.getSizeY() + 0.0001); + playerCollision.setSizeZ(playerCollision.getSizeZ() + 0.0001); + return result; + } +} From 1499def4a3e4ed17c4752b9bdeb6099522463a97 Mon Sep 17 00:00:00 2001 From: chris Date: Thu, 7 Dec 2023 20:27:25 +0100 Subject: [PATCH 139/344] Catch UnknownHostExceptions in legacy ping passthrough pings (#4331) * Catch unknownhostexception to avoid network errors when using legacy ping passthrough * Catch UnknownHostException separately, log a warning but no stacktrace --- .../org/geysermc/geyser/ping/GeyserLegacyPingPassthrough.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/src/main/java/org/geysermc/geyser/ping/GeyserLegacyPingPassthrough.java b/core/src/main/java/org/geysermc/geyser/ping/GeyserLegacyPingPassthrough.java index 64ad2c445..6bbca11ca 100644 --- a/core/src/main/java/org/geysermc/geyser/ping/GeyserLegacyPingPassthrough.java +++ b/core/src/main/java/org/geysermc/geyser/ping/GeyserLegacyPingPassthrough.java @@ -139,6 +139,9 @@ public class GeyserLegacyPingPassthrough implements IGeyserPingPassthrough, Runn this.geyser.getLogger().debug("Connection timeout for ping passthrough."); } catch (JsonParseException | JsonMappingException ex) { this.geyser.getLogger().error("Failed to parse json when pinging server!", ex); + } catch (UnknownHostException ex) { + // Don't reset pingInfo, as we want to keep the last known value + this.geyser.getLogger().warning("Unable to resolve remote host! Is the remote server down or invalid?"); } catch (IOException e) { this.geyser.getLogger().error("IO error while trying to use legacy ping passthrough", e); } From f1e7ef92f4d63a4f6d6cbff23022c7723647a7a9 Mon Sep 17 00:00:00 2001 From: chris Date: Mon, 11 Dec 2023 18:12:19 +0100 Subject: [PATCH 140/344] Fix issues with the ConnectionTestCommand (#4333) - Port out of bounds checking - Proper encoding of ip's to check - Don't assume "cache" response is nonnull; it is null when there's an error - Send users the error message that we get when server is unreachable --- .../defaults/ConnectionTestCommand.java | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/ConnectionTestCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/ConnectionTestCommand.java index 4cda72c9b..ad51826c3 100644 --- a/core/src/main/java/org/geysermc/geyser/command/defaults/ConnectionTestCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/ConnectionTestCommand.java @@ -36,6 +36,8 @@ import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.util.LoopbackUtil; import org.geysermc.geyser.util.WebUtils; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.Random; import java.util.concurrent.CompletableFuture; @@ -104,6 +106,12 @@ public class ConnectionTestCommand extends GeyserCommand { return; } + // Issue: port out of bounds + if (port <= 0 || port >= 65535) { + sender.sendMessage("The port you specified is invalid! Please specify a valid port."); + return; + } + // Issue: do the ports not line up? if (port != geyser.getConfig().getBedrock().port()) { if (fullAddress.length == 2) { @@ -161,20 +169,21 @@ public class ConnectionTestCommand extends GeyserCommand { sender.sendMessage("Testing server connection now. Please wait..."); JsonNode output; try { - output = WebUtils.getJson("https://checker.geysermc.org/ping?hostname=" + ip + "&port=" + port); + String hostname = URLEncoder.encode(ip, StandardCharsets.UTF_8); + output = WebUtils.getJson("https://checker.geysermc.org/ping?hostname=" + hostname + "&port=" + port); } finally { CONNECTION_TEST_MOTD = null; } - JsonNode cache = output.get("cache"); - String when; - if (cache.get("fromCache").asBoolean()) { - when = cache.get("secondsSince").asInt() + " seconds ago"; - } else { - when = "now"; - } - if (output.get("success").asBoolean()) { + JsonNode cache = output.get("cache"); + String when; + if (cache.get("fromCache").asBoolean()) { + when = cache.get("secondsSince").asInt() + " seconds ago"; + } else { + when = "now"; + } + JsonNode ping = output.get("ping"); JsonNode pong = ping.get("pong"); String remoteMotd = pong.get("motd").asText(); @@ -196,7 +205,11 @@ public class ConnectionTestCommand extends GeyserCommand { return; } - sender.sendMessage("Your server is likely unreachable from outside the network as of " + when + "."); + sender.sendMessage("Your server is likely unreachable from outside the network!"); + JsonNode message = output.get("message"); + if (message != null && !message.asText().isEmpty()) { + sender.sendMessage("Got the error message: " + message.asText()); + } sendLinks(sender); } catch (Exception e) { sender.sendMessage("An error occurred while trying to check your connection! Check the console for more information."); From d63a70daa9604193d78824b6fb8c2ad3f9923b14 Mon Sep 17 00:00:00 2001 From: kyrptonaught Date: Mon, 11 Dec 2023 18:20:25 -0500 Subject: [PATCH 141/344] Add support for adding custom translations. (#4047) * Add support for loading locale overwrites. Any lang files in this new folder will be appended to the main lang file when loaded. * A locale will no longer attempt to be downloaded and loaded if it already is loaded. Previously a lang file was reloaded everytime a player joins. * Switch some io bits to nio * formatting fixes * Update core/src/main/java/org/geysermc/geyser/text/MinecraftLocale.java * Rename isLocalLoaded to isLocaleLoaded * Rename overwrites to overrides * Catch separate exceptions when parsing locale file. Similar to previous implementation * Add //no-op to try/catch * Apply suggestions to fix issues that might arise with the Norwegian locale * Properly resolve override locale path for nb_no * Yeet temporary fix - addresses @Camotoy's review * Catch IOException properly --------- Co-authored-by: onebeastchris --- .../geysermc/geyser/text/MinecraftLocale.java | 118 +++++++++++------- 1 file changed, 72 insertions(+), 46 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/text/MinecraftLocale.java b/core/src/main/java/org/geysermc/geyser/text/MinecraftLocale.java index fa1b322a5..f6e37787d 100644 --- a/core/src/main/java/org/geysermc/geyser/text/MinecraftLocale.java +++ b/core/src/main/java/org/geysermc/geyser/text/MinecraftLocale.java @@ -35,6 +35,7 @@ import org.geysermc.geyser.util.WebUtils; import java.io.*; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.StandardOpenOption; import java.util.HashMap; import java.util.Iterator; import java.util.Locale; @@ -44,16 +45,15 @@ public class MinecraftLocale { public static final Map> LOCALE_MAPPINGS = new HashMap<>(); - static { - // Create the locales folder - File localesFolder = GeyserImpl.getInstance().getBootstrap().getConfigFolder().resolve("locales").toFile(); - //noinspection ResultOfMethodCallIgnored - localesFolder.mkdir(); + private static final Path LOCALE_FOLDER = GeyserImpl.getInstance().getBootstrap().getConfigFolder().resolve("locales"); - // FIXME TEMPORARY + static { try { - Files.delete(localesFolder.toPath().resolve("en_us.hash")); - } catch (IOException ignored) { + // Create the locales folder + Files.createDirectories(LOCALE_FOLDER); + Files.createDirectories(LOCALE_FOLDER.resolve("overrides")); + } catch (IOException exception) { + throw new RuntimeException("Unable to create locale folders! " + exception.getMessage()); } } @@ -69,12 +69,18 @@ public class MinecraftLocale { } /** - * Downloads a locale from Mojang if its not already loaded + * Downloads a locale from Mojang if it's not already loaded * * @param locale Locale to download and load */ public static void downloadAndLoadLocale(String locale) { locale = locale.toLowerCase(Locale.ROOT); + + if (isLocaleLoaded(locale)) { + GeyserImpl.getInstance().getLogger().debug("Locale already loaded: " + locale); + return; + } + if (locale.equals("nb_no")) { // Different locale code - https://minecraft.wiki/w/Language locale = "no_no"; @@ -99,7 +105,7 @@ public class MinecraftLocale { } /** - * Downloads the specified locale if its not already downloaded + * Downloads the specified locale if it's not already downloaded * * @param locale Locale to download */ @@ -132,34 +138,56 @@ public class MinecraftLocale { } private static Path getPath(String locale) { - return GeyserImpl.getInstance().getBootstrap().getConfigFolder().resolve("locales/" + locale + ".json"); + return LOCALE_FOLDER.resolve(locale + ".json"); } /** * Loads a locale already downloaded, if the file doesn't exist it just logs a warning * - * @param locale Locale to load + * @param locale Bedrock locale to load */ private static boolean loadLocale(String locale) { - File localeFile = GeyserImpl.getInstance().getBootstrap().getConfigFolder().resolve("locales/" + locale + ".json").toFile(); + String lowercaseLocale = locale.toLowerCase(Locale.ROOT); - // Load the locale - if (localeFile.exists()) { - // Read the localefile - InputStream localeStream; - try { - localeStream = new FileInputStream(localeFile); - } catch (FileNotFoundException e) { - throw new AssertionError(GeyserLocale.getLocaleStringLog("geyser.locale.fail.file", locale, e.getMessage())); - } + // Need to grab this before we change the locale - downloaded/override locales are stored under the Java locale name + Path localeFile = getPath(lowercaseLocale); + Path localeOverride = getPath("overrides/" + lowercaseLocale); + if (lowercaseLocale.equals("no_no")) { + // Store this locale under the Bedrock locale, so we don't need to do this check over and over + lowercaseLocale = "nb_no"; + } + + Map langMap = new HashMap<>(); + if (Files.exists(localeFile) && Files.isReadable(localeFile)) { + langMap.putAll(parseLangFile(localeFile, lowercaseLocale)); + } + + // Load the locale overwrites + if (Files.exists(localeOverride) && Files.isReadable(localeOverride)) { + langMap.putAll(parseLangFile(localeOverride, lowercaseLocale)); + } + + if (!langMap.isEmpty()) { + LOCALE_MAPPINGS.put(lowercaseLocale, langMap); + return true; + } else { + return false; + } + } + + /** + * Load and parse a json lang file. + * + * @param localeFile Path of locale file + * @param locale Locale to load + * @return a Map of the loaded translations + */ + public static Map parseLangFile(Path localeFile, String locale) { + // Read the localefile + try (InputStream localeStream = Files.newInputStream(localeFile, StandardOpenOption.READ)) { // Parse the file as json - JsonNode localeObj; - try { - localeObj = GeyserImpl.JSON_MAPPER.readTree(localeStream); - } catch (Exception e) { - throw new AssertionError(GeyserLocale.getLocaleStringLog("geyser.locale.fail.json", locale), e); - } + JsonNode localeObj = GeyserImpl.JSON_MAPPER.readTree(localeStream); // Parse all the locale fields Iterator> localeIterator = localeObj.fields(); @@ -168,24 +196,12 @@ public class MinecraftLocale { Map.Entry entry = localeIterator.next(); langMap.put(entry.getKey(), entry.getValue().asText()); } - - String bedrockLocale = locale.toLowerCase(Locale.ROOT); - if (bedrockLocale.equals("no_no")) { - // Store this locale under the Bedrock locale so we don't need to do this check over and over - bedrockLocale = "nb_no"; - } - - // Insert the locale into the mappings - LOCALE_MAPPINGS.put(bedrockLocale, langMap); - - try { - localeStream.close(); - } catch (IOException e) { - throw new AssertionError(GeyserLocale.getLocaleStringLog("geyser.locale.fail.file", locale, e.getMessage())); - } - return true; - } else { - return false; + localeStream.close(); + return langMap; + } catch (FileNotFoundException e){ + throw new AssertionError(GeyserLocale.getLocaleStringLog("geyser.locale.fail.file", locale, e.getMessage())); + } catch (Exception e) { + throw new AssertionError(GeyserLocale.getLocaleStringLog("geyser.locale.fail.json", locale), e); } } @@ -226,6 +242,16 @@ public class MinecraftLocale { return null; } + /** + * Checks if a locale has been loaded. + * + * @param locale Locale to check + * @return true if the locale has been loaded + */ + public static boolean isLocaleLoaded(String locale) { + return LOCALE_MAPPINGS.containsKey(locale.toLowerCase(Locale.ROOT)); + } + /** * Convert a byte array into a hex string * From 3d05181a1390ff43d66ed8e8b79792bf883df859 Mon Sep 17 00:00:00 2001 From: chris Date: Tue, 12 Dec 2023 22:44:13 +0100 Subject: [PATCH 142/344] Fix: Show the correct port that Geyser started on when using Geyser-Fabric on a client. (#4335) --- .../platform/fabric/mixin/client/IntegratedServerMixin.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/mixin/client/IntegratedServerMixin.java b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/mixin/client/IntegratedServerMixin.java index f11d3a1ae..af11174dc 100644 --- a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/mixin/client/IntegratedServerMixin.java +++ b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/mixin/client/IntegratedServerMixin.java @@ -32,6 +32,7 @@ import net.minecraft.client.server.IntegratedServer; import net.minecraft.network.chat.Component; import net.minecraft.server.MinecraftServer; import net.minecraft.world.level.GameType; +import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.platform.fabric.GeyserFabricMod; import org.geysermc.geyser.platform.fabric.GeyserServerPortGetter; import org.geysermc.geyser.text.GeyserLocale; @@ -62,7 +63,7 @@ public class IntegratedServerMixin implements GeyserServerPortGetter { // Give indication that Geyser is loaded Objects.requireNonNull(this.minecraft.player); this.minecraft.player.displayClientMessage(Component.literal(GeyserLocale.getPlayerLocaleString("geyser.core.start", - this.minecraft.options.languageCode, "localhost", String.valueOf(this.publishedPort))), false); + this.minecraft.options.languageCode, "localhost", String.valueOf(GeyserImpl.getInstance().bedrockListener().port()))), false); } } From f33703929eb8c324551fe0a871d2db2491ab3f58 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Mon, 20 Nov 2023 23:24:16 -0500 Subject: [PATCH 143/344] 1.20.3: update Items class --- .../java/org/geysermc/geyser/item/Items.java | 61 ++++++++++++++++++- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/item/Items.java b/core/src/main/java/org/geysermc/geyser/item/Items.java index 303665c79..92c446f68 100644 --- a/core/src/main/java/org/geysermc/geyser/item/Items.java +++ b/core/src/main/java/org/geysermc/geyser/item/Items.java @@ -51,6 +51,19 @@ public final class Items { public static final Item POLISHED_DEEPSLATE = register(new BlockItem("polished_deepslate", builder())); public static final Item CALCITE = register(new BlockItem("calcite", builder())); public static final Item TUFF = register(new BlockItem("tuff", builder())); + public static final Item TUFF_SLAB = register(new BlockItem("tuff_slab", builder())); + public static final Item TUFF_STAIRS = register(new BlockItem("tuff_stairs", builder())); + public static final Item TUFF_WALL = register(new BlockItem("tuff_wall", builder())); + public static final Item CHISELED_TUFF = register(new BlockItem("chiseled_tuff", builder())); + public static final Item POLISHED_TUFF = register(new BlockItem("polished_tuff", builder())); + public static final Item POLISHED_TUFF_SLAB = register(new BlockItem("polished_tuff_slab", builder())); + public static final Item POLISHED_TUFF_STAIRS = register(new BlockItem("polished_tuff_stairs", builder())); + public static final Item POLISHED_TUFF_WALL = register(new BlockItem("polished_tuff_wall", builder())); + public static final Item TUFF_BRICKS = register(new BlockItem("tuff_bricks", builder())); + public static final Item TUFF_BRICK_SLAB = register(new BlockItem("tuff_brick_slab", builder())); + public static final Item TUFF_BRICK_STAIRS = register(new BlockItem("tuff_brick_stairs", builder())); + public static final Item TUFF_BRICK_WALL = register(new BlockItem("tuff_brick_wall", builder())); + public static final Item CHISELED_TUFF_BRICKS = register(new BlockItem("chiseled_tuff_bricks", builder())); public static final Item DRIPSTONE_BLOCK = register(new BlockItem("dripstone_block", builder())); public static final Item GRASS_BLOCK = register(new BlockItem("grass_block", builder())); public static final Item DIRT = register(new BlockItem("dirt", builder())); @@ -120,6 +133,10 @@ public final class Items { public static final Item EXPOSED_COPPER = register(new BlockItem("exposed_copper", builder())); public static final Item WEATHERED_COPPER = register(new BlockItem("weathered_copper", builder())); public static final Item OXIDIZED_COPPER = register(new BlockItem("oxidized_copper", builder())); + public static final Item CHISELED_COPPER = register(new BlockItem("chiseled_copper", builder())); + public static final Item EXPOSED_CHISELED_COPPER = register(new BlockItem("exposed_chiseled_copper", builder())); + public static final Item WEATHERED_CHISELED_COPPER = register(new BlockItem("weathered_chiseled_copper", builder())); + public static final Item OXIDIZED_CHISELED_COPPER = register(new BlockItem("oxidized_chiseled_copper", builder())); public static final Item CUT_COPPER = register(new BlockItem("cut_copper", builder())); public static final Item EXPOSED_CUT_COPPER = register(new BlockItem("exposed_cut_copper", builder())); public static final Item WEATHERED_CUT_COPPER = register(new BlockItem("weathered_cut_copper", builder())); @@ -136,6 +153,10 @@ public final class Items { public static final Item WAXED_EXPOSED_COPPER = register(new BlockItem("waxed_exposed_copper", builder())); public static final Item WAXED_WEATHERED_COPPER = register(new BlockItem("waxed_weathered_copper", builder())); public static final Item WAXED_OXIDIZED_COPPER = register(new BlockItem("waxed_oxidized_copper", builder())); + public static final Item WAXED_CHISELED_COPPER = register(new BlockItem("waxed_chiseled_copper", builder())); + public static final Item WAXED_EXPOSED_CHISELED_COPPER = register(new BlockItem("waxed_exposed_chiseled_copper", builder())); + public static final Item WAXED_WEATHERED_CHISELED_COPPER = register(new BlockItem("waxed_weathered_chiseled_copper", builder())); + public static final Item WAXED_OXIDIZED_CHISELED_COPPER = register(new BlockItem("waxed_oxidized_chiseled_copper", builder())); public static final Item WAXED_CUT_COPPER = register(new BlockItem("waxed_cut_copper", builder())); public static final Item WAXED_EXPOSED_CUT_COPPER = register(new BlockItem("waxed_exposed_cut_copper", builder())); public static final Item WAXED_WEATHERED_CUT_COPPER = register(new BlockItem("waxed_weathered_cut_copper", builder())); @@ -211,7 +232,7 @@ public final class Items { public static final Item CHISELED_SANDSTONE = register(new BlockItem("chiseled_sandstone", builder())); public static final Item CUT_SANDSTONE = register(new BlockItem("cut_sandstone", builder())); public static final Item COBWEB = register(new BlockItem("cobweb", builder())); - public static final Item GRASS = register(new BlockItem("grass", builder())); + public static final Item SHORT_GRASS = register(new BlockItem("short_grass", builder())); public static final Item FERN = register(new BlockItem("fern", builder())); public static final Item AZALEA = register(new BlockItem("azalea", builder())); public static final Item FLOWERING_AZALEA = register(new BlockItem("flowering_azalea", builder())); @@ -304,7 +325,7 @@ public final class Items { public static final Item BRICKS = register(new BlockItem("bricks", builder())); public static final Item BOOKSHELF = register(new BlockItem("bookshelf", builder())); public static final Item CHISELED_BOOKSHELF = register(new BlockItem("chiseled_bookshelf", builder())); - public static final Item DECORATED_POT = register(new DecoratedPotItem("decorated_pot", builder().stackSize(1))); + public static final Item DECORATED_POT = register(new DecoratedPotItem("decorated_pot", builder())); public static final Item MOSSY_COBBLESTONE = register(new BlockItem("mossy_cobblestone", builder())); public static final Item OBSIDIAN = register(new BlockItem("obsidian", builder())); public static final Item TORCH = register(new BlockItem("torch", builder())); @@ -738,6 +759,14 @@ public final class Items { public static final Item BAMBOO_DOOR = register(new BlockItem("bamboo_door", builder())); public static final Item CRIMSON_DOOR = register(new BlockItem("crimson_door", builder())); public static final Item WARPED_DOOR = register(new BlockItem("warped_door", builder())); + public static final Item COPPER_DOOR = register(new BlockItem("copper_door", builder())); + public static final Item EXPOSED_COPPER_DOOR = register(new BlockItem("exposed_copper_door", builder())); + public static final Item WEATHERED_COPPER_DOOR = register(new BlockItem("weathered_copper_door", builder())); + public static final Item OXIDIZED_COPPER_DOOR = register(new BlockItem("oxidized_copper_door", builder())); + public static final Item WAXED_COPPER_DOOR = register(new BlockItem("waxed_copper_door", builder())); + public static final Item WAXED_EXPOSED_COPPER_DOOR = register(new BlockItem("waxed_exposed_copper_door", builder())); + public static final Item WAXED_WEATHERED_COPPER_DOOR = register(new BlockItem("waxed_weathered_copper_door", builder())); + public static final Item WAXED_OXIDIZED_COPPER_DOOR = register(new BlockItem("waxed_oxidized_copper_door", builder())); public static final Item IRON_TRAPDOOR = register(new BlockItem("iron_trapdoor", builder())); public static final Item OAK_TRAPDOOR = register(new BlockItem("oak_trapdoor", builder())); public static final Item SPRUCE_TRAPDOOR = register(new BlockItem("spruce_trapdoor", builder())); @@ -750,6 +779,14 @@ public final class Items { public static final Item BAMBOO_TRAPDOOR = register(new BlockItem("bamboo_trapdoor", builder())); public static final Item CRIMSON_TRAPDOOR = register(new BlockItem("crimson_trapdoor", builder())); public static final Item WARPED_TRAPDOOR = register(new BlockItem("warped_trapdoor", builder())); + public static final Item COPPER_TRAPDOOR = register(new BlockItem("copper_trapdoor", builder())); + public static final Item EXPOSED_COPPER_TRAPDOOR = register(new BlockItem("exposed_copper_trapdoor", builder())); + public static final Item WEATHERED_COPPER_TRAPDOOR = register(new BlockItem("weathered_copper_trapdoor", builder())); + public static final Item OXIDIZED_COPPER_TRAPDOOR = register(new BlockItem("oxidized_copper_trapdoor", builder())); + public static final Item WAXED_COPPER_TRAPDOOR = register(new BlockItem("waxed_copper_trapdoor", builder())); + public static final Item WAXED_EXPOSED_COPPER_TRAPDOOR = register(new BlockItem("waxed_exposed_copper_trapdoor", builder())); + public static final Item WAXED_WEATHERED_COPPER_TRAPDOOR = register(new BlockItem("waxed_weathered_copper_trapdoor", builder())); + public static final Item WAXED_OXIDIZED_COPPER_TRAPDOOR = register(new BlockItem("waxed_oxidized_copper_trapdoor", builder())); public static final Item OAK_FENCE_GATE = register(new BlockItem("oak_fence_gate", builder())); public static final Item SPRUCE_FENCE_GATE = register(new BlockItem("spruce_fence_gate", builder())); public static final Item BIRCH_FENCE_GATE = register(new BlockItem("birch_fence_gate", builder())); @@ -979,6 +1016,7 @@ public final class Items { public static final Item RED_BED = register(new BlockItem("red_bed", builder().stackSize(1))); public static final Item BLACK_BED = register(new BlockItem("black_bed", builder().stackSize(1))); public static final Item COOKIE = register(new Item("cookie", builder())); + public static final Item CRAFTER = register(new BlockItem("crafter", builder())); public static final Item FILLED_MAP = register(new FilledMapItem("filled_map", builder())); public static final Item SHEARS = register(new Item("shears", builder().stackSize(1).maxDamage(238))); public static final Item MELON_SLICE = register(new Item("melon_slice", builder())); @@ -1010,6 +1048,7 @@ public final class Items { public static final Item BAT_SPAWN_EGG = register(new SpawnEggItem("bat_spawn_egg", builder())); public static final Item BEE_SPAWN_EGG = register(new SpawnEggItem("bee_spawn_egg", builder())); public static final Item BLAZE_SPAWN_EGG = register(new SpawnEggItem("blaze_spawn_egg", builder())); + public static final Item BREEZE_SPAWN_EGG = register(new SpawnEggItem("breeze_spawn_egg", builder())); public static final Item CAT_SPAWN_EGG = register(new SpawnEggItem("cat_spawn_egg", builder())); public static final Item CAMEL_SPAWN_EGG = register(new SpawnEggItem("camel_spawn_egg", builder())); public static final Item CAVE_SPIDER_SPAWN_EGG = register(new SpawnEggItem("cave_spider_spawn_egg", builder())); @@ -1293,6 +1332,24 @@ public final class Items { public static final Item SHELTER_POTTERY_SHERD = register(new Item("shelter_pottery_sherd", builder())); public static final Item SKULL_POTTERY_SHERD = register(new Item("skull_pottery_sherd", builder())); public static final Item SNORT_POTTERY_SHERD = register(new Item("snort_pottery_sherd", builder())); + public static final Item COPPER_GRATE = register(new BlockItem("copper_grate", builder())); + public static final Item EXPOSED_COPPER_GRATE = register(new BlockItem("exposed_copper_grate", builder())); + public static final Item WEATHERED_COPPER_GRATE = register(new BlockItem("weathered_copper_grate", builder())); + public static final Item OXIDIZED_COPPER_GRATE = register(new BlockItem("oxidized_copper_grate", builder())); + public static final Item WAXED_COPPER_GRATE = register(new BlockItem("waxed_copper_grate", builder())); + public static final Item WAXED_EXPOSED_COPPER_GRATE = register(new BlockItem("waxed_exposed_copper_grate", builder())); + public static final Item WAXED_WEATHERED_COPPER_GRATE = register(new BlockItem("waxed_weathered_copper_grate", builder())); + public static final Item WAXED_OXIDIZED_COPPER_GRATE = register(new BlockItem("waxed_oxidized_copper_grate", builder())); + public static final Item COPPER_BULB = register(new BlockItem("copper_bulb", builder())); + public static final Item EXPOSED_COPPER_BULB = register(new BlockItem("exposed_copper_bulb", builder())); + public static final Item WEATHERED_COPPER_BULB = register(new BlockItem("weathered_copper_bulb", builder())); + public static final Item OXIDIZED_COPPER_BULB = register(new BlockItem("oxidized_copper_bulb", builder())); + public static final Item WAXED_COPPER_BULB = register(new BlockItem("waxed_copper_bulb", builder())); + public static final Item WAXED_EXPOSED_COPPER_BULB = register(new BlockItem("waxed_exposed_copper_bulb", builder())); + public static final Item WAXED_WEATHERED_COPPER_BULB = register(new BlockItem("waxed_weathered_copper_bulb", builder())); + public static final Item WAXED_OXIDIZED_COPPER_BULB = register(new BlockItem("waxed_oxidized_copper_bulb", builder())); + public static final Item TRIAL_SPAWNER = register(new BlockItem("trial_spawner", builder())); + public static final Item TRIAL_KEY = register(new Item("trial_key", builder())); private static T register(T item) { return register(item, Registries.JAVA_ITEMS.get().size()); From 184a14d026f9ce75a8776d4da0787011f76f70ae Mon Sep 17 00:00:00 2001 From: Hasan <52300558+hasankayra04@users.noreply.github.com> Date: Tue, 21 Nov 2023 09:10:11 +0300 Subject: [PATCH 144/344] Update versions in README and modrinth task (#4303) * Change fabric version * Update java version * Update Bedrock version also --- README.md | 2 +- bootstrap/fabric/build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b878db64d..b3471b4d7 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,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.20.0 - 1.20.50 and Minecraft Java 1.20.2 +### Currently supporting Minecraft Bedrock 1.20.0 - 1.20.50 and Minecraft Java 1.20.3 ## Setting Up Take a look [here](https://wiki.geysermc.org/geyser/setup/) for how to set up Geyser. diff --git a/bootstrap/fabric/build.gradle.kts b/bootstrap/fabric/build.gradle.kts index 07de70f60..83d6a48d0 100644 --- a/bootstrap/fabric/build.gradle.kts +++ b/bootstrap/fabric/build.gradle.kts @@ -119,7 +119,7 @@ modrinth { syncBodyFrom.set(rootProject.file("README.md").readText()) uploadFile.set(tasks.getByPath("remapModrinthJar")) - gameVersions.addAll("1.20.2") + gameVersions.addAll("1.20.3") loaders.add("fabric") failSilently.set(true) From a89aa4e0645153a8c85b9e1fa47fe171bf0e20be Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Sat, 25 Nov 2023 07:09:02 -0500 Subject: [PATCH 145/344] 1.20.3: compiling protocol changes --- .../geyser/level/GeyserAdvancement.java | 8 +- .../session/cache/AdvancementsCache.java | 2 +- .../DecoratedPotBlockEntityTranslator.java | 1 + .../BedrockBlockEntityDataTranslator.java | 3 +- ...avaClientboundResourcePackPushPacket.java} | 12 +-- .../JavaUpdateAdvancementsTranslator.java | 2 +- .../entity/spawn/JavaAddEntityTranslator.java | 10 +++ .../java/level/JavaBlockEventTranslator.java | 31 +++++--- .../java/level/JavaExplodeTranslator.java | 1 + .../java/level/JavaGameEventTranslator.java | 3 + .../java/level/JavaLevelEventTranslator.java | 10 ++- .../java/scoreboard/JavaResetScorePacket.java | 77 +++++++++++++++++++ .../JavaSetObjectiveTranslator.java | 1 + .../scoreboard/JavaSetScoreTranslator.java | 46 +++-------- gradle/libs.versions.toml | 4 +- 15 files changed, 147 insertions(+), 64 deletions(-) rename core/src/main/java/org/geysermc/geyser/translator/protocol/java/{JavaClientboundResourcePacksPacket.java => JavaClientboundResourcePackPushPacket.java} (85%) create mode 100644 core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaResetScorePacket.java diff --git a/core/src/main/java/org/geysermc/geyser/level/GeyserAdvancement.java b/core/src/main/java/org/geysermc/geyser/level/GeyserAdvancement.java index e09cad19c..f51e7b2ab 100644 --- a/core/src/main/java/org/geysermc/geyser/level/GeyserAdvancement.java +++ b/core/src/main/java/org/geysermc/geyser/level/GeyserAdvancement.java @@ -26,6 +26,8 @@ package org.geysermc.geyser.level; import com.github.steveice10.mc.protocol.data.game.advancement.Advancement; +import com.github.steveice10.mc.protocol.data.game.advancement.Advancement.DisplayData; +import com.github.steveice10.mc.protocol.data.game.advancement.Advancement.DisplayData.AdvancementType; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.session.cache.AdvancementsCache; import org.geysermc.geyser.text.ChatColor; @@ -61,7 +63,7 @@ public class GeyserAdvancement { return this.advancement.getParentId(); } - public Advancement.DisplayData getDisplayData() { + public DisplayData getDisplayData() { return this.advancement.getDisplayData(); } @@ -69,8 +71,8 @@ public class GeyserAdvancement { * @return Purple for challenges and green for normal advancements */ public String getDisplayColor() { - Advancement.DisplayData displayData = getDisplayData(); - return displayData != null && displayData.getFrameType() == Advancement.DisplayData.FrameType.CHALLENGE ? ChatColor.LIGHT_PURPLE : ChatColor.GREEN; + DisplayData displayData = getDisplayData(); + return displayData != null && displayData.getAdvancementType() == AdvancementType.CHALLENGE ? ChatColor.LIGHT_PURPLE : ChatColor.GREEN; } public @NonNull String getRootId(AdvancementsCache advancementsCache) { diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/AdvancementsCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/AdvancementsCache.java index 3562f0d4d..3bc661c16 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/AdvancementsCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/AdvancementsCache.java @@ -231,7 +231,7 @@ public class AdvancementsCache { } public String getColorFromAdvancementFrameType(GeyserAdvancement advancement) { - if (advancement.getDisplayData().getFrameType() == Advancement.DisplayData.FrameType.CHALLENGE) { + if (advancement.getDisplayData().getAdvancementType() == Advancement.DisplayData.AdvancementType.CHALLENGE) { return ChatColor.DARK_PURPLE; } return ChatColor.GREEN; // Used for types TASK and GOAL diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DecoratedPotBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DecoratedPotBlockEntityTranslator.java index 1774d9c76..9ff864101 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DecoratedPotBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DecoratedPotBlockEntityTranslator.java @@ -44,6 +44,7 @@ public class DecoratedPotBlockEntityTranslator extends BlockEntityTranslator { if (tag == null) { return; } + // todo 1.20.3 maybe // exact same format if (tag.get("sherds") instanceof ListTag sherds) { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockEntityDataTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockEntityDataTranslator.java index bab5e59a5..239bf9616 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockEntityDataTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockEntityDataTranslator.java @@ -118,8 +118,9 @@ public class BedrockBlockEntityDataTranslator extends PacketTranslator { +@Translator(packet = ClientboundResourcePackPushPacket.class) +public class JavaClientboundResourcePackPushPacket extends PacketTranslator { @Override - public void translate(GeyserSession session, ClientboundResourcePackPacket packet) { + public void translate(GeyserSession session, ClientboundResourcePackPushPacket packet) { // We need to "answer" this to avoid timeout issues related to resource packs // If packs are required, we need to lie to the server that we accepted them, as we get kicked otherwise. if (packet.isRequired()) { - session.sendDownstreamPacket(new ServerboundResourcePackPacket(ResourcePackStatus.SUCCESSFULLY_LOADED)); + session.sendDownstreamPacket(new ServerboundResourcePackPacket(packet.getId(), ResourcePackStatus.SUCCESSFULLY_LOADED)); } else { - session.sendDownstreamPacket(new ServerboundResourcePackPacket(ResourcePackStatus.DECLINED)); + session.sendDownstreamPacket(new ServerboundResourcePackPacket(packet.getId(), ResourcePackStatus.DECLINED)); } } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateAdvancementsTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateAdvancementsTranslator.java index e98e5c1ec..a7efdbefa 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateAdvancementsTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateAdvancementsTranslator.java @@ -81,7 +81,7 @@ public class JavaUpdateAdvancementsTranslator extends PacketTranslator 0 ? 1 : 0); + blockEventPacket.setEventData(chestValue.getViewers() > 0 ? 1 : 0); session.sendUpstreamPacket(blockEventPacket); - } else if (packet.getValue() instanceof EndGatewayValue) { + } else if (value instanceof EndGatewayValue) { blockEventPacket.setEventType(1); session.sendUpstreamPacket(blockEventPacket); - } else if (packet.getValue() instanceof NoteBlockValue) { + } else if (value instanceof NoteBlockValue) { session.getGeyser().getWorldManager().getBlockAtAsync(session, position).thenAccept(blockState -> { blockEventPacket.setEventData(BlockStateValues.getNoteblockPitch(blockState)); session.sendUpstreamPacket(blockEventPacket); }); - } else if (packet.getValue() instanceof PistonValue pistonValue) { + } else if (value instanceof PistonValue pistonValue) { PistonValueType action = (PistonValueType) packet.getType(); Direction direction = Direction.fromPistonValue(pistonValue.getDirection()); PistonCache pistonCache = session.getPistonCache(); @@ -98,13 +102,10 @@ public class JavaBlockEventTranslator extends PacketTranslator { - effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_SHOOT); + case SMOKE, WHITE_SMOKE -> { + if (levelEvent == LevelEventType.SMOKE) { + effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_SHOOT); + } else { + effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_SHOOT_WHITE_SMOKE); + } SmokeEventData smokeEventData = (SmokeEventData) packet.getData(); int data = 0; @@ -332,7 +336,7 @@ public class JavaLevelEventTranslator extends PacketTranslator { - GeyserImpl.getInstance().getLogger().debug("Unhandled level event: " + packet.getEvent()); + GeyserImpl.getInstance().getLogger().warning("Unhandled level event: " + packet.getEvent()); return; } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaResetScorePacket.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaResetScorePacket.java new file mode 100644 index 000000000..418037760 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaResetScorePacket.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2019-2023 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.translator.protocol.java.scoreboard; + +import com.github.steveice10.mc.protocol.data.game.scoreboard.ScoreboardPosition; +import com.github.steveice10.mc.protocol.packet.ingame.clientbound.scoreboard.ClientboundResetScorePacket; +import org.geysermc.geyser.scoreboard.Objective; +import org.geysermc.geyser.scoreboard.Scoreboard; +import org.geysermc.geyser.scoreboard.ScoreboardUpdater; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.WorldCache; +import org.geysermc.geyser.translator.protocol.PacketTranslator; +import org.geysermc.geyser.translator.protocol.Translator; + +@Translator(packet = ClientboundResetScorePacket.class) +public class JavaResetScorePacket extends PacketTranslator { + + @Override + public void translate(GeyserSession session, ClientboundResetScorePacket packet) { + WorldCache worldCache = session.getWorldCache(); + Scoreboard scoreboard = worldCache.getScoreboard(); + int pps = worldCache.increaseAndGetScoreboardPacketsPerSecond(); + + Objective belowName = scoreboard.getObjectiveSlots().get(ScoreboardPosition.BELOW_NAME); + + if (packet.getObjective() == null) { + // No objective name means all scores are reset for that player (/scoreboard players reset PLAYERNAME) + for (Objective otherObjective : scoreboard.getObjectives()) { + otherObjective.removeScore(packet.getOwner()); + } + + // as described below + if (belowName != null) { + JavaSetScoreTranslator.setBelowName(session, belowName, packet.getOwner(), 0); + } + } else { + Objective objective = scoreboard.getObjective(packet.getObjective()); + objective.removeScore(packet.getOwner()); + + // If this is the objective that is in use to show the below name text, we need to update the player + // attached to this score. + if (objective == belowName) { + // Update the score on this player to now reflect 0 + JavaSetScoreTranslator.setBelowName(session, objective, packet.getOwner(), 0); + } + } + + // ScoreboardUpdater will handle it for us if the packets per second + // (for score and team packets) is higher than the first threshold + if (pps < ScoreboardUpdater.FIRST_SCORE_PACKETS_PER_SECOND_THRESHOLD) { + scoreboard.onUpdate(); + } + } +} diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaSetObjectiveTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaSetObjectiveTranslator.java index 3b009a2a5..cef94c98e 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaSetObjectiveTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaSetObjectiveTranslator.java @@ -47,6 +47,7 @@ public class JavaSetObjectiveTranslator extends PacketTranslator { - objective.setScore(packet.getEntry(), packet.getValue()); - if (isBelowName) { - // Update the below name score on this player - setBelowName(session, objective, packet.getEntry(), packet.getValue()); - } - } - case REMOVE -> { - if (packet.getObjective().isEmpty()) { - // An empty objective name means all scores are reset for that player (/scoreboard players reset PLAYERNAME) - Objective belowName = scoreboard.getObjectiveSlots().get(ScoreboardPosition.BELOW_NAME); - if (belowName != null) { - setBelowName(session, belowName, packet.getEntry(), 0); - } - } - - if (objective != null) { - objective.removeScore(packet.getEntry()); - - if (isBelowName) { - // Update the score on this player to now reflect 0 - setBelowName(session, objective, packet.getEntry(), 0); - } - } else { - for (Objective objective1 : scoreboard.getObjectives()) { - objective1.removeScore(packet.getEntry()); - } - } - } + objective.setScore(packet.getOwner(), packet.getValue()); + if (isBelowName) { + // Update the below name score on this player + setBelowName(session, objective, packet.getOwner(), packet.getValue()); } // ScoreboardUpdater will handle it for us if the packets per second @@ -112,8 +86,8 @@ public class JavaSetScoreTranslator extends PacketTranslator Date: Mon, 27 Nov 2023 07:37:29 -0500 Subject: [PATCH 146/344] Drop <1.20.50 --- .../geysermc/geyser/network/GameProtocol.java | 28 +- .../populator/BlockRegistryPopulator.java | 12 +- .../populator/ItemRegistryPopulator.java | 36 +- .../geyser/session/GeyserSession.java | 11 +- .../JavaClientboundRecipesTranslator.java | 5 - .../bedrock/block_palette.1_20_0.nbt | Bin 151635 -> 0 bytes .../bedrock/block_palette.1_20_10.nbt | Bin 108793 -> 0 bytes .../bedrock/block_palette.1_20_30.nbt | Bin 158190 -> 0 bytes .../bedrock/runtime_item_states.1_20_0.json | 5186 --------------- .../bedrock/runtime_item_states.1_20_10.json | 5314 ---------------- .../bedrock/runtime_item_states.1_20_30.json | 5570 ----------------- 11 files changed, 10 insertions(+), 16152 deletions(-) delete mode 100644 core/src/main/resources/bedrock/block_palette.1_20_0.nbt delete mode 100644 core/src/main/resources/bedrock/block_palette.1_20_10.nbt delete mode 100644 core/src/main/resources/bedrock/block_palette.1_20_30.nbt delete mode 100644 core/src/main/resources/bedrock/runtime_item_states.1_20_0.json delete mode 100644 core/src/main/resources/bedrock/runtime_item_states.1_20_10.json delete mode 100644 core/src/main/resources/bedrock/runtime_item_states.1_20_30.json diff --git a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java index 11c7bc11e..923779095 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java @@ -29,13 +29,8 @@ import com.github.steveice10.mc.protocol.codec.MinecraftCodec; import com.github.steveice10.mc.protocol.codec.PacketCodec; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; -import org.cloudburstmc.protocol.bedrock.codec.v589.Bedrock_v589; -import org.cloudburstmc.protocol.bedrock.codec.v594.Bedrock_v594; -import org.cloudburstmc.protocol.bedrock.codec.v618.Bedrock_v618; -import org.cloudburstmc.protocol.bedrock.codec.v622.Bedrock_v622; import org.cloudburstmc.protocol.bedrock.codec.v630.Bedrock_v630; import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec; -import org.geysermc.geyser.session.GeyserSession; import java.util.ArrayList; import java.util.List; @@ -63,18 +58,11 @@ public final class GameProtocol { private static final PacketCodec DEFAULT_JAVA_CODEC = MinecraftCodec.CODEC; static { - SUPPORTED_BEDROCK_CODECS.add(Bedrock_v589.CODEC.toBuilder() - .minecraftVersion("1.20.0/1.20.1") - .build()); - SUPPORTED_BEDROCK_CODECS.add(Bedrock_v594.CODEC.toBuilder() - .minecraftVersion("1.20.10/1.20.15") - .build()); - SUPPORTED_BEDROCK_CODECS.add(Bedrock_v618.CODEC.toBuilder() - .minecraftVersion("1.20.30/1.20.32") - .build()); + /* SUPPORTED_BEDROCK_CODECS.add(Bedrock_v622.CODEC.toBuilder() .minecraftVersion("1.20.40/1.20.41") .build()); + */ SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC); } @@ -94,18 +82,6 @@ public final class GameProtocol { /* Bedrock convenience methods to gatekeep features and easily remove the check on version removal */ - public static boolean isPre1_20_10(GeyserSession session) { - return session.getUpstream().getProtocolVersion() < Bedrock_v594.CODEC.getProtocolVersion(); - } - - /** - * @param session the session to check - * @return true if the session needs an experiment for recipe unlocking - */ - public static boolean isUsingExperimentalRecipeUnlocking(GeyserSession session) { - return session.getUpstream().getProtocolVersion() == Bedrock_v594.CODEC.getProtocolVersion(); - } - /** * Gets the {@link PacketCodec} for Minecraft: Java Edition. * 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 328f61500..f185119ca 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 @@ -122,17 +122,9 @@ public final class BlockRegistryPopulator { } private static void registerBedrockBlocks() { - Remapper mapper594 = Remapper.of(BlockStateUpdater_1_20_10.INSTANCE); - Remapper mapper618 = Remapper.of(BlockStateUpdater_1_20_10.INSTANCE, BlockStateUpdater_1_20_30.INSTANCE); - Remapper mapper622 = Remapper.of(BlockStateUpdater_1_20_10.INSTANCE, BlockStateUpdater_1_20_30.INSTANCE, BlockStateUpdater_1_20_40.INSTANCE); - Remapper mapper630 = Remapper.of(BlockStateUpdater_1_20_10.INSTANCE, BlockStateUpdater_1_20_30.INSTANCE, BlockStateUpdater_1_20_40.INSTANCE, BlockStateUpdater_1_20_50.INSTANCE); - var blockMappers = ImmutableMap., Remapper>builder() - .put(ObjectIntPair.of("1_20_0", Bedrock_v589.CODEC.getProtocolVersion()), tag -> tag) - .put(ObjectIntPair.of("1_20_10", Bedrock_v594.CODEC.getProtocolVersion()), mapper594) - .put(ObjectIntPair.of("1_20_30", Bedrock_v618.CODEC.getProtocolVersion()), mapper618) - .put(ObjectIntPair.of("1_20_40", Bedrock_v622.CODEC.getProtocolVersion()), mapper622) - .put(ObjectIntPair.of("1_20_50", Bedrock_v630.CODEC.getProtocolVersion()), mapper630) + //.put(ObjectIntPair.of("1_20_40", Bedrock_v622.CODEC.getProtocolVersion()), mapper622) + .put(ObjectIntPair.of("1_20_50", Bedrock_v630.CODEC.getProtocolVersion()), tag -> tag) .build(); // We can keep this strong as nothing should be garbage collected 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 f46a49c3a..5aa24de1f 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 @@ -89,34 +89,8 @@ public class ItemRegistryPopulator { } public static void populate() { - // Forward-map 1.20 mappings to 1.20.10 - Remapper remapper594 = (item, mapping) -> { - // 1.20.10+ received parity for concrete and shulker boxes - String id = item.javaIdentifier(); - if (id.endsWith("_concrete") || id.endsWith("_shulker_box")) { - // the first underscore in "_shulker_box" accounts for ignoring "minecraft:shulker_box" - // which is mapped to "minecraft:undyed_shulker_box" - return mapping.withBedrockIdentifier(id); - } - return mapping; - }; - // 1.20 to 1.20.30 - Remapper remapper618 = (item, mapping) -> { - mapping = remapper594.remap(item, mapping); // apply 1.20.10 remapper first - - String id = item.javaIdentifier(); - if (id.endsWith("concrete_powder") || id.contains("stained_glass") || (id.endsWith("_terracotta") && !id.contains("glazed"))) { - // parity: concrete powder, stained-glass blocks and panes, and coloured terracotta - // 1. 'minecraft:terracotta' is still 'minecraft:hardened_clay' - // 2. there were no changes for glazed, but it doesn't have full parity, so ignore it. - return mapping.withBedrockIdentifier(id); - } - return mapping; - }; - + /* Remapper remapper630 = (item, mapping) -> { - mapping = remapper618.remap(item, mapping); // apply 1.20.30 remapper first - String id = item.javaIdentifier(); // 1.20.50 replaced stone & planks to individual stone types // E.g.: granite, diorite, andesite, polished variants, dark_oak_planks etc @@ -126,13 +100,11 @@ public class ItemRegistryPopulator { return mapping; }; + */ List paletteVersions = new ArrayList<>(3); - paletteVersions.add(new PaletteVersion("1_20_0", Bedrock_v589.CODEC.getProtocolVersion())); - paletteVersions.add(new PaletteVersion("1_20_10", Bedrock_v594.CODEC.getProtocolVersion(), Collections.emptyMap(), remapper594)); - paletteVersions.add(new PaletteVersion("1_20_30", Bedrock_v618.CODEC.getProtocolVersion(), Collections.emptyMap(), remapper618)); - paletteVersions.add(new PaletteVersion("1_20_40", Bedrock_v622.CODEC.getProtocolVersion(), Collections.emptyMap(), remapper618)); // NO item changes between 1.20.30 and 1.20.40 - paletteVersions.add(new PaletteVersion("1_20_50", Bedrock_v630.CODEC.getProtocolVersion(), Collections.emptyMap(), remapper630)); + //paletteVersions.add(new PaletteVersion("1_20_40", Bedrock_v622.CODEC.getProtocolVersion(), Collections.emptyMap(), remapper618)); // NO item changes between 1.20.30 and 1.20.40 + paletteVersions.add(new PaletteVersion("1_20_50", Bedrock_v630.CODEC.getProtocolVersion())); GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap(); diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 2f0d47b38..265a978ff 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -129,7 +129,6 @@ import org.geysermc.geyser.item.Items; import org.geysermc.geyser.level.JavaDimension; import org.geysermc.geyser.level.WorldManager; import org.geysermc.geyser.level.physics.CollisionManager; -import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.network.netty.LocalSession; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.type.BlockMappings; @@ -699,10 +698,8 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { gamerulePacket.getGameRules().add(new GameRuleData<>("keepinventory", true)); // Ensure client doesn't try and do anything funky; the server handles this for us gamerulePacket.getGameRules().add(new GameRuleData<>("spawnradius", 0)); - // Recipe unlocking - only needs to be added if 1. it isn't already on via an experiment, or 2. the client is on pre 1.20.10 - if (!GameProtocol.isPre1_20_10(this) && !GameProtocol.isUsingExperimentalRecipeUnlocking(this)) { - gamerulePacket.getGameRules().add(new GameRuleData<>("recipesunlock", true)); - } + // Recipe unlocking + gamerulePacket.getGameRules().add(new GameRuleData<>("recipesunlock", true)); upstream.sendPacket(gamerulePacket); } @@ -1561,10 +1558,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { startGamePacket.setRewindHistorySize(0); startGamePacket.setServerAuthoritativeBlockBreaking(false); - if (GameProtocol.isUsingExperimentalRecipeUnlocking(this)) { - startGamePacket.getExperiments().add(new ExperimentData("recipe_unlocking", true)); - } - upstream.sendPacket(startGamePacket); } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaClientboundRecipesTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaClientboundRecipesTranslator.java index 1ccbcfdec..fbf4c6f7b 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaClientboundRecipesTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaClientboundRecipesTranslator.java @@ -40,11 +40,6 @@ public class JavaClientboundRecipesTranslator extends PacketTranslator { diff --git a/core/src/main/resources/bedrock/block_palette.1_20_0.nbt b/core/src/main/resources/bedrock/block_palette.1_20_0.nbt deleted file mode 100644 index 3593e53e49819a4768d0f743a79958a565cc3303..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 151635 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 h73w(P|IQF`eRVO)4Td?fa@O>K{PO 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∋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

*|y7&{8R?>6?;6jSB@+;cJYMACRSEe?$K-gCM1 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 diff --git a/core/src/main/resources/bedrock/runtime_item_states.1_20_0.json b/core/src/main/resources/bedrock/runtime_item_states.1_20_0.json deleted file mode 100644 index 8aa2d1b0a..000000000 --- a/core/src/main/resources/bedrock/runtime_item_states.1_20_0.json +++ /dev/null @@ -1,5186 +0,0 @@ -[ - { - "name": "minecraft:acacia_boat", - "id": 381 - }, - { - "name": "minecraft:acacia_button", - "id": -140 - }, - { - "name": "minecraft:acacia_chest_boat", - "id": 649 - }, - { - "name": "minecraft:acacia_door", - "id": 563 - }, - { - "name": "minecraft:acacia_fence", - "id": -575 - }, - { - "name": "minecraft:acacia_fence_gate", - "id": 187 - }, - { - "name": "minecraft:acacia_hanging_sign", - "id": -504 - }, - { - "name": "minecraft:acacia_log", - "id": 162 - }, - { - "name": "minecraft:acacia_pressure_plate", - "id": -150 - }, - { - "name": "minecraft:acacia_sign", - "id": 586 - }, - { - "name": "minecraft:acacia_stairs", - "id": 163 - }, - { - "name": "minecraft:acacia_standing_sign", - "id": -190 - }, - { - "name": "minecraft:acacia_trapdoor", - "id": -145 - }, - { - "name": "minecraft:acacia_wall_sign", - "id": -191 - }, - { - "name": "minecraft:activator_rail", - "id": 126 - }, - { - "name": "minecraft:agent_spawn_egg", - "id": 489 - }, - { - "name": "minecraft:air", - "id": -158 - }, - { - "name": "minecraft:allay_spawn_egg", - "id": 638 - }, - { - "name": "minecraft:allow", - "id": 210 - }, - { - "name": "minecraft:amethyst_block", - "id": -327 - }, - { - "name": "minecraft:amethyst_cluster", - "id": -329 - }, - { - "name": "minecraft:amethyst_shard", - "id": 631 - }, - { - "name": "minecraft:ancient_debris", - "id": -271 - }, - { - "name": "minecraft:andesite_stairs", - "id": -171 - }, - { - "name": "minecraft:angler_pottery_sherd", - "id": 663 - }, - { - "name": "minecraft:anvil", - "id": 145 - }, - { - "name": "minecraft:apple", - "id": 257 - }, - { - "name": "minecraft:archer_pottery_sherd", - "id": 664 - }, - { - "name": "minecraft:armor_stand", - "id": 559 - }, - { - "name": "minecraft:arms_up_pottery_sherd", - "id": 665 - }, - { - "name": "minecraft:arrow", - "id": 303 - }, - { - "name": "minecraft:axolotl_bucket", - "id": 371 - }, - { - "name": "minecraft:axolotl_spawn_egg", - "id": 503 - }, - { - "name": "minecraft:azalea", - "id": -337 - }, - { - "name": "minecraft:azalea_leaves", - "id": -324 - }, - { - "name": "minecraft:azalea_leaves_flowered", - "id": -325 - }, - { - "name": "minecraft:baked_potato", - "id": 281 - }, - { - "name": "minecraft:balloon", - "id": 605 - }, - { - "name": "minecraft:bamboo", - "id": -163 - }, - { - "name": "minecraft:bamboo_block", - "id": -527 - }, - { - "name": "minecraft:bamboo_button", - "id": -511 - }, - { - "name": "minecraft:bamboo_chest_raft", - "id": 661 - }, - { - "name": "minecraft:bamboo_door", - "id": -517 - }, - { - "name": "minecraft:bamboo_double_slab", - "id": -521 - }, - { - "name": "minecraft:bamboo_fence", - "id": -515 - }, - { - "name": "minecraft:bamboo_fence_gate", - "id": -516 - }, - { - "name": "minecraft:bamboo_hanging_sign", - "id": -522 - }, - { - "name": "minecraft:bamboo_mosaic", - "id": -509 - }, - { - "name": "minecraft:bamboo_mosaic_double_slab", - "id": -525 - }, - { - "name": "minecraft:bamboo_mosaic_slab", - "id": -524 - }, - { - "name": "minecraft:bamboo_mosaic_stairs", - "id": -523 - }, - { - "name": "minecraft:bamboo_planks", - "id": -510 - }, - { - "name": "minecraft:bamboo_pressure_plate", - "id": -514 - }, - { - "name": "minecraft:bamboo_raft", - "id": 660 - }, - { - "name": "minecraft:bamboo_sapling", - "id": -164 - }, - { - "name": "minecraft:bamboo_sign", - "id": 659 - }, - { - "name": "minecraft:bamboo_slab", - "id": -513 - }, - { - "name": "minecraft:bamboo_stairs", - "id": -512 - }, - { - "name": "minecraft:bamboo_standing_sign", - "id": -518 - }, - { - "name": "minecraft:bamboo_trapdoor", - "id": -520 - }, - { - "name": "minecraft:bamboo_wall_sign", - "id": -519 - }, - { - "name": "minecraft:banner", - "id": 574 - }, - { - "name": "minecraft:banner_pattern", - "id": 710 - }, - { - "name": "minecraft:barrel", - "id": -203 - }, - { - "name": "minecraft:barrier", - "id": -161 - }, - { - "name": "minecraft:basalt", - "id": -234 - }, - { - "name": "minecraft:bat_spawn_egg", - "id": 455 - }, - { - "name": "minecraft:beacon", - "id": 138 - }, - { - "name": "minecraft:bed", - "id": 420 - }, - { - "name": "minecraft:bedrock", - "id": 7 - }, - { - "name": "minecraft:bee_nest", - "id": -218 - }, - { - "name": "minecraft:bee_spawn_egg", - "id": 496 - }, - { - "name": "minecraft:beef", - "id": 273 - }, - { - "name": "minecraft:beehive", - "id": -219 - }, - { - "name": "minecraft:beetroot", - "id": 285 - }, - { - "name": "minecraft:beetroot_seeds", - "id": 295 - }, - { - "name": "minecraft:beetroot_soup", - "id": 286 - }, - { - "name": "minecraft:bell", - "id": -206 - }, - { - "name": "minecraft:big_dripleaf", - "id": -323 - }, - { - "name": "minecraft:birch_boat", - "id": 378 - }, - { - "name": "minecraft:birch_button", - "id": -141 - }, - { - "name": "minecraft:birch_chest_boat", - "id": 646 - }, - { - "name": "minecraft:birch_door", - "id": 561 - }, - { - "name": "minecraft:birch_fence", - "id": -576 - }, - { - "name": "minecraft:birch_fence_gate", - "id": 184 - }, - { - "name": "minecraft:birch_hanging_sign", - "id": -502 - }, - { - "name": "minecraft:birch_log", - "id": -570 - }, - { - "name": "minecraft:birch_pressure_plate", - "id": -151 - }, - { - "name": "minecraft:birch_sign", - "id": 584 - }, - { - "name": "minecraft:birch_stairs", - "id": 135 - }, - { - "name": "minecraft:birch_standing_sign", - "id": -186 - }, - { - "name": "minecraft:birch_trapdoor", - "id": -146 - }, - { - "name": "minecraft:birch_wall_sign", - "id": -187 - }, - { - "name": "minecraft:black_candle", - "id": -428 - }, - { - "name": "minecraft:black_candle_cake", - "id": -445 - }, - { - "name": "minecraft:black_carpet", - "id": -611 - }, - { - "name": "minecraft:black_dye", - "id": 397 - }, - { - "name": "minecraft:black_glazed_terracotta", - "id": 235 - }, - { - "name": "minecraft:black_wool", - "id": -554 - }, - { - "name": "minecraft:blackstone", - "id": -273 - }, - { - "name": "minecraft:blackstone_double_slab", - "id": -283 - }, - { - "name": "minecraft:blackstone_slab", - "id": -282 - }, - { - "name": "minecraft:blackstone_stairs", - "id": -276 - }, - { - "name": "minecraft:blackstone_wall", - "id": -277 - }, - { - "name": "minecraft:blade_pottery_sherd", - "id": 666 - }, - { - "name": "minecraft:blast_furnace", - "id": -196 - }, - { - "name": "minecraft:blaze_powder", - "id": 431 - }, - { - "name": "minecraft:blaze_rod", - "id": 425 - }, - { - "name": "minecraft:blaze_spawn_egg", - "id": 458 - }, - { - "name": "minecraft:bleach", - "id": 603 - }, - { - "name": "minecraft:blue_candle", - "id": -424 - }, - { - "name": "minecraft:blue_candle_cake", - "id": -441 - }, - { - "name": "minecraft:blue_carpet", - "id": -607 - }, - { - "name": "minecraft:blue_dye", - "id": 401 - }, - { - "name": "minecraft:blue_glazed_terracotta", - "id": 231 - }, - { - "name": "minecraft:blue_ice", - "id": -11 - }, - { - "name": "minecraft:blue_wool", - "id": -563 - }, - { - "name": "minecraft:boat", - "id": 708 - }, - { - "name": "minecraft:bone", - "id": 417 - }, - { - "name": "minecraft:bone_block", - "id": 216 - }, - { - "name": "minecraft:bone_meal", - "id": 413 - }, - { - "name": "minecraft:book", - "id": 389 - }, - { - "name": "minecraft:bookshelf", - "id": 47 - }, - { - "name": "minecraft:border_block", - "id": 212 - }, - { - "name": "minecraft:bordure_indented_banner_pattern", - "id": 593 - }, - { - "name": "minecraft:bow", - "id": 302 - }, - { - "name": "minecraft:bowl", - "id": 323 - }, - { - "name": "minecraft:brain_coral", - "id": -581 - }, - { - "name": "minecraft:bread", - "id": 261 - }, - { - "name": "minecraft:brewer_pottery_sherd", - "id": 667 - }, - { - "name": "minecraft:brewing_stand", - "id": 433 - }, - { - "name": "minecraft:brick", - "id": 385 - }, - { - "name": "minecraft:brick_block", - "id": 45 - }, - { - "name": "minecraft:brick_stairs", - "id": 108 - }, - { - "name": "minecraft:brown_candle", - "id": -425 - }, - { - "name": "minecraft:brown_candle_cake", - "id": -442 - }, - { - "name": "minecraft:brown_carpet", - "id": -608 - }, - { - "name": "minecraft:brown_dye", - "id": 400 - }, - { - "name": "minecraft:brown_glazed_terracotta", - "id": 232 - }, - { - "name": "minecraft:brown_mushroom", - "id": 39 - }, - { - "name": "minecraft:brown_mushroom_block", - "id": 99 - }, - { - "name": "minecraft:brown_wool", - "id": -555 - }, - { - "name": "minecraft:brush", - "id": 683 - }, - { - "name": "minecraft:bubble_column", - "id": -160 - }, - { - "name": "minecraft:bubble_coral", - "id": -582 - }, - { - "name": "minecraft:bucket", - "id": 362 - }, - { - "name": "minecraft:budding_amethyst", - "id": -328 - }, - { - "name": "minecraft:burn_pottery_sherd", - "id": 668 - }, - { - "name": "minecraft:cactus", - "id": 81 - }, - { - "name": "minecraft:cake", - "id": 419 - }, - { - "name": "minecraft:calcite", - "id": -326 - }, - { - "name": "minecraft:calibrated_sculk_sensor", - "id": -580 - }, - { - "name": "minecraft:camel_spawn_egg", - "id": 662 - }, - { - "name": "minecraft:camera", - "id": 600 - }, - { - "name": "minecraft:campfire", - "id": 596 - }, - { - "name": "minecraft:candle", - "id": -412 - }, - { - "name": "minecraft:candle_cake", - "id": -429 - }, - { - "name": "minecraft:carpet", - "id": 703 - }, - { - "name": "minecraft:carrot", - "id": 279 - }, - { - "name": "minecraft:carrot_on_a_stick", - "id": 524 - }, - { - "name": "minecraft:carrots", - "id": 141 - }, - { - "name": "minecraft:cartography_table", - "id": -200 - }, - { - "name": "minecraft:carved_pumpkin", - "id": -155 - }, - { - "name": "minecraft:cat_spawn_egg", - "id": 490 - }, - { - "name": "minecraft:cauldron", - "id": 434 - }, - { - "name": "minecraft:cave_spider_spawn_egg", - "id": 459 - }, - { - "name": "minecraft:cave_vines", - "id": -322 - }, - { - "name": "minecraft:cave_vines_body_with_berries", - "id": -375 - }, - { - "name": "minecraft:cave_vines_head_with_berries", - "id": -376 - }, - { - "name": "minecraft:chain", - "id": 626 - }, - { - "name": "minecraft:chain_command_block", - "id": 189 - }, - { - "name": "minecraft:chainmail_boots", - "id": 344 - }, - { - "name": "minecraft:chainmail_chestplate", - "id": 342 - }, - { - "name": "minecraft:chainmail_helmet", - "id": 341 - }, - { - "name": "minecraft:chainmail_leggings", - "id": 343 - }, - { - "name": "minecraft:charcoal", - "id": 305 - }, - { - "name": "minecraft:chemical_heat", - "id": 192 - }, - { - "name": "minecraft:chemistry_table", - "id": 238 - }, - { - "name": "minecraft:cherry_boat", - "id": 656 - }, - { - "name": "minecraft:cherry_button", - "id": -530 - }, - { - "name": "minecraft:cherry_chest_boat", - "id": 657 - }, - { - "name": "minecraft:cherry_door", - "id": -531 - }, - { - "name": "minecraft:cherry_double_slab", - "id": -540 - }, - { - "name": "minecraft:cherry_fence", - "id": -532 - }, - { - "name": "minecraft:cherry_fence_gate", - "id": -533 - }, - { - "name": "minecraft:cherry_hanging_sign", - "id": -534 - }, - { - "name": "minecraft:cherry_leaves", - "id": -548 - }, - { - "name": "minecraft:cherry_log", - "id": -536 - }, - { - "name": "minecraft:cherry_planks", - "id": -537 - }, - { - "name": "minecraft:cherry_pressure_plate", - "id": -538 - }, - { - "name": "minecraft:cherry_sapling", - "id": -547 - }, - { - "name": "minecraft:cherry_sign", - "id": 658 - }, - { - "name": "minecraft:cherry_slab", - "id": -539 - }, - { - "name": "minecraft:cherry_stairs", - "id": -541 - }, - { - "name": "minecraft:cherry_standing_sign", - "id": -542 - }, - { - "name": "minecraft:cherry_trapdoor", - "id": -543 - }, - { - "name": "minecraft:cherry_wall_sign", - "id": -544 - }, - { - "name": "minecraft:cherry_wood", - "id": -546 - }, - { - "name": "minecraft:chest", - "id": 54 - }, - { - "name": "minecraft:chest_boat", - "id": 652 - }, - { - "name": "minecraft:chest_minecart", - "id": 391 - }, - { - "name": "minecraft:chicken", - "id": 275 - }, - { - "name": "minecraft:chicken_spawn_egg", - "id": 437 - }, - { - "name": "minecraft:chiseled_bookshelf", - "id": -526 - }, - { - "name": "minecraft:chiseled_deepslate", - "id": -395 - }, - { - "name": "minecraft:chiseled_nether_bricks", - "id": -302 - }, - { - "name": "minecraft:chiseled_polished_blackstone", - "id": -279 - }, - { - "name": "minecraft:chorus_flower", - "id": 200 - }, - { - "name": "minecraft:chorus_fruit", - "id": 565 - }, - { - "name": "minecraft:chorus_plant", - "id": 240 - }, - { - "name": "minecraft:clay", - "id": 82 - }, - { - "name": "minecraft:clay_ball", - "id": 386 - }, - { - "name": "minecraft:client_request_placeholder_block", - "id": -465 - }, - { - "name": "minecraft:clock", - "id": 395 - }, - { - "name": "minecraft:coal", - "id": 304 - }, - { - "name": "minecraft:coal_block", - "id": 173 - }, - { - "name": "minecraft:coal_ore", - "id": 16 - }, - { - "name": "minecraft:coast_armor_trim_smithing_template", - "id": 687 - }, - { - "name": "minecraft:cobbled_deepslate", - "id": -379 - }, - { - "name": "minecraft:cobbled_deepslate_double_slab", - "id": -396 - }, - { - "name": "minecraft:cobbled_deepslate_slab", - "id": -380 - }, - { - "name": "minecraft:cobbled_deepslate_stairs", - "id": -381 - }, - { - "name": "minecraft:cobbled_deepslate_wall", - "id": -382 - }, - { - "name": "minecraft:cobblestone", - "id": 4 - }, - { - "name": "minecraft:cobblestone_wall", - "id": 139 - }, - { - "name": "minecraft:cocoa", - "id": 127 - }, - { - "name": "minecraft:cocoa_beans", - "id": 414 - }, - { - "name": "minecraft:cod", - "id": 264 - }, - { - "name": "minecraft:cod_bucket", - "id": 366 - }, - { - "name": "minecraft:cod_spawn_egg", - "id": 482 - }, - { - "name": "minecraft:colored_torch_bp", - "id": 204 - }, - { - "name": "minecraft:colored_torch_rg", - "id": 202 - }, - { - "name": "minecraft:command_block", - "id": 137 - }, - { - "name": "minecraft:command_block_minecart", - "id": 570 - }, - { - "name": "minecraft:comparator", - "id": 529 - }, - { - "name": "minecraft:compass", - "id": 393 - }, - { - "name": "minecraft:composter", - "id": -213 - }, - { - "name": "minecraft:compound", - "id": 601 - }, - { - "name": "minecraft:concrete", - "id": 236 - }, - { - "name": "minecraft:concrete_powder", - "id": 237 - }, - { - "name": "minecraft:conduit", - "id": -157 - }, - { - "name": "minecraft:cooked_beef", - "id": 274 - }, - { - "name": "minecraft:cooked_chicken", - "id": 276 - }, - { - "name": "minecraft:cooked_cod", - "id": 268 - }, - { - "name": "minecraft:cooked_mutton", - "id": 558 - }, - { - "name": "minecraft:cooked_porkchop", - "id": 263 - }, - { - "name": "minecraft:cooked_rabbit", - "id": 289 - }, - { - "name": "minecraft:cooked_salmon", - "id": 269 - }, - { - "name": "minecraft:cookie", - "id": 271 - }, - { - "name": "minecraft:copper_block", - "id": -340 - }, - { - "name": "minecraft:copper_ingot", - "id": 511 - }, - { - "name": "minecraft:copper_ore", - "id": -311 - }, - { - "name": "minecraft:coral", - "id": 706 - }, - { - "name": "minecraft:coral_block", - "id": -132 - }, - { - "name": "minecraft:coral_fan", - "id": -133 - }, - { - "name": "minecraft:coral_fan_dead", - "id": -134 - }, - { - "name": "minecraft:coral_fan_hang", - "id": -135 - }, - { - "name": "minecraft:coral_fan_hang2", - "id": -136 - }, - { - "name": "minecraft:coral_fan_hang3", - "id": -137 - }, - { - "name": "minecraft:cow_spawn_egg", - "id": 438 - }, - { - "name": "minecraft:cracked_deepslate_bricks", - "id": -410 - }, - { - "name": "minecraft:cracked_deepslate_tiles", - "id": -409 - }, - { - "name": "minecraft:cracked_nether_bricks", - "id": -303 - }, - { - "name": "minecraft:cracked_polished_blackstone_bricks", - "id": -280 - }, - { - "name": "minecraft:crafting_table", - "id": 58 - }, - { - "name": "minecraft:creeper_banner_pattern", - "id": 589 - }, - { - "name": "minecraft:creeper_spawn_egg", - "id": 443 - }, - { - "name": "minecraft:crimson_button", - "id": -260 - }, - { - "name": "minecraft:crimson_door", - "id": 623 - }, - { - "name": "minecraft:crimson_double_slab", - "id": -266 - }, - { - "name": "minecraft:crimson_fence", - "id": -256 - }, - { - "name": "minecraft:crimson_fence_gate", - "id": -258 - }, - { - "name": "minecraft:crimson_fungus", - "id": -228 - }, - { - "name": "minecraft:crimson_hanging_sign", - "id": -506 - }, - { - "name": "minecraft:crimson_hyphae", - "id": -299 - }, - { - "name": "minecraft:crimson_nylium", - "id": -232 - }, - { - "name": "minecraft:crimson_planks", - "id": -242 - }, - { - "name": "minecraft:crimson_pressure_plate", - "id": -262 - }, - { - "name": "minecraft:crimson_roots", - "id": -223 - }, - { - "name": "minecraft:crimson_sign", - "id": 621 - }, - { - "name": "minecraft:crimson_slab", - "id": -264 - }, - { - "name": "minecraft:crimson_stairs", - "id": -254 - }, - { - "name": "minecraft:crimson_standing_sign", - "id": -250 - }, - { - "name": "minecraft:crimson_stem", - "id": -225 - }, - { - "name": "minecraft:crimson_trapdoor", - "id": -246 - }, - { - "name": "minecraft:crimson_wall_sign", - "id": -252 - }, - { - "name": "minecraft:crossbow", - "id": 582 - }, - { - "name": "minecraft:crying_obsidian", - "id": -289 - }, - { - "name": "minecraft:cut_copper", - "id": -347 - }, - { - "name": "minecraft:cut_copper_slab", - "id": -361 - }, - { - "name": "minecraft:cut_copper_stairs", - "id": -354 - }, - { - "name": "minecraft:cyan_candle", - "id": -422 - }, - { - "name": "minecraft:cyan_candle_cake", - "id": -439 - }, - { - "name": "minecraft:cyan_carpet", - "id": -605 - }, - { - "name": "minecraft:cyan_dye", - "id": 403 - }, - { - "name": "minecraft:cyan_glazed_terracotta", - "id": 229 - }, - { - "name": "minecraft:cyan_wool", - "id": -561 - }, - { - "name": "minecraft:danger_pottery_sherd", - "id": 669 - }, - { - "name": "minecraft:dark_oak_boat", - "id": 382 - }, - { - "name": "minecraft:dark_oak_button", - "id": -142 - }, - { - "name": "minecraft:dark_oak_chest_boat", - "id": 650 - }, - { - "name": "minecraft:dark_oak_door", - "id": 564 - }, - { - "name": "minecraft:dark_oak_fence", - "id": -577 - }, - { - "name": "minecraft:dark_oak_fence_gate", - "id": 186 - }, - { - "name": "minecraft:dark_oak_hanging_sign", - "id": -505 - }, - { - "name": "minecraft:dark_oak_log", - "id": -572 - }, - { - "name": "minecraft:dark_oak_pressure_plate", - "id": -152 - }, - { - "name": "minecraft:dark_oak_sign", - "id": 587 - }, - { - "name": "minecraft:dark_oak_stairs", - "id": 164 - }, - { - "name": "minecraft:dark_oak_trapdoor", - "id": -147 - }, - { - "name": "minecraft:dark_prismarine_stairs", - "id": -3 - }, - { - "name": "minecraft:darkoak_standing_sign", - "id": -192 - }, - { - "name": "minecraft:darkoak_wall_sign", - "id": -193 - }, - { - "name": "minecraft:daylight_detector", - "id": 151 - }, - { - "name": "minecraft:daylight_detector_inverted", - "id": 178 - }, - { - "name": "minecraft:dead_brain_coral", - "id": -586 - }, - { - "name": "minecraft:dead_bubble_coral", - "id": -587 - }, - { - "name": "minecraft:dead_fire_coral", - "id": -588 - }, - { - "name": "minecraft:dead_horn_coral", - "id": -589 - }, - { - "name": "minecraft:dead_tube_coral", - "id": -585 - }, - { - "name": "minecraft:deadbush", - "id": 32 - }, - { - "name": "minecraft:decorated_pot", - "id": -551 - }, - { - "name": "minecraft:deepslate", - "id": -378 - }, - { - "name": "minecraft:deepslate_brick_double_slab", - "id": -399 - }, - { - "name": "minecraft:deepslate_brick_slab", - "id": -392 - }, - { - "name": "minecraft:deepslate_brick_stairs", - "id": -393 - }, - { - "name": "minecraft:deepslate_brick_wall", - "id": -394 - }, - { - "name": "minecraft:deepslate_bricks", - "id": -391 - }, - { - "name": "minecraft:deepslate_coal_ore", - "id": -406 - }, - { - "name": "minecraft:deepslate_copper_ore", - "id": -408 - }, - { - "name": "minecraft:deepslate_diamond_ore", - "id": -405 - }, - { - "name": "minecraft:deepslate_emerald_ore", - "id": -407 - }, - { - "name": "minecraft:deepslate_gold_ore", - "id": -402 - }, - { - "name": "minecraft:deepslate_iron_ore", - "id": -401 - }, - { - "name": "minecraft:deepslate_lapis_ore", - "id": -400 - }, - { - "name": "minecraft:deepslate_redstone_ore", - "id": -403 - }, - { - "name": "minecraft:deepslate_tile_double_slab", - "id": -398 - }, - { - "name": "minecraft:deepslate_tile_slab", - "id": -388 - }, - { - "name": "minecraft:deepslate_tile_stairs", - "id": -389 - }, - { - "name": "minecraft:deepslate_tile_wall", - "id": -390 - }, - { - "name": "minecraft:deepslate_tiles", - "id": -387 - }, - { - "name": "minecraft:deny", - "id": 211 - }, - { - "name": "minecraft:detector_rail", - "id": 28 - }, - { - "name": "minecraft:diamond", - "id": 306 - }, - { - "name": "minecraft:diamond_axe", - "id": 321 - }, - { - "name": "minecraft:diamond_block", - "id": 57 - }, - { - "name": "minecraft:diamond_boots", - "id": 352 - }, - { - "name": "minecraft:diamond_chestplate", - "id": 350 - }, - { - "name": "minecraft:diamond_helmet", - "id": 349 - }, - { - "name": "minecraft:diamond_hoe", - "id": 334 - }, - { - "name": "minecraft:diamond_horse_armor", - "id": 540 - }, - { - "name": "minecraft:diamond_leggings", - "id": 351 - }, - { - "name": "minecraft:diamond_ore", - "id": 56 - }, - { - "name": "minecraft:diamond_pickaxe", - "id": 320 - }, - { - "name": "minecraft:diamond_shovel", - "id": 319 - }, - { - "name": "minecraft:diamond_sword", - "id": 318 - }, - { - "name": "minecraft:diorite_stairs", - "id": -170 - }, - { - "name": "minecraft:dirt", - "id": 3 - }, - { - "name": "minecraft:dirt_with_roots", - "id": -318 - }, - { - "name": "minecraft:disc_fragment_5", - "id": 644 - }, - { - "name": "minecraft:dispenser", - "id": 23 - }, - { - "name": "minecraft:dolphin_spawn_egg", - "id": 486 - }, - { - "name": "minecraft:donkey_spawn_egg", - "id": 467 - }, - { - "name": "minecraft:double_cut_copper_slab", - "id": -368 - }, - { - "name": "minecraft:double_plant", - "id": 175 - }, - { - "name": "minecraft:double_stone_block_slab", - "id": 43 - }, - { - "name": "minecraft:double_stone_block_slab2", - "id": 181 - }, - { - "name": "minecraft:double_stone_block_slab3", - "id": -167 - }, - { - "name": "minecraft:double_stone_block_slab4", - "id": -168 - }, - { - "name": "minecraft:double_wooden_slab", - "id": 157 - }, - { - "name": "minecraft:dragon_breath", - "id": 567 - }, - { - "name": "minecraft:dragon_egg", - "id": 122 - }, - { - "name": "minecraft:dried_kelp", - "id": 270 - }, - { - "name": "minecraft:dried_kelp_block", - "id": -139 - }, - { - "name": "minecraft:dripstone_block", - "id": -317 - }, - { - "name": "minecraft:dropper", - "id": 125 - }, - { - "name": "minecraft:drowned_spawn_egg", - "id": 485 - }, - { - "name": "minecraft:dune_armor_trim_smithing_template", - "id": 686 - }, - { - "name": "minecraft:dye", - "id": 709 - }, - { - "name": "minecraft:echo_shard", - "id": 654 - }, - { - "name": "minecraft:egg", - "id": 392 - }, - { - "name": "minecraft:elder_guardian_spawn_egg", - "id": 473 - }, - { - "name": "minecraft:element_0", - "id": 36 - }, - { - "name": "minecraft:element_1", - "id": -12 - }, - { - "name": "minecraft:element_10", - "id": -21 - }, - { - "name": "minecraft:element_100", - "id": -111 - }, - { - "name": "minecraft:element_101", - "id": -112 - }, - { - "name": "minecraft:element_102", - "id": -113 - }, - { - "name": "minecraft:element_103", - "id": -114 - }, - { - "name": "minecraft:element_104", - "id": -115 - }, - { - "name": "minecraft:element_105", - "id": -116 - }, - { - "name": "minecraft:element_106", - "id": -117 - }, - { - "name": "minecraft:element_107", - "id": -118 - }, - { - "name": "minecraft:element_108", - "id": -119 - }, - { - "name": "minecraft:element_109", - "id": -120 - }, - { - "name": "minecraft:element_11", - "id": -22 - }, - { - "name": "minecraft:element_110", - "id": -121 - }, - { - "name": "minecraft:element_111", - "id": -122 - }, - { - "name": "minecraft:element_112", - "id": -123 - }, - { - "name": "minecraft:element_113", - "id": -124 - }, - { - "name": "minecraft:element_114", - "id": -125 - }, - { - "name": "minecraft:element_115", - "id": -126 - }, - { - "name": "minecraft:element_116", - "id": -127 - }, - { - "name": "minecraft:element_117", - "id": -128 - }, - { - "name": "minecraft:element_118", - "id": -129 - }, - { - "name": "minecraft:element_12", - "id": -23 - }, - { - "name": "minecraft:element_13", - "id": -24 - }, - { - "name": "minecraft:element_14", - "id": -25 - }, - { - "name": "minecraft:element_15", - "id": -26 - }, - { - "name": "minecraft:element_16", - "id": -27 - }, - { - "name": "minecraft:element_17", - "id": -28 - }, - { - "name": "minecraft:element_18", - "id": -29 - }, - { - "name": "minecraft:element_19", - "id": -30 - }, - { - "name": "minecraft:element_2", - "id": -13 - }, - { - "name": "minecraft:element_20", - "id": -31 - }, - { - "name": "minecraft:element_21", - "id": -32 - }, - { - "name": "minecraft:element_22", - "id": -33 - }, - { - "name": "minecraft:element_23", - "id": -34 - }, - { - "name": "minecraft:element_24", - "id": -35 - }, - { - "name": "minecraft:element_25", - "id": -36 - }, - { - "name": "minecraft:element_26", - "id": -37 - }, - { - "name": "minecraft:element_27", - "id": -38 - }, - { - "name": "minecraft:element_28", - "id": -39 - }, - { - "name": "minecraft:element_29", - "id": -40 - }, - { - "name": "minecraft:element_3", - "id": -14 - }, - { - "name": "minecraft:element_30", - "id": -41 - }, - { - "name": "minecraft:element_31", - "id": -42 - }, - { - "name": "minecraft:element_32", - "id": -43 - }, - { - "name": "minecraft:element_33", - "id": -44 - }, - { - "name": "minecraft:element_34", - "id": -45 - }, - { - "name": "minecraft:element_35", - "id": -46 - }, - { - "name": "minecraft:element_36", - "id": -47 - }, - { - "name": "minecraft:element_37", - "id": -48 - }, - { - "name": "minecraft:element_38", - "id": -49 - }, - { - "name": "minecraft:element_39", - "id": -50 - }, - { - "name": "minecraft:element_4", - "id": -15 - }, - { - "name": "minecraft:element_40", - "id": -51 - }, - { - "name": "minecraft:element_41", - "id": -52 - }, - { - "name": "minecraft:element_42", - "id": -53 - }, - { - "name": "minecraft:element_43", - "id": -54 - }, - { - "name": "minecraft:element_44", - "id": -55 - }, - { - "name": "minecraft:element_45", - "id": -56 - }, - { - "name": "minecraft:element_46", - "id": -57 - }, - { - "name": "minecraft:element_47", - "id": -58 - }, - { - "name": "minecraft:element_48", - "id": -59 - }, - { - "name": "minecraft:element_49", - "id": -60 - }, - { - "name": "minecraft:element_5", - "id": -16 - }, - { - "name": "minecraft:element_50", - "id": -61 - }, - { - "name": "minecraft:element_51", - "id": -62 - }, - { - "name": "minecraft:element_52", - "id": -63 - }, - { - "name": "minecraft:element_53", - "id": -64 - }, - { - "name": "minecraft:element_54", - "id": -65 - }, - { - "name": "minecraft:element_55", - "id": -66 - }, - { - "name": "minecraft:element_56", - "id": -67 - }, - { - "name": "minecraft:element_57", - "id": -68 - }, - { - "name": "minecraft:element_58", - "id": -69 - }, - { - "name": "minecraft:element_59", - "id": -70 - }, - { - "name": "minecraft:element_6", - "id": -17 - }, - { - "name": "minecraft:element_60", - "id": -71 - }, - { - "name": "minecraft:element_61", - "id": -72 - }, - { - "name": "minecraft:element_62", - "id": -73 - }, - { - "name": "minecraft:element_63", - "id": -74 - }, - { - "name": "minecraft:element_64", - "id": -75 - }, - { - "name": "minecraft:element_65", - "id": -76 - }, - { - "name": "minecraft:element_66", - "id": -77 - }, - { - "name": "minecraft:element_67", - "id": -78 - }, - { - "name": "minecraft:element_68", - "id": -79 - }, - { - "name": "minecraft:element_69", - "id": -80 - }, - { - "name": "minecraft:element_7", - "id": -18 - }, - { - "name": "minecraft:element_70", - "id": -81 - }, - { - "name": "minecraft:element_71", - "id": -82 - }, - { - "name": "minecraft:element_72", - "id": -83 - }, - { - "name": "minecraft:element_73", - "id": -84 - }, - { - "name": "minecraft:element_74", - "id": -85 - }, - { - "name": "minecraft:element_75", - "id": -86 - }, - { - "name": "minecraft:element_76", - "id": -87 - }, - { - "name": "minecraft:element_77", - "id": -88 - }, - { - "name": "minecraft:element_78", - "id": -89 - }, - { - "name": "minecraft:element_79", - "id": -90 - }, - { - "name": "minecraft:element_8", - "id": -19 - }, - { - "name": "minecraft:element_80", - "id": -91 - }, - { - "name": "minecraft:element_81", - "id": -92 - }, - { - "name": "minecraft:element_82", - "id": -93 - }, - { - "name": "minecraft:element_83", - "id": -94 - }, - { - "name": "minecraft:element_84", - "id": -95 - }, - { - "name": "minecraft:element_85", - "id": -96 - }, - { - "name": "minecraft:element_86", - "id": -97 - }, - { - "name": "minecraft:element_87", - "id": -98 - }, - { - "name": "minecraft:element_88", - "id": -99 - }, - { - "name": "minecraft:element_89", - "id": -100 - }, - { - "name": "minecraft:element_9", - "id": -20 - }, - { - "name": "minecraft:element_90", - "id": -101 - }, - { - "name": "minecraft:element_91", - "id": -102 - }, - { - "name": "minecraft:element_92", - "id": -103 - }, - { - "name": "minecraft:element_93", - "id": -104 - }, - { - "name": "minecraft:element_94", - "id": -105 - }, - { - "name": "minecraft:element_95", - "id": -106 - }, - { - "name": "minecraft:element_96", - "id": -107 - }, - { - "name": "minecraft:element_97", - "id": -108 - }, - { - "name": "minecraft:element_98", - "id": -109 - }, - { - "name": "minecraft:element_99", - "id": -110 - }, - { - "name": "minecraft:elytra", - "id": 571 - }, - { - "name": "minecraft:emerald", - "id": 519 - }, - { - "name": "minecraft:emerald_block", - "id": 133 - }, - { - "name": "minecraft:emerald_ore", - "id": 129 - }, - { - "name": "minecraft:empty_map", - "id": 522 - }, - { - "name": "minecraft:enchanted_book", - "id": 528 - }, - { - "name": "minecraft:enchanted_golden_apple", - "id": 259 - }, - { - "name": "minecraft:enchanting_table", - "id": 116 - }, - { - "name": "minecraft:end_brick_stairs", - "id": -178 - }, - { - "name": "minecraft:end_bricks", - "id": 206 - }, - { - "name": "minecraft:end_crystal", - "id": 712 - }, - { - "name": "minecraft:end_gateway", - "id": 209 - }, - { - "name": "minecraft:end_portal", - "id": 119 - }, - { - "name": "minecraft:end_portal_frame", - "id": 120 - }, - { - "name": "minecraft:end_rod", - "id": 208 - }, - { - "name": "minecraft:end_stone", - "id": 121 - }, - { - "name": "minecraft:ender_chest", - "id": 130 - }, - { - "name": "minecraft:ender_dragon_spawn_egg", - "id": 508 - }, - { - "name": "minecraft:ender_eye", - "id": 435 - }, - { - "name": "minecraft:ender_pearl", - "id": 424 - }, - { - "name": "minecraft:enderman_spawn_egg", - "id": 444 - }, - { - "name": "minecraft:endermite_spawn_egg", - "id": 462 - }, - { - "name": "minecraft:evoker_spawn_egg", - "id": 477 - }, - { - "name": "minecraft:experience_bottle", - "id": 515 - }, - { - "name": "minecraft:explorer_pottery_sherd", - "id": 670 - }, - { - "name": "minecraft:exposed_copper", - "id": -341 - }, - { - "name": "minecraft:exposed_cut_copper", - "id": -348 - }, - { - "name": "minecraft:exposed_cut_copper_slab", - "id": -362 - }, - { - "name": "minecraft:exposed_cut_copper_stairs", - "id": -355 - }, - { - "name": "minecraft:exposed_double_cut_copper_slab", - "id": -369 - }, - { - "name": "minecraft:eye_armor_trim_smithing_template", - "id": 690 - }, - { - "name": "minecraft:farmland", - "id": 60 - }, - { - "name": "minecraft:feather", - "id": 329 - }, - { - "name": "minecraft:fence", - "id": 705 - }, - { - "name": "minecraft:fence_gate", - "id": 107 - }, - { - "name": "minecraft:fermented_spider_eye", - "id": 430 - }, - { - "name": "minecraft:field_masoned_banner_pattern", - "id": 592 - }, - { - "name": "minecraft:filled_map", - "id": 422 - }, - { - "name": "minecraft:fire", - "id": 51 - }, - { - "name": "minecraft:fire_charge", - "id": 516 - }, - { - "name": "minecraft:fire_coral", - "id": -583 - }, - { - "name": "minecraft:firework_rocket", - "id": 526 - }, - { - "name": "minecraft:firework_star", - "id": 527 - }, - { - "name": "minecraft:fishing_rod", - "id": 394 - }, - { - "name": "minecraft:fletching_table", - "id": -201 - }, - { - "name": "minecraft:flint", - "id": 358 - }, - { - "name": "minecraft:flint_and_steel", - "id": 301 - }, - { - "name": "minecraft:flower_banner_pattern", - "id": 588 - }, - { - "name": "minecraft:flower_pot", - "id": 521 - }, - { - "name": "minecraft:flowering_azalea", - "id": -338 - }, - { - "name": "minecraft:flowing_lava", - "id": 10 - }, - { - "name": "minecraft:flowing_water", - "id": 8 - }, - { - "name": "minecraft:fox_spawn_egg", - "id": 492 - }, - { - "name": "minecraft:frame", - "id": 520 - }, - { - "name": "minecraft:friend_pottery_sherd", - "id": 671 - }, - { - "name": "minecraft:frog_spawn", - "id": -468 - }, - { - "name": "minecraft:frog_spawn_egg", - "id": 635 - }, - { - "name": "minecraft:frosted_ice", - "id": 207 - }, - { - "name": "minecraft:furnace", - "id": 61 - }, - { - "name": "minecraft:ghast_spawn_egg", - "id": 456 - }, - { - "name": "minecraft:ghast_tear", - "id": 426 - }, - { - "name": "minecraft:gilded_blackstone", - "id": -281 - }, - { - "name": "minecraft:glass", - "id": 20 - }, - { - "name": "minecraft:glass_bottle", - "id": 429 - }, - { - "name": "minecraft:glass_pane", - "id": 102 - }, - { - "name": "minecraft:glistering_melon_slice", - "id": 436 - }, - { - "name": "minecraft:globe_banner_pattern", - "id": 595 - }, - { - "name": "minecraft:glow_berries", - "id": 713 - }, - { - "name": "minecraft:glow_frame", - "id": 630 - }, - { - "name": "minecraft:glow_ink_sac", - "id": 510 - }, - { - "name": "minecraft:glow_lichen", - "id": -411 - }, - { - "name": "minecraft:glow_squid_spawn_egg", - "id": 505 - }, - { - "name": "minecraft:glow_stick", - "id": 608 - }, - { - "name": "minecraft:glowingobsidian", - "id": 246 - }, - { - "name": "minecraft:glowstone", - "id": 89 - }, - { - "name": "minecraft:glowstone_dust", - "id": 396 - }, - { - "name": "minecraft:goat_horn", - "id": 634 - }, - { - "name": "minecraft:goat_spawn_egg", - "id": 504 - }, - { - "name": "minecraft:gold_block", - "id": 41 - }, - { - "name": "minecraft:gold_ingot", - "id": 308 - }, - { - "name": "minecraft:gold_nugget", - "id": 427 - }, - { - "name": "minecraft:gold_ore", - "id": 14 - }, - { - "name": "minecraft:golden_apple", - "id": 258 - }, - { - "name": "minecraft:golden_axe", - "id": 327 - }, - { - "name": "minecraft:golden_boots", - "id": 356 - }, - { - "name": "minecraft:golden_carrot", - "id": 283 - }, - { - "name": "minecraft:golden_chestplate", - "id": 354 - }, - { - "name": "minecraft:golden_helmet", - "id": 353 - }, - { - "name": "minecraft:golden_hoe", - "id": 335 - }, - { - "name": "minecraft:golden_horse_armor", - "id": 539 - }, - { - "name": "minecraft:golden_leggings", - "id": 355 - }, - { - "name": "minecraft:golden_pickaxe", - "id": 326 - }, - { - "name": "minecraft:golden_rail", - "id": 27 - }, - { - "name": "minecraft:golden_shovel", - "id": 325 - }, - { - "name": "minecraft:golden_sword", - "id": 324 - }, - { - "name": "minecraft:granite_stairs", - "id": -169 - }, - { - "name": "minecraft:grass", - "id": 2 - }, - { - "name": "minecraft:grass_path", - "id": 198 - }, - { - "name": "minecraft:gravel", - "id": 13 - }, - { - "name": "minecraft:gray_candle", - "id": -420 - }, - { - "name": "minecraft:gray_candle_cake", - "id": -437 - }, - { - "name": "minecraft:gray_carpet", - "id": -603 - }, - { - "name": "minecraft:gray_dye", - "id": 405 - }, - { - "name": "minecraft:gray_glazed_terracotta", - "id": 227 - }, - { - "name": "minecraft:gray_wool", - "id": -553 - }, - { - "name": "minecraft:green_candle", - "id": -426 - }, - { - "name": "minecraft:green_candle_cake", - "id": -443 - }, - { - "name": "minecraft:green_carpet", - "id": -609 - }, - { - "name": "minecraft:green_dye", - "id": 399 - }, - { - "name": "minecraft:green_glazed_terracotta", - "id": 233 - }, - { - "name": "minecraft:green_wool", - "id": -560 - }, - { - "name": "minecraft:grindstone", - "id": -195 - }, - { - "name": "minecraft:guardian_spawn_egg", - "id": 463 - }, - { - "name": "minecraft:gunpowder", - "id": 330 - }, - { - "name": "minecraft:hanging_roots", - "id": -319 - }, - { - "name": "minecraft:hard_glass", - "id": 253 - }, - { - "name": "minecraft:hard_glass_pane", - "id": 190 - }, - { - "name": "minecraft:hard_stained_glass", - "id": 254 - }, - { - "name": "minecraft:hard_stained_glass_pane", - "id": 191 - }, - { - "name": "minecraft:hardened_clay", - "id": 172 - }, - { - "name": "minecraft:hay_block", - "id": 170 - }, - { - "name": "minecraft:heart_of_the_sea", - "id": 578 - }, - { - "name": "minecraft:heart_pottery_sherd", - "id": 672 - }, - { - "name": "minecraft:heartbreak_pottery_sherd", - "id": 673 - }, - { - "name": "minecraft:heavy_weighted_pressure_plate", - "id": 148 - }, - { - "name": "minecraft:hoglin_spawn_egg", - "id": 498 - }, - { - "name": "minecraft:honey_block", - "id": -220 - }, - { - "name": "minecraft:honey_bottle", - "id": 599 - }, - { - "name": "minecraft:honeycomb", - "id": 598 - }, - { - "name": "minecraft:honeycomb_block", - "id": -221 - }, - { - "name": "minecraft:hopper", - "id": 534 - }, - { - "name": "minecraft:hopper_minecart", - "id": 533 - }, - { - "name": "minecraft:horn_coral", - "id": -584 - }, - { - "name": "minecraft:horse_spawn_egg", - "id": 460 - }, - { - "name": "minecraft:host_armor_trim_smithing_template", - "id": 700 - }, - { - "name": "minecraft:howl_pottery_sherd", - "id": 674 - }, - { - "name": "minecraft:husk_spawn_egg", - "id": 465 - }, - { - "name": "minecraft:ice", - "id": 79 - }, - { - "name": "minecraft:ice_bomb", - "id": 602 - }, - { - "name": "minecraft:infested_deepslate", - "id": -454 - }, - { - "name": "minecraft:info_update", - "id": 248 - }, - { - "name": "minecraft:info_update2", - "id": 249 - }, - { - "name": "minecraft:ink_sac", - "id": 415 - }, - { - "name": "minecraft:invisible_bedrock", - "id": 95 - }, - { - "name": "minecraft:iron_axe", - "id": 300 - }, - { - "name": "minecraft:iron_bars", - "id": 101 - }, - { - "name": "minecraft:iron_block", - "id": 42 - }, - { - "name": "minecraft:iron_boots", - "id": 348 - }, - { - "name": "minecraft:iron_chestplate", - "id": 346 - }, - { - "name": "minecraft:iron_door", - "id": 374 - }, - { - "name": "minecraft:iron_golem_spawn_egg", - "id": 506 - }, - { - "name": "minecraft:iron_helmet", - "id": 345 - }, - { - "name": "minecraft:iron_hoe", - "id": 333 - }, - { - "name": "minecraft:iron_horse_armor", - "id": 538 - }, - { - "name": "minecraft:iron_ingot", - "id": 307 - }, - { - "name": "minecraft:iron_leggings", - "id": 347 - }, - { - "name": "minecraft:iron_nugget", - "id": 576 - }, - { - "name": "minecraft:iron_ore", - "id": 15 - }, - { - "name": "minecraft:iron_pickaxe", - "id": 299 - }, - { - "name": "minecraft:iron_shovel", - "id": 298 - }, - { - "name": "minecraft:iron_sword", - "id": 309 - }, - { - "name": "minecraft:iron_trapdoor", - "id": 167 - }, - { - "name": "minecraft:item.acacia_door", - "id": 196 - }, - { - "name": "minecraft:item.bed", - "id": 26 - }, - { - "name": "minecraft:item.beetroot", - "id": 244 - }, - { - "name": "minecraft:item.birch_door", - "id": 194 - }, - { - "name": "minecraft:item.brewing_stand", - "id": 117 - }, - { - "name": "minecraft:item.cake", - "id": 92 - }, - { - "name": "minecraft:item.camera", - "id": 242 - }, - { - "name": "minecraft:item.campfire", - "id": -209 - }, - { - "name": "minecraft:item.cauldron", - "id": 118 - }, - { - "name": "minecraft:item.chain", - "id": -286 - }, - { - "name": "minecraft:item.crimson_door", - "id": -244 - }, - { - "name": "minecraft:item.dark_oak_door", - "id": 197 - }, - { - "name": "minecraft:item.flower_pot", - "id": 140 - }, - { - "name": "minecraft:item.frame", - "id": 199 - }, - { - "name": "minecraft:item.glow_frame", - "id": -339 - }, - { - "name": "minecraft:item.hopper", - "id": 154 - }, - { - "name": "minecraft:item.iron_door", - "id": 71 - }, - { - "name": "minecraft:item.jungle_door", - "id": 195 - }, - { - "name": "minecraft:item.kelp", - "id": -138 - }, - { - "name": "minecraft:item.mangrove_door", - "id": -493 - }, - { - "name": "minecraft:item.nether_sprouts", - "id": -238 - }, - { - "name": "minecraft:item.nether_wart", - "id": 115 - }, - { - "name": "minecraft:item.reeds", - "id": 83 - }, - { - "name": "minecraft:item.skull", - "id": 144 - }, - { - "name": "minecraft:item.soul_campfire", - "id": -290 - }, - { - "name": "minecraft:item.spruce_door", - "id": 193 - }, - { - "name": "minecraft:item.warped_door", - "id": -245 - }, - { - "name": "minecraft:item.wheat", - "id": 59 - }, - { - "name": "minecraft:item.wooden_door", - "id": 64 - }, - { - "name": "minecraft:jigsaw", - "id": -211 - }, - { - "name": "minecraft:jukebox", - "id": 84 - }, - { - "name": "minecraft:jungle_boat", - "id": 379 - }, - { - "name": "minecraft:jungle_button", - "id": -143 - }, - { - "name": "minecraft:jungle_chest_boat", - "id": 647 - }, - { - "name": "minecraft:jungle_door", - "id": 562 - }, - { - "name": "minecraft:jungle_fence", - "id": -578 - }, - { - "name": "minecraft:jungle_fence_gate", - "id": 185 - }, - { - "name": "minecraft:jungle_hanging_sign", - "id": -503 - }, - { - "name": "minecraft:jungle_log", - "id": -571 - }, - { - "name": "minecraft:jungle_pressure_plate", - "id": -153 - }, - { - "name": "minecraft:jungle_sign", - "id": 585 - }, - { - "name": "minecraft:jungle_stairs", - "id": 136 - }, - { - "name": "minecraft:jungle_standing_sign", - "id": -188 - }, - { - "name": "minecraft:jungle_trapdoor", - "id": -148 - }, - { - "name": "minecraft:jungle_wall_sign", - "id": -189 - }, - { - "name": "minecraft:kelp", - "id": 384 - }, - { - "name": "minecraft:ladder", - "id": 65 - }, - { - "name": "minecraft:lantern", - "id": -208 - }, - { - "name": "minecraft:lapis_block", - "id": 22 - }, - { - "name": "minecraft:lapis_lazuli", - "id": 416 - }, - { - "name": "minecraft:lapis_ore", - "id": 21 - }, - { - "name": "minecraft:large_amethyst_bud", - "id": -330 - }, - { - "name": "minecraft:lava", - "id": 11 - }, - { - "name": "minecraft:lava_bucket", - "id": 365 - }, - { - "name": "minecraft:lead", - "id": 554 - }, - { - "name": "minecraft:leather", - "id": 383 - }, - { - "name": "minecraft:leather_boots", - "id": 340 - }, - { - "name": "minecraft:leather_chestplate", - "id": 338 - }, - { - "name": "minecraft:leather_helmet", - "id": 337 - }, - { - "name": "minecraft:leather_horse_armor", - "id": 537 - }, - { - "name": "minecraft:leather_leggings", - "id": 339 - }, - { - "name": "minecraft:leaves", - "id": 18 - }, - { - "name": "minecraft:leaves2", - "id": 161 - }, - { - "name": "minecraft:lectern", - "id": -194 - }, - { - "name": "minecraft:lever", - "id": 69 - }, - { - "name": "minecraft:light_block", - "id": -215 - }, - { - "name": "minecraft:light_blue_candle", - "id": -416 - }, - { - "name": "minecraft:light_blue_candle_cake", - "id": -433 - }, - { - "name": "minecraft:light_blue_carpet", - "id": -599 - }, - { - "name": "minecraft:light_blue_dye", - "id": 409 - }, - { - "name": "minecraft:light_blue_glazed_terracotta", - "id": 223 - }, - { - "name": "minecraft:light_blue_wool", - "id": -562 - }, - { - "name": "minecraft:light_gray_candle", - "id": -421 - }, - { - "name": "minecraft:light_gray_candle_cake", - "id": -438 - }, - { - "name": "minecraft:light_gray_carpet", - "id": -604 - }, - { - "name": "minecraft:light_gray_dye", - "id": 404 - }, - { - "name": "minecraft:light_gray_wool", - "id": -552 - }, - { - "name": "minecraft:light_weighted_pressure_plate", - "id": 147 - }, - { - "name": "minecraft:lightning_rod", - "id": -312 - }, - { - "name": "minecraft:lime_candle", - "id": -418 - }, - { - "name": "minecraft:lime_candle_cake", - "id": -435 - }, - { - "name": "minecraft:lime_carpet", - "id": -601 - }, - { - "name": "minecraft:lime_dye", - "id": 407 - }, - { - "name": "minecraft:lime_glazed_terracotta", - "id": 225 - }, - { - "name": "minecraft:lime_wool", - "id": -559 - }, - { - "name": "minecraft:lingering_potion", - "id": 569 - }, - { - "name": "minecraft:lit_blast_furnace", - "id": -214 - }, - { - "name": "minecraft:lit_deepslate_redstone_ore", - "id": -404 - }, - { - "name": "minecraft:lit_furnace", - "id": 62 - }, - { - "name": "minecraft:lit_pumpkin", - "id": 91 - }, - { - "name": "minecraft:lit_redstone_lamp", - "id": 124 - }, - { - "name": "minecraft:lit_redstone_ore", - "id": 74 - }, - { - "name": "minecraft:lit_smoker", - "id": -199 - }, - { - "name": "minecraft:llama_spawn_egg", - "id": 475 - }, - { - "name": "minecraft:lodestone", - "id": -222 - }, - { - "name": "minecraft:lodestone_compass", - "id": 609 - }, - { - "name": "minecraft:log", - "id": 704 - }, - { - "name": "minecraft:log2", - "id": 707 - }, - { - "name": "minecraft:loom", - "id": -204 - }, - { - "name": "minecraft:magenta_candle", - "id": -415 - }, - { - "name": "minecraft:magenta_candle_cake", - "id": -432 - }, - { - "name": "minecraft:magenta_carpet", - "id": -598 - }, - { - "name": "minecraft:magenta_dye", - "id": 410 - }, - { - "name": "minecraft:magenta_glazed_terracotta", - "id": 222 - }, - { - "name": "minecraft:magenta_wool", - "id": -565 - }, - { - "name": "minecraft:magma", - "id": 213 - }, - { - "name": "minecraft:magma_cream", - "id": 432 - }, - { - "name": "minecraft:magma_cube_spawn_egg", - "id": 457 - }, - { - "name": "minecraft:mangrove_boat", - "id": 642 - }, - { - "name": "minecraft:mangrove_button", - "id": -487 - }, - { - "name": "minecraft:mangrove_chest_boat", - "id": 651 - }, - { - "name": "minecraft:mangrove_door", - "id": 640 - }, - { - "name": "minecraft:mangrove_double_slab", - "id": -499 - }, - { - "name": "minecraft:mangrove_fence", - "id": -491 - }, - { - "name": "minecraft:mangrove_fence_gate", - "id": -492 - }, - { - "name": "minecraft:mangrove_hanging_sign", - "id": -508 - }, - { - "name": "minecraft:mangrove_leaves", - "id": -472 - }, - { - "name": "minecraft:mangrove_log", - "id": -484 - }, - { - "name": "minecraft:mangrove_planks", - "id": -486 - }, - { - "name": "minecraft:mangrove_pressure_plate", - "id": -490 - }, - { - "name": "minecraft:mangrove_propagule", - "id": -474 - }, - { - "name": "minecraft:mangrove_roots", - "id": -482 - }, - { - "name": "minecraft:mangrove_sign", - "id": 641 - }, - { - "name": "minecraft:mangrove_slab", - "id": -489 - }, - { - "name": "minecraft:mangrove_stairs", - "id": -488 - }, - { - "name": "minecraft:mangrove_standing_sign", - "id": -494 - }, - { - "name": "minecraft:mangrove_trapdoor", - "id": -496 - }, - { - "name": "minecraft:mangrove_wall_sign", - "id": -495 - }, - { - "name": "minecraft:mangrove_wood", - "id": -497 - }, - { - "name": "minecraft:medicine", - "id": 606 - }, - { - "name": "minecraft:medium_amethyst_bud", - "id": -331 - }, - { - "name": "minecraft:melon_block", - "id": 103 - }, - { - "name": "minecraft:melon_seeds", - "id": 293 - }, - { - "name": "minecraft:melon_slice", - "id": 272 - }, - { - "name": "minecraft:melon_stem", - "id": 105 - }, - { - "name": "minecraft:milk_bucket", - "id": 363 - }, - { - "name": "minecraft:minecart", - "id": 372 - }, - { - "name": "minecraft:miner_pottery_sherd", - "id": 675 - }, - { - "name": "minecraft:mob_spawner", - "id": 52 - }, - { - "name": "minecraft:mojang_banner_pattern", - "id": 591 - }, - { - "name": "minecraft:monster_egg", - "id": 97 - }, - { - "name": "minecraft:mooshroom_spawn_egg", - "id": 442 - }, - { - "name": "minecraft:moss_block", - "id": -320 - }, - { - "name": "minecraft:moss_carpet", - "id": -335 - }, - { - "name": "minecraft:mossy_cobblestone", - "id": 48 - }, - { - "name": "minecraft:mossy_cobblestone_stairs", - "id": -179 - }, - { - "name": "minecraft:mossy_stone_brick_stairs", - "id": -175 - }, - { - "name": "minecraft:mourner_pottery_sherd", - "id": 676 - }, - { - "name": "minecraft:moving_block", - "id": 250 - }, - { - "name": "minecraft:mud", - "id": -473 - }, - { - "name": "minecraft:mud_brick_double_slab", - "id": -479 - }, - { - "name": "minecraft:mud_brick_slab", - "id": -478 - }, - { - "name": "minecraft:mud_brick_stairs", - "id": -480 - }, - { - "name": "minecraft:mud_brick_wall", - "id": -481 - }, - { - "name": "minecraft:mud_bricks", - "id": -475 - }, - { - "name": "minecraft:muddy_mangrove_roots", - "id": -483 - }, - { - "name": "minecraft:mule_spawn_egg", - "id": 468 - }, - { - "name": "minecraft:mushroom_stew", - "id": 260 - }, - { - "name": "minecraft:music_disc_11", - "id": 551 - }, - { - "name": "minecraft:music_disc_13", - "id": 541 - }, - { - "name": "minecraft:music_disc_5", - "id": 643 - }, - { - "name": "minecraft:music_disc_blocks", - "id": 543 - }, - { - "name": "minecraft:music_disc_cat", - "id": 542 - }, - { - "name": "minecraft:music_disc_chirp", - "id": 544 - }, - { - "name": "minecraft:music_disc_far", - "id": 545 - }, - { - "name": "minecraft:music_disc_mall", - "id": 546 - }, - { - "name": "minecraft:music_disc_mellohi", - "id": 547 - }, - { - "name": "minecraft:music_disc_otherside", - "id": 633 - }, - { - "name": "minecraft:music_disc_pigstep", - "id": 627 - }, - { - "name": "minecraft:music_disc_relic", - "id": 701 - }, - { - "name": "minecraft:music_disc_stal", - "id": 548 - }, - { - "name": "minecraft:music_disc_strad", - "id": 549 - }, - { - "name": "minecraft:music_disc_wait", - "id": 552 - }, - { - "name": "minecraft:music_disc_ward", - "id": 550 - }, - { - "name": "minecraft:mutton", - "id": 557 - }, - { - "name": "minecraft:mycelium", - "id": 110 - }, - { - "name": "minecraft:name_tag", - "id": 555 - }, - { - "name": "minecraft:nautilus_shell", - "id": 577 - }, - { - "name": "minecraft:nether_brick", - "id": 112 - }, - { - "name": "minecraft:nether_brick_fence", - "id": 113 - }, - { - "name": "minecraft:nether_brick_stairs", - "id": 114 - }, - { - "name": "minecraft:nether_gold_ore", - "id": -288 - }, - { - "name": "minecraft:nether_sprouts", - "id": 628 - }, - { - "name": "minecraft:nether_star", - "id": 525 - }, - { - "name": "minecraft:nether_wart", - "id": 294 - }, - { - "name": "minecraft:nether_wart_block", - "id": 214 - }, - { - "name": "minecraft:netherbrick", - "id": 530 - }, - { - "name": "minecraft:netherite_axe", - "id": 613 - }, - { - "name": "minecraft:netherite_block", - "id": -270 - }, - { - "name": "minecraft:netherite_boots", - "id": 619 - }, - { - "name": "minecraft:netherite_chestplate", - "id": 617 - }, - { - "name": "minecraft:netherite_helmet", - "id": 616 - }, - { - "name": "minecraft:netherite_hoe", - "id": 614 - }, - { - "name": "minecraft:netherite_ingot", - "id": 615 - }, - { - "name": "minecraft:netherite_leggings", - "id": 618 - }, - { - "name": "minecraft:netherite_pickaxe", - "id": 612 - }, - { - "name": "minecraft:netherite_scrap", - "id": 620 - }, - { - "name": "minecraft:netherite_shovel", - "id": 611 - }, - { - "name": "minecraft:netherite_sword", - "id": 610 - }, - { - "name": "minecraft:netherite_upgrade_smithing_template", - "id": 684 - }, - { - "name": "minecraft:netherrack", - "id": 87 - }, - { - "name": "minecraft:netherreactor", - "id": 247 - }, - { - "name": "minecraft:normal_stone_stairs", - "id": -180 - }, - { - "name": "minecraft:noteblock", - "id": 25 - }, - { - "name": "minecraft:npc_spawn_egg", - "id": 472 - }, - { - "name": "minecraft:oak_boat", - "id": 377 - }, - { - "name": "minecraft:oak_chest_boat", - "id": 645 - }, - { - "name": "minecraft:oak_fence", - "id": 85 - }, - { - "name": "minecraft:oak_hanging_sign", - "id": -500 - }, - { - "name": "minecraft:oak_log", - "id": 17 - }, - { - "name": "minecraft:oak_sign", - "id": 360 - }, - { - "name": "minecraft:oak_stairs", - "id": 53 - }, - { - "name": "minecraft:observer", - "id": 251 - }, - { - "name": "minecraft:obsidian", - "id": 49 - }, - { - "name": "minecraft:ocelot_spawn_egg", - "id": 453 - }, - { - "name": "minecraft:ochre_froglight", - "id": -471 - }, - { - "name": "minecraft:orange_candle", - "id": -414 - }, - { - "name": "minecraft:orange_candle_cake", - "id": -431 - }, - { - "name": "minecraft:orange_carpet", - "id": -597 - }, - { - "name": "minecraft:orange_dye", - "id": 411 - }, - { - "name": "minecraft:orange_glazed_terracotta", - "id": 221 - }, - { - "name": "minecraft:orange_wool", - "id": -557 - }, - { - "name": "minecraft:oxidized_copper", - "id": -343 - }, - { - "name": "minecraft:oxidized_cut_copper", - "id": -350 - }, - { - "name": "minecraft:oxidized_cut_copper_slab", - "id": -364 - }, - { - "name": "minecraft:oxidized_cut_copper_stairs", - "id": -357 - }, - { - "name": "minecraft:oxidized_double_cut_copper_slab", - "id": -371 - }, - { - "name": "minecraft:packed_ice", - "id": 174 - }, - { - "name": "minecraft:packed_mud", - "id": -477 - }, - { - "name": "minecraft:painting", - "id": 359 - }, - { - "name": "minecraft:panda_spawn_egg", - "id": 491 - }, - { - "name": "minecraft:paper", - "id": 388 - }, - { - "name": "minecraft:parrot_spawn_egg", - "id": 480 - }, - { - "name": "minecraft:pearlescent_froglight", - "id": -469 - }, - { - "name": "minecraft:phantom_membrane", - "id": 581 - }, - { - "name": "minecraft:phantom_spawn_egg", - "id": 488 - }, - { - "name": "minecraft:pig_spawn_egg", - "id": 439 - }, - { - "name": "minecraft:piglin_banner_pattern", - "id": 594 - }, - { - "name": "minecraft:piglin_brute_spawn_egg", - "id": 501 - }, - { - "name": "minecraft:piglin_spawn_egg", - "id": 499 - }, - { - "name": "minecraft:pillager_spawn_egg", - "id": 493 - }, - { - "name": "minecraft:pink_candle", - "id": -419 - }, - { - "name": "minecraft:pink_candle_cake", - "id": -436 - }, - { - "name": "minecraft:pink_carpet", - "id": -602 - }, - { - "name": "minecraft:pink_dye", - "id": 406 - }, - { - "name": "minecraft:pink_glazed_terracotta", - "id": 226 - }, - { - "name": "minecraft:pink_petals", - "id": -549 - }, - { - "name": "minecraft:pink_wool", - "id": -566 - }, - { - "name": "minecraft:piston", - "id": 33 - }, - { - "name": "minecraft:piston_arm_collision", - "id": 34 - }, - { - "name": "minecraft:pitcher_crop", - "id": -574 - }, - { - "name": "minecraft:pitcher_plant", - "id": -612 - }, - { - "name": "minecraft:pitcher_pod", - "id": 297 - }, - { - "name": "minecraft:planks", - "id": 5 - }, - { - "name": "minecraft:plenty_pottery_sherd", - "id": 677 - }, - { - "name": "minecraft:podzol", - "id": 243 - }, - { - "name": "minecraft:pointed_dripstone", - "id": -308 - }, - { - "name": "minecraft:poisonous_potato", - "id": 282 - }, - { - "name": "minecraft:polar_bear_spawn_egg", - "id": 474 - }, - { - "name": "minecraft:polished_andesite_stairs", - "id": -174 - }, - { - "name": "minecraft:polished_basalt", - "id": -235 - }, - { - "name": "minecraft:polished_blackstone", - "id": -291 - }, - { - "name": "minecraft:polished_blackstone_brick_double_slab", - "id": -285 - }, - { - "name": "minecraft:polished_blackstone_brick_slab", - "id": -284 - }, - { - "name": "minecraft:polished_blackstone_brick_stairs", - "id": -275 - }, - { - "name": "minecraft:polished_blackstone_brick_wall", - "id": -278 - }, - { - "name": "minecraft:polished_blackstone_bricks", - "id": -274 - }, - { - "name": "minecraft:polished_blackstone_button", - "id": -296 - }, - { - "name": "minecraft:polished_blackstone_double_slab", - "id": -294 - }, - { - "name": "minecraft:polished_blackstone_pressure_plate", - "id": -295 - }, - { - "name": "minecraft:polished_blackstone_slab", - "id": -293 - }, - { - "name": "minecraft:polished_blackstone_stairs", - "id": -292 - }, - { - "name": "minecraft:polished_blackstone_wall", - "id": -297 - }, - { - "name": "minecraft:polished_deepslate", - "id": -383 - }, - { - "name": "minecraft:polished_deepslate_double_slab", - "id": -397 - }, - { - "name": "minecraft:polished_deepslate_slab", - "id": -384 - }, - { - "name": "minecraft:polished_deepslate_stairs", - "id": -385 - }, - { - "name": "minecraft:polished_deepslate_wall", - "id": -386 - }, - { - "name": "minecraft:polished_diorite_stairs", - "id": -173 - }, - { - "name": "minecraft:polished_granite_stairs", - "id": -172 - }, - { - "name": "minecraft:popped_chorus_fruit", - "id": 566 - }, - { - "name": "minecraft:porkchop", - "id": 262 - }, - { - "name": "minecraft:portal", - "id": 90 - }, - { - "name": "minecraft:potato", - "id": 280 - }, - { - "name": "minecraft:potatoes", - "id": 142 - }, - { - "name": "minecraft:potion", - "id": 428 - }, - { - "name": "minecraft:powder_snow", - "id": -306 - }, - { - "name": "minecraft:powder_snow_bucket", - "id": 370 - }, - { - "name": "minecraft:powered_comparator", - "id": 150 - }, - { - "name": "minecraft:powered_repeater", - "id": 94 - }, - { - "name": "minecraft:prismarine", - "id": 168 - }, - { - "name": "minecraft:prismarine_bricks_stairs", - "id": -4 - }, - { - "name": "minecraft:prismarine_crystals", - "id": 556 - }, - { - "name": "minecraft:prismarine_shard", - "id": 572 - }, - { - "name": "minecraft:prismarine_stairs", - "id": -2 - }, - { - "name": "minecraft:prize_pottery_sherd", - "id": 678 - }, - { - "name": "minecraft:pufferfish", - "id": 267 - }, - { - "name": "minecraft:pufferfish_bucket", - "id": 369 - }, - { - "name": "minecraft:pufferfish_spawn_egg", - "id": 483 - }, - { - "name": "minecraft:pumpkin", - "id": 86 - }, - { - "name": "minecraft:pumpkin_pie", - "id": 284 - }, - { - "name": "minecraft:pumpkin_seeds", - "id": 292 - }, - { - "name": "minecraft:pumpkin_stem", - "id": 104 - }, - { - "name": "minecraft:purple_candle", - "id": -423 - }, - { - "name": "minecraft:purple_candle_cake", - "id": -440 - }, - { - "name": "minecraft:purple_carpet", - "id": -606 - }, - { - "name": "minecraft:purple_dye", - "id": 402 - }, - { - "name": "minecraft:purple_glazed_terracotta", - "id": 219 - }, - { - "name": "minecraft:purple_wool", - "id": -564 - }, - { - "name": "minecraft:purpur_block", - "id": 201 - }, - { - "name": "minecraft:purpur_stairs", - "id": 203 - }, - { - "name": "minecraft:quartz", - "id": 531 - }, - { - "name": "minecraft:quartz_block", - "id": 155 - }, - { - "name": "minecraft:quartz_bricks", - "id": -304 - }, - { - "name": "minecraft:quartz_ore", - "id": 153 - }, - { - "name": "minecraft:quartz_stairs", - "id": 156 - }, - { - "name": "minecraft:rabbit", - "id": 288 - }, - { - "name": "minecraft:rabbit_foot", - "id": 535 - }, - { - "name": "minecraft:rabbit_hide", - "id": 536 - }, - { - "name": "minecraft:rabbit_spawn_egg", - "id": 461 - }, - { - "name": "minecraft:rabbit_stew", - "id": 290 - }, - { - "name": "minecraft:rail", - "id": 66 - }, - { - "name": "minecraft:raiser_armor_trim_smithing_template", - "id": 698 - }, - { - "name": "minecraft:rapid_fertilizer", - "id": 604 - }, - { - "name": "minecraft:ravager_spawn_egg", - "id": 495 - }, - { - "name": "minecraft:raw_copper", - "id": 514 - }, - { - "name": "minecraft:raw_copper_block", - "id": -452 - }, - { - "name": "minecraft:raw_gold", - "id": 513 - }, - { - "name": "minecraft:raw_gold_block", - "id": -453 - }, - { - "name": "minecraft:raw_iron", - "id": 512 - }, - { - "name": "minecraft:raw_iron_block", - "id": -451 - }, - { - "name": "minecraft:recovery_compass", - "id": 653 - }, - { - "name": "minecraft:red_candle", - "id": -427 - }, - { - "name": "minecraft:red_candle_cake", - "id": -444 - }, - { - "name": "minecraft:red_carpet", - "id": -610 - }, - { - "name": "minecraft:red_dye", - "id": 398 - }, - { - "name": "minecraft:red_flower", - "id": 38 - }, - { - "name": "minecraft:red_glazed_terracotta", - "id": 234 - }, - { - "name": "minecraft:red_mushroom", - "id": 40 - }, - { - "name": "minecraft:red_mushroom_block", - "id": 100 - }, - { - "name": "minecraft:red_nether_brick", - "id": 215 - }, - { - "name": "minecraft:red_nether_brick_stairs", - "id": -184 - }, - { - "name": "minecraft:red_sandstone", - "id": 179 - }, - { - "name": "minecraft:red_sandstone_stairs", - "id": 180 - }, - { - "name": "minecraft:red_wool", - "id": -556 - }, - { - "name": "minecraft:redstone", - "id": 375 - }, - { - "name": "minecraft:redstone_block", - "id": 152 - }, - { - "name": "minecraft:redstone_lamp", - "id": 123 - }, - { - "name": "minecraft:redstone_ore", - "id": 73 - }, - { - "name": "minecraft:redstone_torch", - "id": 76 - }, - { - "name": "minecraft:redstone_wire", - "id": 55 - }, - { - "name": "minecraft:reinforced_deepslate", - "id": -466 - }, - { - "name": "minecraft:repeater", - "id": 421 - }, - { - "name": "minecraft:repeating_command_block", - "id": 188 - }, - { - "name": "minecraft:reserved6", - "id": 255 - }, - { - "name": "minecraft:respawn_anchor", - "id": -272 - }, - { - "name": "minecraft:rib_armor_trim_smithing_template", - "id": 694 - }, - { - "name": "minecraft:rotten_flesh", - "id": 277 - }, - { - "name": "minecraft:saddle", - "id": 373 - }, - { - "name": "minecraft:salmon", - "id": 265 - }, - { - "name": "minecraft:salmon_bucket", - "id": 367 - }, - { - "name": "minecraft:salmon_spawn_egg", - "id": 484 - }, - { - "name": "minecraft:sand", - "id": 12 - }, - { - "name": "minecraft:sandstone", - "id": 24 - }, - { - "name": "minecraft:sandstone_stairs", - "id": 128 - }, - { - "name": "minecraft:sapling", - "id": 6 - }, - { - "name": "minecraft:scaffolding", - "id": -165 - }, - { - "name": "minecraft:sculk", - "id": -458 - }, - { - "name": "minecraft:sculk_catalyst", - "id": -460 - }, - { - "name": "minecraft:sculk_sensor", - "id": -307 - }, - { - "name": "minecraft:sculk_shrieker", - "id": -461 - }, - { - "name": "minecraft:sculk_vein", - "id": -459 - }, - { - "name": "minecraft:scute", - "id": 579 - }, - { - "name": "minecraft:sea_lantern", - "id": 169 - }, - { - "name": "minecraft:sea_pickle", - "id": -156 - }, - { - "name": "minecraft:seagrass", - "id": -130 - }, - { - "name": "minecraft:sentry_armor_trim_smithing_template", - "id": 685 - }, - { - "name": "minecraft:shaper_armor_trim_smithing_template", - "id": 699 - }, - { - "name": "minecraft:sheaf_pottery_sherd", - "id": 679 - }, - { - "name": "minecraft:shears", - "id": 423 - }, - { - "name": "minecraft:sheep_spawn_egg", - "id": 440 - }, - { - "name": "minecraft:shelter_pottery_sherd", - "id": 680 - }, - { - "name": "minecraft:shield", - "id": 357 - }, - { - "name": "minecraft:shroomlight", - "id": -230 - }, - { - "name": "minecraft:shulker_box", - "id": 218 - }, - { - "name": "minecraft:shulker_shell", - "id": 573 - }, - { - "name": "minecraft:shulker_spawn_egg", - "id": 471 - }, - { - "name": "minecraft:silence_armor_trim_smithing_template", - "id": 696 - }, - { - "name": "minecraft:silver_glazed_terracotta", - "id": 228 - }, - { - "name": "minecraft:silverfish_spawn_egg", - "id": 445 - }, - { - "name": "minecraft:skeleton_horse_spawn_egg", - "id": 469 - }, - { - "name": "minecraft:skeleton_spawn_egg", - "id": 446 - }, - { - "name": "minecraft:skull", - "id": 523 - }, - { - "name": "minecraft:skull_banner_pattern", - "id": 590 - }, - { - "name": "minecraft:skull_pottery_sherd", - "id": 681 - }, - { - "name": "minecraft:slime", - "id": 165 - }, - { - "name": "minecraft:slime_ball", - "id": 390 - }, - { - "name": "minecraft:slime_spawn_egg", - "id": 447 - }, - { - "name": "minecraft:small_amethyst_bud", - "id": -332 - }, - { - "name": "minecraft:small_dripleaf_block", - "id": -336 - }, - { - "name": "minecraft:smithing_table", - "id": -202 - }, - { - "name": "minecraft:smoker", - "id": -198 - }, - { - "name": "minecraft:smooth_basalt", - "id": -377 - }, - { - "name": "minecraft:smooth_quartz_stairs", - "id": -185 - }, - { - "name": "minecraft:smooth_red_sandstone_stairs", - "id": -176 - }, - { - "name": "minecraft:smooth_sandstone_stairs", - "id": -177 - }, - { - "name": "minecraft:smooth_stone", - "id": -183 - }, - { - "name": "minecraft:sniffer_egg", - "id": -596 - }, - { - "name": "minecraft:sniffer_spawn_egg", - "id": 502 - }, - { - "name": "minecraft:snort_pottery_sherd", - "id": 682 - }, - { - "name": "minecraft:snout_armor_trim_smithing_template", - "id": 693 - }, - { - "name": "minecraft:snow", - "id": 80 - }, - { - "name": "minecraft:snow_golem_spawn_egg", - "id": 507 - }, - { - "name": "minecraft:snow_layer", - "id": 78 - }, - { - "name": "minecraft:snowball", - "id": 376 - }, - { - "name": "minecraft:soul_campfire", - "id": 629 - }, - { - "name": "minecraft:soul_fire", - "id": -237 - }, - { - "name": "minecraft:soul_lantern", - "id": -269 - }, - { - "name": "minecraft:soul_sand", - "id": 88 - }, - { - "name": "minecraft:soul_soil", - "id": -236 - }, - { - "name": "minecraft:soul_torch", - "id": -268 - }, - { - "name": "minecraft:sparkler", - "id": 607 - }, - { - "name": "minecraft:spawn_egg", - "id": 711 - }, - { - "name": "minecraft:spider_eye", - "id": 278 - }, - { - "name": "minecraft:spider_spawn_egg", - "id": 448 - }, - { - "name": "minecraft:spire_armor_trim_smithing_template", - "id": 695 - }, - { - "name": "minecraft:splash_potion", - "id": 568 - }, - { - "name": "minecraft:sponge", - "id": 19 - }, - { - "name": "minecraft:spore_blossom", - "id": -321 - }, - { - "name": "minecraft:spruce_boat", - "id": 380 - }, - { - "name": "minecraft:spruce_button", - "id": -144 - }, - { - "name": "minecraft:spruce_chest_boat", - "id": 648 - }, - { - "name": "minecraft:spruce_door", - "id": 560 - }, - { - "name": "minecraft:spruce_fence", - "id": -579 - }, - { - "name": "minecraft:spruce_fence_gate", - "id": 183 - }, - { - "name": "minecraft:spruce_hanging_sign", - "id": -501 - }, - { - "name": "minecraft:spruce_log", - "id": -569 - }, - { - "name": "minecraft:spruce_pressure_plate", - "id": -154 - }, - { - "name": "minecraft:spruce_sign", - "id": 583 - }, - { - "name": "minecraft:spruce_stairs", - "id": 134 - }, - { - "name": "minecraft:spruce_standing_sign", - "id": -181 - }, - { - "name": "minecraft:spruce_trapdoor", - "id": -149 - }, - { - "name": "minecraft:spruce_wall_sign", - "id": -182 - }, - { - "name": "minecraft:spyglass", - "id": 632 - }, - { - "name": "minecraft:squid_spawn_egg", - "id": 452 - }, - { - "name": "minecraft:stained_glass", - "id": 241 - }, - { - "name": "minecraft:stained_glass_pane", - "id": 160 - }, - { - "name": "minecraft:stained_hardened_clay", - "id": 159 - }, - { - "name": "minecraft:standing_banner", - "id": 176 - }, - { - "name": "minecraft:standing_sign", - "id": 63 - }, - { - "name": "minecraft:stick", - "id": 322 - }, - { - "name": "minecraft:sticky_piston", - "id": 29 - }, - { - "name": "minecraft:sticky_piston_arm_collision", - "id": -217 - }, - { - "name": "minecraft:stone", - "id": 1 - }, - { - "name": "minecraft:stone_axe", - "id": 317 - }, - { - "name": "minecraft:stone_block_slab", - "id": 44 - }, - { - "name": "minecraft:stone_block_slab2", - "id": 182 - }, - { - "name": "minecraft:stone_block_slab3", - "id": -162 - }, - { - "name": "minecraft:stone_block_slab4", - "id": -166 - }, - { - "name": "minecraft:stone_brick_stairs", - "id": 109 - }, - { - "name": "minecraft:stone_button", - "id": 77 - }, - { - "name": "minecraft:stone_hoe", - "id": 332 - }, - { - "name": "minecraft:stone_pickaxe", - "id": 316 - }, - { - "name": "minecraft:stone_pressure_plate", - "id": 70 - }, - { - "name": "minecraft:stone_shovel", - "id": 315 - }, - { - "name": "minecraft:stone_stairs", - "id": 67 - }, - { - "name": "minecraft:stone_sword", - "id": 314 - }, - { - "name": "minecraft:stonebrick", - "id": 98 - }, - { - "name": "minecraft:stonecutter", - "id": 245 - }, - { - "name": "minecraft:stonecutter_block", - "id": -197 - }, - { - "name": "minecraft:stray_spawn_egg", - "id": 464 - }, - { - "name": "minecraft:strider_spawn_egg", - "id": 497 - }, - { - "name": "minecraft:string", - "id": 328 - }, - { - "name": "minecraft:stripped_acacia_log", - "id": -8 - }, - { - "name": "minecraft:stripped_bamboo_block", - "id": -528 - }, - { - "name": "minecraft:stripped_birch_log", - "id": -6 - }, - { - "name": "minecraft:stripped_cherry_log", - "id": -535 - }, - { - "name": "minecraft:stripped_cherry_wood", - "id": -545 - }, - { - "name": "minecraft:stripped_crimson_hyphae", - "id": -300 - }, - { - "name": "minecraft:stripped_crimson_stem", - "id": -240 - }, - { - "name": "minecraft:stripped_dark_oak_log", - "id": -9 - }, - { - "name": "minecraft:stripped_jungle_log", - "id": -7 - }, - { - "name": "minecraft:stripped_mangrove_log", - "id": -485 - }, - { - "name": "minecraft:stripped_mangrove_wood", - "id": -498 - }, - { - "name": "minecraft:stripped_oak_log", - "id": -10 - }, - { - "name": "minecraft:stripped_spruce_log", - "id": -5 - }, - { - "name": "minecraft:stripped_warped_hyphae", - "id": -301 - }, - { - "name": "minecraft:stripped_warped_stem", - "id": -241 - }, - { - "name": "minecraft:structure_block", - "id": 252 - }, - { - "name": "minecraft:structure_void", - "id": 217 - }, - { - "name": "minecraft:sugar", - "id": 418 - }, - { - "name": "minecraft:sugar_cane", - "id": 387 - }, - { - "name": "minecraft:suspicious_gravel", - "id": -573 - }, - { - "name": "minecraft:suspicious_sand", - "id": -529 - }, - { - "name": "minecraft:suspicious_stew", - "id": 597 - }, - { - "name": "minecraft:sweet_berries", - "id": 287 - }, - { - "name": "minecraft:sweet_berry_bush", - "id": -207 - }, - { - "name": "minecraft:tadpole_bucket", - "id": 637 - }, - { - "name": "minecraft:tadpole_spawn_egg", - "id": 636 - }, - { - "name": "minecraft:tallgrass", - "id": 31 - }, - { - "name": "minecraft:target", - "id": -239 - }, - { - "name": "minecraft:tide_armor_trim_smithing_template", - "id": 692 - }, - { - "name": "minecraft:tinted_glass", - "id": -334 - }, - { - "name": "minecraft:tnt", - "id": 46 - }, - { - "name": "minecraft:tnt_minecart", - "id": 532 - }, - { - "name": "minecraft:torch", - "id": 50 - }, - { - "name": "minecraft:torchflower", - "id": -568 - }, - { - "name": "minecraft:torchflower_crop", - "id": -567 - }, - { - "name": "minecraft:torchflower_seeds", - "id": 296 - }, - { - "name": "minecraft:totem_of_undying", - "id": 575 - }, - { - "name": "minecraft:trader_llama_spawn_egg", - "id": 655 - }, - { - "name": "minecraft:trapdoor", - "id": 96 - }, - { - "name": "minecraft:trapped_chest", - "id": 146 - }, - { - "name": "minecraft:trident", - "id": 553 - }, - { - "name": "minecraft:trip_wire", - "id": 132 - }, - { - "name": "minecraft:tripwire_hook", - "id": 131 - }, - { - "name": "minecraft:tropical_fish", - "id": 266 - }, - { - "name": "minecraft:tropical_fish_bucket", - "id": 368 - }, - { - "name": "minecraft:tropical_fish_spawn_egg", - "id": 481 - }, - { - "name": "minecraft:tube_coral", - "id": -131 - }, - { - "name": "minecraft:tuff", - "id": -333 - }, - { - "name": "minecraft:turtle_egg", - "id": -159 - }, - { - "name": "minecraft:turtle_helmet", - "id": 580 - }, - { - "name": "minecraft:turtle_spawn_egg", - "id": 487 - }, - { - "name": "minecraft:twisting_vines", - "id": -287 - }, - { - "name": "minecraft:underwater_torch", - "id": 239 - }, - { - "name": "minecraft:undyed_shulker_box", - "id": 205 - }, - { - "name": "minecraft:unknown", - "id": -305 - }, - { - "name": "minecraft:unlit_redstone_torch", - "id": 75 - }, - { - "name": "minecraft:unpowered_comparator", - "id": 149 - }, - { - "name": "minecraft:unpowered_repeater", - "id": 93 - }, - { - "name": "minecraft:verdant_froglight", - "id": -470 - }, - { - "name": "minecraft:vex_armor_trim_smithing_template", - "id": 691 - }, - { - "name": "minecraft:vex_spawn_egg", - "id": 478 - }, - { - "name": "minecraft:villager_spawn_egg", - "id": 451 - }, - { - "name": "minecraft:vindicator_spawn_egg", - "id": 476 - }, - { - "name": "minecraft:vine", - "id": 106 - }, - { - "name": "minecraft:wall_banner", - "id": 177 - }, - { - "name": "minecraft:wall_sign", - "id": 68 - }, - { - "name": "minecraft:wandering_trader_spawn_egg", - "id": 494 - }, - { - "name": "minecraft:ward_armor_trim_smithing_template", - "id": 689 - }, - { - "name": "minecraft:warden_spawn_egg", - "id": 639 - }, - { - "name": "minecraft:warped_button", - "id": -261 - }, - { - "name": "minecraft:warped_door", - "id": 624 - }, - { - "name": "minecraft:warped_double_slab", - "id": -267 - }, - { - "name": "minecraft:warped_fence", - "id": -257 - }, - { - "name": "minecraft:warped_fence_gate", - "id": -259 - }, - { - "name": "minecraft:warped_fungus", - "id": -229 - }, - { - "name": "minecraft:warped_fungus_on_a_stick", - "id": 625 - }, - { - "name": "minecraft:warped_hanging_sign", - "id": -507 - }, - { - "name": "minecraft:warped_hyphae", - "id": -298 - }, - { - "name": "minecraft:warped_nylium", - "id": -233 - }, - { - "name": "minecraft:warped_planks", - "id": -243 - }, - { - "name": "minecraft:warped_pressure_plate", - "id": -263 - }, - { - "name": "minecraft:warped_roots", - "id": -224 - }, - { - "name": "minecraft:warped_sign", - "id": 622 - }, - { - "name": "minecraft:warped_slab", - "id": -265 - }, - { - "name": "minecraft:warped_stairs", - "id": -255 - }, - { - "name": "minecraft:warped_standing_sign", - "id": -251 - }, - { - "name": "minecraft:warped_stem", - "id": -226 - }, - { - "name": "minecraft:warped_trapdoor", - "id": -247 - }, - { - "name": "minecraft:warped_wall_sign", - "id": -253 - }, - { - "name": "minecraft:warped_wart_block", - "id": -227 - }, - { - "name": "minecraft:water", - "id": 9 - }, - { - "name": "minecraft:water_bucket", - "id": 364 - }, - { - "name": "minecraft:waterlily", - "id": 111 - }, - { - "name": "minecraft:waxed_copper", - "id": -344 - }, - { - "name": "minecraft:waxed_cut_copper", - "id": -351 - }, - { - "name": "minecraft:waxed_cut_copper_slab", - "id": -365 - }, - { - "name": "minecraft:waxed_cut_copper_stairs", - "id": -358 - }, - { - "name": "minecraft:waxed_double_cut_copper_slab", - "id": -372 - }, - { - "name": "minecraft:waxed_exposed_copper", - "id": -345 - }, - { - "name": "minecraft:waxed_exposed_cut_copper", - "id": -352 - }, - { - "name": "minecraft:waxed_exposed_cut_copper_slab", - "id": -366 - }, - { - "name": "minecraft:waxed_exposed_cut_copper_stairs", - "id": -359 - }, - { - "name": "minecraft:waxed_exposed_double_cut_copper_slab", - "id": -373 - }, - { - "name": "minecraft:waxed_oxidized_copper", - "id": -446 - }, - { - "name": "minecraft:waxed_oxidized_cut_copper", - "id": -447 - }, - { - "name": "minecraft:waxed_oxidized_cut_copper_slab", - "id": -449 - }, - { - "name": "minecraft:waxed_oxidized_cut_copper_stairs", - "id": -448 - }, - { - "name": "minecraft:waxed_oxidized_double_cut_copper_slab", - "id": -450 - }, - { - "name": "minecraft:waxed_weathered_copper", - "id": -346 - }, - { - "name": "minecraft:waxed_weathered_cut_copper", - "id": -353 - }, - { - "name": "minecraft:waxed_weathered_cut_copper_slab", - "id": -367 - }, - { - "name": "minecraft:waxed_weathered_cut_copper_stairs", - "id": -360 - }, - { - "name": "minecraft:waxed_weathered_double_cut_copper_slab", - "id": -374 - }, - { - "name": "minecraft:wayfinder_armor_trim_smithing_template", - "id": 697 - }, - { - "name": "minecraft:weathered_copper", - "id": -342 - }, - { - "name": "minecraft:weathered_cut_copper", - "id": -349 - }, - { - "name": "minecraft:weathered_cut_copper_slab", - "id": -363 - }, - { - "name": "minecraft:weathered_cut_copper_stairs", - "id": -356 - }, - { - "name": "minecraft:weathered_double_cut_copper_slab", - "id": -370 - }, - { - "name": "minecraft:web", - "id": 30 - }, - { - "name": "minecraft:weeping_vines", - "id": -231 - }, - { - "name": "minecraft:wheat", - "id": 336 - }, - { - "name": "minecraft:wheat_seeds", - "id": 291 - }, - { - "name": "minecraft:white_candle", - "id": -413 - }, - { - "name": "minecraft:white_candle_cake", - "id": -430 - }, - { - "name": "minecraft:white_carpet", - "id": 171 - }, - { - "name": "minecraft:white_dye", - "id": 412 - }, - { - "name": "minecraft:white_glazed_terracotta", - "id": 220 - }, - { - "name": "minecraft:white_wool", - "id": 35 - }, - { - "name": "minecraft:wild_armor_trim_smithing_template", - "id": 688 - }, - { - "name": "minecraft:witch_spawn_egg", - "id": 454 - }, - { - "name": "minecraft:wither_rose", - "id": -216 - }, - { - "name": "minecraft:wither_skeleton_spawn_egg", - "id": 466 - }, - { - "name": "minecraft:wither_spawn_egg", - "id": 509 - }, - { - "name": "minecraft:wolf_spawn_egg", - "id": 441 - }, - { - "name": "minecraft:wood", - "id": -212 - }, - { - "name": "minecraft:wooden_axe", - "id": 313 - }, - { - "name": "minecraft:wooden_button", - "id": 143 - }, - { - "name": "minecraft:wooden_door", - "id": 361 - }, - { - "name": "minecraft:wooden_hoe", - "id": 331 - }, - { - "name": "minecraft:wooden_pickaxe", - "id": 312 - }, - { - "name": "minecraft:wooden_pressure_plate", - "id": 72 - }, - { - "name": "minecraft:wooden_shovel", - "id": 311 - }, - { - "name": "minecraft:wooden_slab", - "id": 158 - }, - { - "name": "minecraft:wooden_sword", - "id": 310 - }, - { - "name": "minecraft:wool", - "id": 702 - }, - { - "name": "minecraft:writable_book", - "id": 517 - }, - { - "name": "minecraft:written_book", - "id": 518 - }, - { - "name": "minecraft:yellow_candle", - "id": -417 - }, - { - "name": "minecraft:yellow_candle_cake", - "id": -434 - }, - { - "name": "minecraft:yellow_carpet", - "id": -600 - }, - { - "name": "minecraft:yellow_dye", - "id": 408 - }, - { - "name": "minecraft:yellow_flower", - "id": 37 - }, - { - "name": "minecraft:yellow_glazed_terracotta", - "id": 224 - }, - { - "name": "minecraft:yellow_wool", - "id": -558 - }, - { - "name": "minecraft:zoglin_spawn_egg", - "id": 500 - }, - { - "name": "minecraft:zombie_horse_spawn_egg", - "id": 470 - }, - { - "name": "minecraft:zombie_pigman_spawn_egg", - "id": 450 - }, - { - "name": "minecraft:zombie_spawn_egg", - "id": 449 - }, - { - "name": "minecraft:zombie_villager_spawn_egg", - "id": 479 - } -] \ No newline at end of file diff --git a/core/src/main/resources/bedrock/runtime_item_states.1_20_10.json b/core/src/main/resources/bedrock/runtime_item_states.1_20_10.json deleted file mode 100644 index 3625f3045..000000000 --- a/core/src/main/resources/bedrock/runtime_item_states.1_20_10.json +++ /dev/null @@ -1,5314 +0,0 @@ -[ - { - "name": "minecraft:acacia_boat", - "id": 381 - }, - { - "name": "minecraft:acacia_button", - "id": -140 - }, - { - "name": "minecraft:acacia_chest_boat", - "id": 649 - }, - { - "name": "minecraft:acacia_door", - "id": 563 - }, - { - "name": "minecraft:acacia_fence", - "id": -575 - }, - { - "name": "minecraft:acacia_fence_gate", - "id": 187 - }, - { - "name": "minecraft:acacia_hanging_sign", - "id": -504 - }, - { - "name": "minecraft:acacia_log", - "id": 162 - }, - { - "name": "minecraft:acacia_pressure_plate", - "id": -150 - }, - { - "name": "minecraft:acacia_sign", - "id": 586 - }, - { - "name": "minecraft:acacia_stairs", - "id": 163 - }, - { - "name": "minecraft:acacia_standing_sign", - "id": -190 - }, - { - "name": "minecraft:acacia_trapdoor", - "id": -145 - }, - { - "name": "minecraft:acacia_wall_sign", - "id": -191 - }, - { - "name": "minecraft:activator_rail", - "id": 126 - }, - { - "name": "minecraft:agent_spawn_egg", - "id": 489 - }, - { - "name": "minecraft:air", - "id": -158 - }, - { - "name": "minecraft:allay_spawn_egg", - "id": 638 - }, - { - "name": "minecraft:allow", - "id": 210 - }, - { - "name": "minecraft:amethyst_block", - "id": -327 - }, - { - "name": "minecraft:amethyst_cluster", - "id": -329 - }, - { - "name": "minecraft:amethyst_shard", - "id": 631 - }, - { - "name": "minecraft:ancient_debris", - "id": -271 - }, - { - "name": "minecraft:andesite_stairs", - "id": -171 - }, - { - "name": "minecraft:angler_pottery_sherd", - "id": 663 - }, - { - "name": "minecraft:anvil", - "id": 145 - }, - { - "name": "minecraft:apple", - "id": 257 - }, - { - "name": "minecraft:archer_pottery_sherd", - "id": 664 - }, - { - "name": "minecraft:armor_stand", - "id": 559 - }, - { - "name": "minecraft:arms_up_pottery_sherd", - "id": 665 - }, - { - "name": "minecraft:arrow", - "id": 303 - }, - { - "name": "minecraft:axolotl_bucket", - "id": 371 - }, - { - "name": "minecraft:axolotl_spawn_egg", - "id": 503 - }, - { - "name": "minecraft:azalea", - "id": -337 - }, - { - "name": "minecraft:azalea_leaves", - "id": -324 - }, - { - "name": "minecraft:azalea_leaves_flowered", - "id": -325 - }, - { - "name": "minecraft:baked_potato", - "id": 281 - }, - { - "name": "minecraft:balloon", - "id": 605 - }, - { - "name": "minecraft:bamboo", - "id": -163 - }, - { - "name": "minecraft:bamboo_block", - "id": -527 - }, - { - "name": "minecraft:bamboo_button", - "id": -511 - }, - { - "name": "minecraft:bamboo_chest_raft", - "id": 661 - }, - { - "name": "minecraft:bamboo_door", - "id": -517 - }, - { - "name": "minecraft:bamboo_double_slab", - "id": -521 - }, - { - "name": "minecraft:bamboo_fence", - "id": -515 - }, - { - "name": "minecraft:bamboo_fence_gate", - "id": -516 - }, - { - "name": "minecraft:bamboo_hanging_sign", - "id": -522 - }, - { - "name": "minecraft:bamboo_mosaic", - "id": -509 - }, - { - "name": "minecraft:bamboo_mosaic_double_slab", - "id": -525 - }, - { - "name": "minecraft:bamboo_mosaic_slab", - "id": -524 - }, - { - "name": "minecraft:bamboo_mosaic_stairs", - "id": -523 - }, - { - "name": "minecraft:bamboo_planks", - "id": -510 - }, - { - "name": "minecraft:bamboo_pressure_plate", - "id": -514 - }, - { - "name": "minecraft:bamboo_raft", - "id": 660 - }, - { - "name": "minecraft:bamboo_sapling", - "id": -164 - }, - { - "name": "minecraft:bamboo_sign", - "id": 659 - }, - { - "name": "minecraft:bamboo_slab", - "id": -513 - }, - { - "name": "minecraft:bamboo_stairs", - "id": -512 - }, - { - "name": "minecraft:bamboo_standing_sign", - "id": -518 - }, - { - "name": "minecraft:bamboo_trapdoor", - "id": -520 - }, - { - "name": "minecraft:bamboo_wall_sign", - "id": -519 - }, - { - "name": "minecraft:banner", - "id": 574 - }, - { - "name": "minecraft:banner_pattern", - "id": 712 - }, - { - "name": "minecraft:barrel", - "id": -203 - }, - { - "name": "minecraft:barrier", - "id": -161 - }, - { - "name": "minecraft:basalt", - "id": -234 - }, - { - "name": "minecraft:bat_spawn_egg", - "id": 455 - }, - { - "name": "minecraft:beacon", - "id": 138 - }, - { - "name": "minecraft:bed", - "id": 420 - }, - { - "name": "minecraft:bedrock", - "id": 7 - }, - { - "name": "minecraft:bee_nest", - "id": -218 - }, - { - "name": "minecraft:bee_spawn_egg", - "id": 496 - }, - { - "name": "minecraft:beef", - "id": 273 - }, - { - "name": "minecraft:beehive", - "id": -219 - }, - { - "name": "minecraft:beetroot", - "id": 285 - }, - { - "name": "minecraft:beetroot_seeds", - "id": 295 - }, - { - "name": "minecraft:beetroot_soup", - "id": 286 - }, - { - "name": "minecraft:bell", - "id": -206 - }, - { - "name": "minecraft:big_dripleaf", - "id": -323 - }, - { - "name": "minecraft:birch_boat", - "id": 378 - }, - { - "name": "minecraft:birch_button", - "id": -141 - }, - { - "name": "minecraft:birch_chest_boat", - "id": 646 - }, - { - "name": "minecraft:birch_door", - "id": 561 - }, - { - "name": "minecraft:birch_fence", - "id": -576 - }, - { - "name": "minecraft:birch_fence_gate", - "id": 184 - }, - { - "name": "minecraft:birch_hanging_sign", - "id": -502 - }, - { - "name": "minecraft:birch_log", - "id": -570 - }, - { - "name": "minecraft:birch_pressure_plate", - "id": -151 - }, - { - "name": "minecraft:birch_sign", - "id": 584 - }, - { - "name": "minecraft:birch_stairs", - "id": 135 - }, - { - "name": "minecraft:birch_standing_sign", - "id": -186 - }, - { - "name": "minecraft:birch_trapdoor", - "id": -146 - }, - { - "name": "minecraft:birch_wall_sign", - "id": -187 - }, - { - "name": "minecraft:black_candle", - "id": -428 - }, - { - "name": "minecraft:black_candle_cake", - "id": -445 - }, - { - "name": "minecraft:black_carpet", - "id": -611 - }, - { - "name": "minecraft:black_concrete", - "id": -642 - }, - { - "name": "minecraft:black_dye", - "id": 397 - }, - { - "name": "minecraft:black_glazed_terracotta", - "id": 235 - }, - { - "name": "minecraft:black_shulker_box", - "id": -627 - }, - { - "name": "minecraft:black_wool", - "id": -554 - }, - { - "name": "minecraft:blackstone", - "id": -273 - }, - { - "name": "minecraft:blackstone_double_slab", - "id": -283 - }, - { - "name": "minecraft:blackstone_slab", - "id": -282 - }, - { - "name": "minecraft:blackstone_stairs", - "id": -276 - }, - { - "name": "minecraft:blackstone_wall", - "id": -277 - }, - { - "name": "minecraft:blade_pottery_sherd", - "id": 666 - }, - { - "name": "minecraft:blast_furnace", - "id": -196 - }, - { - "name": "minecraft:blaze_powder", - "id": 431 - }, - { - "name": "minecraft:blaze_rod", - "id": 425 - }, - { - "name": "minecraft:blaze_spawn_egg", - "id": 458 - }, - { - "name": "minecraft:bleach", - "id": 603 - }, - { - "name": "minecraft:blue_candle", - "id": -424 - }, - { - "name": "minecraft:blue_candle_cake", - "id": -441 - }, - { - "name": "minecraft:blue_carpet", - "id": -607 - }, - { - "name": "minecraft:blue_concrete", - "id": -638 - }, - { - "name": "minecraft:blue_dye", - "id": 401 - }, - { - "name": "minecraft:blue_glazed_terracotta", - "id": 231 - }, - { - "name": "minecraft:blue_ice", - "id": -11 - }, - { - "name": "minecraft:blue_shulker_box", - "id": -623 - }, - { - "name": "minecraft:blue_wool", - "id": -563 - }, - { - "name": "minecraft:boat", - "id": 710 - }, - { - "name": "minecraft:bone", - "id": 417 - }, - { - "name": "minecraft:bone_block", - "id": 216 - }, - { - "name": "minecraft:bone_meal", - "id": 413 - }, - { - "name": "minecraft:book", - "id": 389 - }, - { - "name": "minecraft:bookshelf", - "id": 47 - }, - { - "name": "minecraft:border_block", - "id": 212 - }, - { - "name": "minecraft:bordure_indented_banner_pattern", - "id": 593 - }, - { - "name": "minecraft:bow", - "id": 302 - }, - { - "name": "minecraft:bowl", - "id": 323 - }, - { - "name": "minecraft:brain_coral", - "id": -581 - }, - { - "name": "minecraft:bread", - "id": 261 - }, - { - "name": "minecraft:brewer_pottery_sherd", - "id": 667 - }, - { - "name": "minecraft:brewing_stand", - "id": 433 - }, - { - "name": "minecraft:brick", - "id": 385 - }, - { - "name": "minecraft:brick_block", - "id": 45 - }, - { - "name": "minecraft:brick_stairs", - "id": 108 - }, - { - "name": "minecraft:brown_candle", - "id": -425 - }, - { - "name": "minecraft:brown_candle_cake", - "id": -442 - }, - { - "name": "minecraft:brown_carpet", - "id": -608 - }, - { - "name": "minecraft:brown_concrete", - "id": -639 - }, - { - "name": "minecraft:brown_dye", - "id": 400 - }, - { - "name": "minecraft:brown_glazed_terracotta", - "id": 232 - }, - { - "name": "minecraft:brown_mushroom", - "id": 39 - }, - { - "name": "minecraft:brown_mushroom_block", - "id": 99 - }, - { - "name": "minecraft:brown_shulker_box", - "id": -624 - }, - { - "name": "minecraft:brown_wool", - "id": -555 - }, - { - "name": "minecraft:brush", - "id": 683 - }, - { - "name": "minecraft:bubble_column", - "id": -160 - }, - { - "name": "minecraft:bubble_coral", - "id": -582 - }, - { - "name": "minecraft:bucket", - "id": 362 - }, - { - "name": "minecraft:budding_amethyst", - "id": -328 - }, - { - "name": "minecraft:burn_pottery_sherd", - "id": 668 - }, - { - "name": "minecraft:cactus", - "id": 81 - }, - { - "name": "minecraft:cake", - "id": 419 - }, - { - "name": "minecraft:calcite", - "id": -326 - }, - { - "name": "minecraft:calibrated_sculk_sensor", - "id": -580 - }, - { - "name": "minecraft:camel_spawn_egg", - "id": 662 - }, - { - "name": "minecraft:camera", - "id": 600 - }, - { - "name": "minecraft:campfire", - "id": 596 - }, - { - "name": "minecraft:candle", - "id": -412 - }, - { - "name": "minecraft:candle_cake", - "id": -429 - }, - { - "name": "minecraft:carpet", - "id": 703 - }, - { - "name": "minecraft:carrot", - "id": 279 - }, - { - "name": "minecraft:carrot_on_a_stick", - "id": 524 - }, - { - "name": "minecraft:carrots", - "id": 141 - }, - { - "name": "minecraft:cartography_table", - "id": -200 - }, - { - "name": "minecraft:carved_pumpkin", - "id": -155 - }, - { - "name": "minecraft:cat_spawn_egg", - "id": 490 - }, - { - "name": "minecraft:cauldron", - "id": 434 - }, - { - "name": "minecraft:cave_spider_spawn_egg", - "id": 459 - }, - { - "name": "minecraft:cave_vines", - "id": -322 - }, - { - "name": "minecraft:cave_vines_body_with_berries", - "id": -375 - }, - { - "name": "minecraft:cave_vines_head_with_berries", - "id": -376 - }, - { - "name": "minecraft:chain", - "id": 626 - }, - { - "name": "minecraft:chain_command_block", - "id": 189 - }, - { - "name": "minecraft:chainmail_boots", - "id": 344 - }, - { - "name": "minecraft:chainmail_chestplate", - "id": 342 - }, - { - "name": "minecraft:chainmail_helmet", - "id": 341 - }, - { - "name": "minecraft:chainmail_leggings", - "id": 343 - }, - { - "name": "minecraft:charcoal", - "id": 305 - }, - { - "name": "minecraft:chemical_heat", - "id": 192 - }, - { - "name": "minecraft:chemistry_table", - "id": 238 - }, - { - "name": "minecraft:cherry_boat", - "id": 656 - }, - { - "name": "minecraft:cherry_button", - "id": -530 - }, - { - "name": "minecraft:cherry_chest_boat", - "id": 657 - }, - { - "name": "minecraft:cherry_door", - "id": -531 - }, - { - "name": "minecraft:cherry_double_slab", - "id": -540 - }, - { - "name": "minecraft:cherry_fence", - "id": -532 - }, - { - "name": "minecraft:cherry_fence_gate", - "id": -533 - }, - { - "name": "minecraft:cherry_hanging_sign", - "id": -534 - }, - { - "name": "minecraft:cherry_leaves", - "id": -548 - }, - { - "name": "minecraft:cherry_log", - "id": -536 - }, - { - "name": "minecraft:cherry_planks", - "id": -537 - }, - { - "name": "minecraft:cherry_pressure_plate", - "id": -538 - }, - { - "name": "minecraft:cherry_sapling", - "id": -547 - }, - { - "name": "minecraft:cherry_sign", - "id": 658 - }, - { - "name": "minecraft:cherry_slab", - "id": -539 - }, - { - "name": "minecraft:cherry_stairs", - "id": -541 - }, - { - "name": "minecraft:cherry_standing_sign", - "id": -542 - }, - { - "name": "minecraft:cherry_trapdoor", - "id": -543 - }, - { - "name": "minecraft:cherry_wall_sign", - "id": -544 - }, - { - "name": "minecraft:cherry_wood", - "id": -546 - }, - { - "name": "minecraft:chest", - "id": 54 - }, - { - "name": "minecraft:chest_boat", - "id": 652 - }, - { - "name": "minecraft:chest_minecart", - "id": 391 - }, - { - "name": "minecraft:chicken", - "id": 275 - }, - { - "name": "minecraft:chicken_spawn_egg", - "id": 437 - }, - { - "name": "minecraft:chiseled_bookshelf", - "id": -526 - }, - { - "name": "minecraft:chiseled_deepslate", - "id": -395 - }, - { - "name": "minecraft:chiseled_nether_bricks", - "id": -302 - }, - { - "name": "minecraft:chiseled_polished_blackstone", - "id": -279 - }, - { - "name": "minecraft:chorus_flower", - "id": 200 - }, - { - "name": "minecraft:chorus_fruit", - "id": 565 - }, - { - "name": "minecraft:chorus_plant", - "id": 240 - }, - { - "name": "minecraft:clay", - "id": 82 - }, - { - "name": "minecraft:clay_ball", - "id": 386 - }, - { - "name": "minecraft:client_request_placeholder_block", - "id": -465 - }, - { - "name": "minecraft:clock", - "id": 395 - }, - { - "name": "minecraft:coal", - "id": 304 - }, - { - "name": "minecraft:coal_block", - "id": 173 - }, - { - "name": "minecraft:coal_ore", - "id": 16 - }, - { - "name": "minecraft:coast_armor_trim_smithing_template", - "id": 687 - }, - { - "name": "minecraft:cobbled_deepslate", - "id": -379 - }, - { - "name": "minecraft:cobbled_deepslate_double_slab", - "id": -396 - }, - { - "name": "minecraft:cobbled_deepslate_slab", - "id": -380 - }, - { - "name": "minecraft:cobbled_deepslate_stairs", - "id": -381 - }, - { - "name": "minecraft:cobbled_deepslate_wall", - "id": -382 - }, - { - "name": "minecraft:cobblestone", - "id": 4 - }, - { - "name": "minecraft:cobblestone_wall", - "id": 139 - }, - { - "name": "minecraft:cocoa", - "id": 127 - }, - { - "name": "minecraft:cocoa_beans", - "id": 414 - }, - { - "name": "minecraft:cod", - "id": 264 - }, - { - "name": "minecraft:cod_bucket", - "id": 366 - }, - { - "name": "minecraft:cod_spawn_egg", - "id": 482 - }, - { - "name": "minecraft:colored_torch_bp", - "id": 204 - }, - { - "name": "minecraft:colored_torch_rg", - "id": 202 - }, - { - "name": "minecraft:command_block", - "id": 137 - }, - { - "name": "minecraft:command_block_minecart", - "id": 570 - }, - { - "name": "minecraft:comparator", - "id": 529 - }, - { - "name": "minecraft:compass", - "id": 393 - }, - { - "name": "minecraft:composter", - "id": -213 - }, - { - "name": "minecraft:compound", - "id": 601 - }, - { - "name": "minecraft:concrete", - "id": 708 - }, - { - "name": "minecraft:concrete_powder", - "id": 237 - }, - { - "name": "minecraft:conduit", - "id": -157 - }, - { - "name": "minecraft:cooked_beef", - "id": 274 - }, - { - "name": "minecraft:cooked_chicken", - "id": 276 - }, - { - "name": "minecraft:cooked_cod", - "id": 268 - }, - { - "name": "minecraft:cooked_mutton", - "id": 558 - }, - { - "name": "minecraft:cooked_porkchop", - "id": 263 - }, - { - "name": "minecraft:cooked_rabbit", - "id": 289 - }, - { - "name": "minecraft:cooked_salmon", - "id": 269 - }, - { - "name": "minecraft:cookie", - "id": 271 - }, - { - "name": "minecraft:copper_block", - "id": -340 - }, - { - "name": "minecraft:copper_ingot", - "id": 511 - }, - { - "name": "minecraft:copper_ore", - "id": -311 - }, - { - "name": "minecraft:coral", - "id": 706 - }, - { - "name": "minecraft:coral_block", - "id": -132 - }, - { - "name": "minecraft:coral_fan", - "id": -133 - }, - { - "name": "minecraft:coral_fan_dead", - "id": -134 - }, - { - "name": "minecraft:coral_fan_hang", - "id": -135 - }, - { - "name": "minecraft:coral_fan_hang2", - "id": -136 - }, - { - "name": "minecraft:coral_fan_hang3", - "id": -137 - }, - { - "name": "minecraft:cow_spawn_egg", - "id": 438 - }, - { - "name": "minecraft:cracked_deepslate_bricks", - "id": -410 - }, - { - "name": "minecraft:cracked_deepslate_tiles", - "id": -409 - }, - { - "name": "minecraft:cracked_nether_bricks", - "id": -303 - }, - { - "name": "minecraft:cracked_polished_blackstone_bricks", - "id": -280 - }, - { - "name": "minecraft:crafting_table", - "id": 58 - }, - { - "name": "minecraft:creeper_banner_pattern", - "id": 589 - }, - { - "name": "minecraft:creeper_spawn_egg", - "id": 443 - }, - { - "name": "minecraft:crimson_button", - "id": -260 - }, - { - "name": "minecraft:crimson_door", - "id": 623 - }, - { - "name": "minecraft:crimson_double_slab", - "id": -266 - }, - { - "name": "minecraft:crimson_fence", - "id": -256 - }, - { - "name": "minecraft:crimson_fence_gate", - "id": -258 - }, - { - "name": "minecraft:crimson_fungus", - "id": -228 - }, - { - "name": "minecraft:crimson_hanging_sign", - "id": -506 - }, - { - "name": "minecraft:crimson_hyphae", - "id": -299 - }, - { - "name": "minecraft:crimson_nylium", - "id": -232 - }, - { - "name": "minecraft:crimson_planks", - "id": -242 - }, - { - "name": "minecraft:crimson_pressure_plate", - "id": -262 - }, - { - "name": "minecraft:crimson_roots", - "id": -223 - }, - { - "name": "minecraft:crimson_sign", - "id": 621 - }, - { - "name": "minecraft:crimson_slab", - "id": -264 - }, - { - "name": "minecraft:crimson_stairs", - "id": -254 - }, - { - "name": "minecraft:crimson_standing_sign", - "id": -250 - }, - { - "name": "minecraft:crimson_stem", - "id": -225 - }, - { - "name": "minecraft:crimson_trapdoor", - "id": -246 - }, - { - "name": "minecraft:crimson_wall_sign", - "id": -252 - }, - { - "name": "minecraft:crossbow", - "id": 582 - }, - { - "name": "minecraft:crying_obsidian", - "id": -289 - }, - { - "name": "minecraft:cut_copper", - "id": -347 - }, - { - "name": "minecraft:cut_copper_slab", - "id": -361 - }, - { - "name": "minecraft:cut_copper_stairs", - "id": -354 - }, - { - "name": "minecraft:cyan_candle", - "id": -422 - }, - { - "name": "minecraft:cyan_candle_cake", - "id": -439 - }, - { - "name": "minecraft:cyan_carpet", - "id": -605 - }, - { - "name": "minecraft:cyan_concrete", - "id": -636 - }, - { - "name": "minecraft:cyan_dye", - "id": 403 - }, - { - "name": "minecraft:cyan_glazed_terracotta", - "id": 229 - }, - { - "name": "minecraft:cyan_shulker_box", - "id": -621 - }, - { - "name": "minecraft:cyan_wool", - "id": -561 - }, - { - "name": "minecraft:danger_pottery_sherd", - "id": 669 - }, - { - "name": "minecraft:dark_oak_boat", - "id": 382 - }, - { - "name": "minecraft:dark_oak_button", - "id": -142 - }, - { - "name": "minecraft:dark_oak_chest_boat", - "id": 650 - }, - { - "name": "minecraft:dark_oak_door", - "id": 564 - }, - { - "name": "minecraft:dark_oak_fence", - "id": -577 - }, - { - "name": "minecraft:dark_oak_fence_gate", - "id": 186 - }, - { - "name": "minecraft:dark_oak_hanging_sign", - "id": -505 - }, - { - "name": "minecraft:dark_oak_log", - "id": -572 - }, - { - "name": "minecraft:dark_oak_pressure_plate", - "id": -152 - }, - { - "name": "minecraft:dark_oak_sign", - "id": 587 - }, - { - "name": "minecraft:dark_oak_stairs", - "id": 164 - }, - { - "name": "minecraft:dark_oak_trapdoor", - "id": -147 - }, - { - "name": "minecraft:dark_prismarine_stairs", - "id": -3 - }, - { - "name": "minecraft:darkoak_standing_sign", - "id": -192 - }, - { - "name": "minecraft:darkoak_wall_sign", - "id": -193 - }, - { - "name": "minecraft:daylight_detector", - "id": 151 - }, - { - "name": "minecraft:daylight_detector_inverted", - "id": 178 - }, - { - "name": "minecraft:dead_brain_coral", - "id": -586 - }, - { - "name": "minecraft:dead_bubble_coral", - "id": -587 - }, - { - "name": "minecraft:dead_fire_coral", - "id": -588 - }, - { - "name": "minecraft:dead_horn_coral", - "id": -589 - }, - { - "name": "minecraft:dead_tube_coral", - "id": -585 - }, - { - "name": "minecraft:deadbush", - "id": 32 - }, - { - "name": "minecraft:decorated_pot", - "id": -551 - }, - { - "name": "minecraft:deepslate", - "id": -378 - }, - { - "name": "minecraft:deepslate_brick_double_slab", - "id": -399 - }, - { - "name": "minecraft:deepslate_brick_slab", - "id": -392 - }, - { - "name": "minecraft:deepslate_brick_stairs", - "id": -393 - }, - { - "name": "minecraft:deepslate_brick_wall", - "id": -394 - }, - { - "name": "minecraft:deepslate_bricks", - "id": -391 - }, - { - "name": "minecraft:deepslate_coal_ore", - "id": -406 - }, - { - "name": "minecraft:deepslate_copper_ore", - "id": -408 - }, - { - "name": "minecraft:deepslate_diamond_ore", - "id": -405 - }, - { - "name": "minecraft:deepslate_emerald_ore", - "id": -407 - }, - { - "name": "minecraft:deepslate_gold_ore", - "id": -402 - }, - { - "name": "minecraft:deepslate_iron_ore", - "id": -401 - }, - { - "name": "minecraft:deepslate_lapis_ore", - "id": -400 - }, - { - "name": "minecraft:deepslate_redstone_ore", - "id": -403 - }, - { - "name": "minecraft:deepslate_tile_double_slab", - "id": -398 - }, - { - "name": "minecraft:deepslate_tile_slab", - "id": -388 - }, - { - "name": "minecraft:deepslate_tile_stairs", - "id": -389 - }, - { - "name": "minecraft:deepslate_tile_wall", - "id": -390 - }, - { - "name": "minecraft:deepslate_tiles", - "id": -387 - }, - { - "name": "minecraft:deny", - "id": 211 - }, - { - "name": "minecraft:detector_rail", - "id": 28 - }, - { - "name": "minecraft:diamond", - "id": 306 - }, - { - "name": "minecraft:diamond_axe", - "id": 321 - }, - { - "name": "minecraft:diamond_block", - "id": 57 - }, - { - "name": "minecraft:diamond_boots", - "id": 352 - }, - { - "name": "minecraft:diamond_chestplate", - "id": 350 - }, - { - "name": "minecraft:diamond_helmet", - "id": 349 - }, - { - "name": "minecraft:diamond_hoe", - "id": 334 - }, - { - "name": "minecraft:diamond_horse_armor", - "id": 540 - }, - { - "name": "minecraft:diamond_leggings", - "id": 351 - }, - { - "name": "minecraft:diamond_ore", - "id": 56 - }, - { - "name": "minecraft:diamond_pickaxe", - "id": 320 - }, - { - "name": "minecraft:diamond_shovel", - "id": 319 - }, - { - "name": "minecraft:diamond_sword", - "id": 318 - }, - { - "name": "minecraft:diorite_stairs", - "id": -170 - }, - { - "name": "minecraft:dirt", - "id": 3 - }, - { - "name": "minecraft:dirt_with_roots", - "id": -318 - }, - { - "name": "minecraft:disc_fragment_5", - "id": 644 - }, - { - "name": "minecraft:dispenser", - "id": 23 - }, - { - "name": "minecraft:dolphin_spawn_egg", - "id": 486 - }, - { - "name": "minecraft:donkey_spawn_egg", - "id": 467 - }, - { - "name": "minecraft:double_cut_copper_slab", - "id": -368 - }, - { - "name": "minecraft:double_plant", - "id": 175 - }, - { - "name": "minecraft:double_stone_block_slab", - "id": 43 - }, - { - "name": "minecraft:double_stone_block_slab2", - "id": 181 - }, - { - "name": "minecraft:double_stone_block_slab3", - "id": -167 - }, - { - "name": "minecraft:double_stone_block_slab4", - "id": -168 - }, - { - "name": "minecraft:double_wooden_slab", - "id": 157 - }, - { - "name": "minecraft:dragon_breath", - "id": 567 - }, - { - "name": "minecraft:dragon_egg", - "id": 122 - }, - { - "name": "minecraft:dried_kelp", - "id": 270 - }, - { - "name": "minecraft:dried_kelp_block", - "id": -139 - }, - { - "name": "minecraft:dripstone_block", - "id": -317 - }, - { - "name": "minecraft:dropper", - "id": 125 - }, - { - "name": "minecraft:drowned_spawn_egg", - "id": 485 - }, - { - "name": "minecraft:dune_armor_trim_smithing_template", - "id": 686 - }, - { - "name": "minecraft:dye", - "id": 711 - }, - { - "name": "minecraft:echo_shard", - "id": 654 - }, - { - "name": "minecraft:egg", - "id": 392 - }, - { - "name": "minecraft:elder_guardian_spawn_egg", - "id": 473 - }, - { - "name": "minecraft:element_0", - "id": 36 - }, - { - "name": "minecraft:element_1", - "id": -12 - }, - { - "name": "minecraft:element_10", - "id": -21 - }, - { - "name": "minecraft:element_100", - "id": -111 - }, - { - "name": "minecraft:element_101", - "id": -112 - }, - { - "name": "minecraft:element_102", - "id": -113 - }, - { - "name": "minecraft:element_103", - "id": -114 - }, - { - "name": "minecraft:element_104", - "id": -115 - }, - { - "name": "minecraft:element_105", - "id": -116 - }, - { - "name": "minecraft:element_106", - "id": -117 - }, - { - "name": "minecraft:element_107", - "id": -118 - }, - { - "name": "minecraft:element_108", - "id": -119 - }, - { - "name": "minecraft:element_109", - "id": -120 - }, - { - "name": "minecraft:element_11", - "id": -22 - }, - { - "name": "minecraft:element_110", - "id": -121 - }, - { - "name": "minecraft:element_111", - "id": -122 - }, - { - "name": "minecraft:element_112", - "id": -123 - }, - { - "name": "minecraft:element_113", - "id": -124 - }, - { - "name": "minecraft:element_114", - "id": -125 - }, - { - "name": "minecraft:element_115", - "id": -126 - }, - { - "name": "minecraft:element_116", - "id": -127 - }, - { - "name": "minecraft:element_117", - "id": -128 - }, - { - "name": "minecraft:element_118", - "id": -129 - }, - { - "name": "minecraft:element_12", - "id": -23 - }, - { - "name": "minecraft:element_13", - "id": -24 - }, - { - "name": "minecraft:element_14", - "id": -25 - }, - { - "name": "minecraft:element_15", - "id": -26 - }, - { - "name": "minecraft:element_16", - "id": -27 - }, - { - "name": "minecraft:element_17", - "id": -28 - }, - { - "name": "minecraft:element_18", - "id": -29 - }, - { - "name": "minecraft:element_19", - "id": -30 - }, - { - "name": "minecraft:element_2", - "id": -13 - }, - { - "name": "minecraft:element_20", - "id": -31 - }, - { - "name": "minecraft:element_21", - "id": -32 - }, - { - "name": "minecraft:element_22", - "id": -33 - }, - { - "name": "minecraft:element_23", - "id": -34 - }, - { - "name": "minecraft:element_24", - "id": -35 - }, - { - "name": "minecraft:element_25", - "id": -36 - }, - { - "name": "minecraft:element_26", - "id": -37 - }, - { - "name": "minecraft:element_27", - "id": -38 - }, - { - "name": "minecraft:element_28", - "id": -39 - }, - { - "name": "minecraft:element_29", - "id": -40 - }, - { - "name": "minecraft:element_3", - "id": -14 - }, - { - "name": "minecraft:element_30", - "id": -41 - }, - { - "name": "minecraft:element_31", - "id": -42 - }, - { - "name": "minecraft:element_32", - "id": -43 - }, - { - "name": "minecraft:element_33", - "id": -44 - }, - { - "name": "minecraft:element_34", - "id": -45 - }, - { - "name": "minecraft:element_35", - "id": -46 - }, - { - "name": "minecraft:element_36", - "id": -47 - }, - { - "name": "minecraft:element_37", - "id": -48 - }, - { - "name": "minecraft:element_38", - "id": -49 - }, - { - "name": "minecraft:element_39", - "id": -50 - }, - { - "name": "minecraft:element_4", - "id": -15 - }, - { - "name": "minecraft:element_40", - "id": -51 - }, - { - "name": "minecraft:element_41", - "id": -52 - }, - { - "name": "minecraft:element_42", - "id": -53 - }, - { - "name": "minecraft:element_43", - "id": -54 - }, - { - "name": "minecraft:element_44", - "id": -55 - }, - { - "name": "minecraft:element_45", - "id": -56 - }, - { - "name": "minecraft:element_46", - "id": -57 - }, - { - "name": "minecraft:element_47", - "id": -58 - }, - { - "name": "minecraft:element_48", - "id": -59 - }, - { - "name": "minecraft:element_49", - "id": -60 - }, - { - "name": "minecraft:element_5", - "id": -16 - }, - { - "name": "minecraft:element_50", - "id": -61 - }, - { - "name": "minecraft:element_51", - "id": -62 - }, - { - "name": "minecraft:element_52", - "id": -63 - }, - { - "name": "minecraft:element_53", - "id": -64 - }, - { - "name": "minecraft:element_54", - "id": -65 - }, - { - "name": "minecraft:element_55", - "id": -66 - }, - { - "name": "minecraft:element_56", - "id": -67 - }, - { - "name": "minecraft:element_57", - "id": -68 - }, - { - "name": "minecraft:element_58", - "id": -69 - }, - { - "name": "minecraft:element_59", - "id": -70 - }, - { - "name": "minecraft:element_6", - "id": -17 - }, - { - "name": "minecraft:element_60", - "id": -71 - }, - { - "name": "minecraft:element_61", - "id": -72 - }, - { - "name": "minecraft:element_62", - "id": -73 - }, - { - "name": "minecraft:element_63", - "id": -74 - }, - { - "name": "minecraft:element_64", - "id": -75 - }, - { - "name": "minecraft:element_65", - "id": -76 - }, - { - "name": "minecraft:element_66", - "id": -77 - }, - { - "name": "minecraft:element_67", - "id": -78 - }, - { - "name": "minecraft:element_68", - "id": -79 - }, - { - "name": "minecraft:element_69", - "id": -80 - }, - { - "name": "minecraft:element_7", - "id": -18 - }, - { - "name": "minecraft:element_70", - "id": -81 - }, - { - "name": "minecraft:element_71", - "id": -82 - }, - { - "name": "minecraft:element_72", - "id": -83 - }, - { - "name": "minecraft:element_73", - "id": -84 - }, - { - "name": "minecraft:element_74", - "id": -85 - }, - { - "name": "minecraft:element_75", - "id": -86 - }, - { - "name": "minecraft:element_76", - "id": -87 - }, - { - "name": "minecraft:element_77", - "id": -88 - }, - { - "name": "minecraft:element_78", - "id": -89 - }, - { - "name": "minecraft:element_79", - "id": -90 - }, - { - "name": "minecraft:element_8", - "id": -19 - }, - { - "name": "minecraft:element_80", - "id": -91 - }, - { - "name": "minecraft:element_81", - "id": -92 - }, - { - "name": "minecraft:element_82", - "id": -93 - }, - { - "name": "minecraft:element_83", - "id": -94 - }, - { - "name": "minecraft:element_84", - "id": -95 - }, - { - "name": "minecraft:element_85", - "id": -96 - }, - { - "name": "minecraft:element_86", - "id": -97 - }, - { - "name": "minecraft:element_87", - "id": -98 - }, - { - "name": "minecraft:element_88", - "id": -99 - }, - { - "name": "minecraft:element_89", - "id": -100 - }, - { - "name": "minecraft:element_9", - "id": -20 - }, - { - "name": "minecraft:element_90", - "id": -101 - }, - { - "name": "minecraft:element_91", - "id": -102 - }, - { - "name": "minecraft:element_92", - "id": -103 - }, - { - "name": "minecraft:element_93", - "id": -104 - }, - { - "name": "minecraft:element_94", - "id": -105 - }, - { - "name": "minecraft:element_95", - "id": -106 - }, - { - "name": "minecraft:element_96", - "id": -107 - }, - { - "name": "minecraft:element_97", - "id": -108 - }, - { - "name": "minecraft:element_98", - "id": -109 - }, - { - "name": "minecraft:element_99", - "id": -110 - }, - { - "name": "minecraft:elytra", - "id": 571 - }, - { - "name": "minecraft:emerald", - "id": 519 - }, - { - "name": "minecraft:emerald_block", - "id": 133 - }, - { - "name": "minecraft:emerald_ore", - "id": 129 - }, - { - "name": "minecraft:empty_map", - "id": 522 - }, - { - "name": "minecraft:enchanted_book", - "id": 528 - }, - { - "name": "minecraft:enchanted_golden_apple", - "id": 259 - }, - { - "name": "minecraft:enchanting_table", - "id": 116 - }, - { - "name": "minecraft:end_brick_stairs", - "id": -178 - }, - { - "name": "minecraft:end_bricks", - "id": 206 - }, - { - "name": "minecraft:end_crystal", - "id": 714 - }, - { - "name": "minecraft:end_gateway", - "id": 209 - }, - { - "name": "minecraft:end_portal", - "id": 119 - }, - { - "name": "minecraft:end_portal_frame", - "id": 120 - }, - { - "name": "minecraft:end_rod", - "id": 208 - }, - { - "name": "minecraft:end_stone", - "id": 121 - }, - { - "name": "minecraft:ender_chest", - "id": 130 - }, - { - "name": "minecraft:ender_dragon_spawn_egg", - "id": 508 - }, - { - "name": "minecraft:ender_eye", - "id": 435 - }, - { - "name": "minecraft:ender_pearl", - "id": 424 - }, - { - "name": "minecraft:enderman_spawn_egg", - "id": 444 - }, - { - "name": "minecraft:endermite_spawn_egg", - "id": 462 - }, - { - "name": "minecraft:evoker_spawn_egg", - "id": 477 - }, - { - "name": "minecraft:experience_bottle", - "id": 515 - }, - { - "name": "minecraft:explorer_pottery_sherd", - "id": 670 - }, - { - "name": "minecraft:exposed_copper", - "id": -341 - }, - { - "name": "minecraft:exposed_cut_copper", - "id": -348 - }, - { - "name": "minecraft:exposed_cut_copper_slab", - "id": -362 - }, - { - "name": "minecraft:exposed_cut_copper_stairs", - "id": -355 - }, - { - "name": "minecraft:exposed_double_cut_copper_slab", - "id": -369 - }, - { - "name": "minecraft:eye_armor_trim_smithing_template", - "id": 690 - }, - { - "name": "minecraft:farmland", - "id": 60 - }, - { - "name": "minecraft:feather", - "id": 329 - }, - { - "name": "minecraft:fence", - "id": 705 - }, - { - "name": "minecraft:fence_gate", - "id": 107 - }, - { - "name": "minecraft:fermented_spider_eye", - "id": 430 - }, - { - "name": "minecraft:field_masoned_banner_pattern", - "id": 592 - }, - { - "name": "minecraft:filled_map", - "id": 422 - }, - { - "name": "minecraft:fire", - "id": 51 - }, - { - "name": "minecraft:fire_charge", - "id": 516 - }, - { - "name": "minecraft:fire_coral", - "id": -583 - }, - { - "name": "minecraft:firework_rocket", - "id": 526 - }, - { - "name": "minecraft:firework_star", - "id": 527 - }, - { - "name": "minecraft:fishing_rod", - "id": 394 - }, - { - "name": "minecraft:fletching_table", - "id": -201 - }, - { - "name": "minecraft:flint", - "id": 358 - }, - { - "name": "minecraft:flint_and_steel", - "id": 301 - }, - { - "name": "minecraft:flower_banner_pattern", - "id": 588 - }, - { - "name": "minecraft:flower_pot", - "id": 521 - }, - { - "name": "minecraft:flowering_azalea", - "id": -338 - }, - { - "name": "minecraft:flowing_lava", - "id": 10 - }, - { - "name": "minecraft:flowing_water", - "id": 8 - }, - { - "name": "minecraft:fox_spawn_egg", - "id": 492 - }, - { - "name": "minecraft:frame", - "id": 520 - }, - { - "name": "minecraft:friend_pottery_sherd", - "id": 671 - }, - { - "name": "minecraft:frog_spawn", - "id": -468 - }, - { - "name": "minecraft:frog_spawn_egg", - "id": 635 - }, - { - "name": "minecraft:frosted_ice", - "id": 207 - }, - { - "name": "minecraft:furnace", - "id": 61 - }, - { - "name": "minecraft:ghast_spawn_egg", - "id": 456 - }, - { - "name": "minecraft:ghast_tear", - "id": 426 - }, - { - "name": "minecraft:gilded_blackstone", - "id": -281 - }, - { - "name": "minecraft:glass", - "id": 20 - }, - { - "name": "minecraft:glass_bottle", - "id": 429 - }, - { - "name": "minecraft:glass_pane", - "id": 102 - }, - { - "name": "minecraft:glistering_melon_slice", - "id": 436 - }, - { - "name": "minecraft:globe_banner_pattern", - "id": 595 - }, - { - "name": "minecraft:glow_berries", - "id": 715 - }, - { - "name": "minecraft:glow_frame", - "id": 630 - }, - { - "name": "minecraft:glow_ink_sac", - "id": 510 - }, - { - "name": "minecraft:glow_lichen", - "id": -411 - }, - { - "name": "minecraft:glow_squid_spawn_egg", - "id": 505 - }, - { - "name": "minecraft:glow_stick", - "id": 608 - }, - { - "name": "minecraft:glowingobsidian", - "id": 246 - }, - { - "name": "minecraft:glowstone", - "id": 89 - }, - { - "name": "minecraft:glowstone_dust", - "id": 396 - }, - { - "name": "minecraft:goat_horn", - "id": 634 - }, - { - "name": "minecraft:goat_spawn_egg", - "id": 504 - }, - { - "name": "minecraft:gold_block", - "id": 41 - }, - { - "name": "minecraft:gold_ingot", - "id": 308 - }, - { - "name": "minecraft:gold_nugget", - "id": 427 - }, - { - "name": "minecraft:gold_ore", - "id": 14 - }, - { - "name": "minecraft:golden_apple", - "id": 258 - }, - { - "name": "minecraft:golden_axe", - "id": 327 - }, - { - "name": "minecraft:golden_boots", - "id": 356 - }, - { - "name": "minecraft:golden_carrot", - "id": 283 - }, - { - "name": "minecraft:golden_chestplate", - "id": 354 - }, - { - "name": "minecraft:golden_helmet", - "id": 353 - }, - { - "name": "minecraft:golden_hoe", - "id": 335 - }, - { - "name": "minecraft:golden_horse_armor", - "id": 539 - }, - { - "name": "minecraft:golden_leggings", - "id": 355 - }, - { - "name": "minecraft:golden_pickaxe", - "id": 326 - }, - { - "name": "minecraft:golden_rail", - "id": 27 - }, - { - "name": "minecraft:golden_shovel", - "id": 325 - }, - { - "name": "minecraft:golden_sword", - "id": 324 - }, - { - "name": "minecraft:granite_stairs", - "id": -169 - }, - { - "name": "minecraft:grass", - "id": 2 - }, - { - "name": "minecraft:grass_path", - "id": 198 - }, - { - "name": "minecraft:gravel", - "id": 13 - }, - { - "name": "minecraft:gray_candle", - "id": -420 - }, - { - "name": "minecraft:gray_candle_cake", - "id": -437 - }, - { - "name": "minecraft:gray_carpet", - "id": -603 - }, - { - "name": "minecraft:gray_concrete", - "id": -634 - }, - { - "name": "minecraft:gray_dye", - "id": 405 - }, - { - "name": "minecraft:gray_glazed_terracotta", - "id": 227 - }, - { - "name": "minecraft:gray_shulker_box", - "id": -619 - }, - { - "name": "minecraft:gray_wool", - "id": -553 - }, - { - "name": "minecraft:green_candle", - "id": -426 - }, - { - "name": "minecraft:green_candle_cake", - "id": -443 - }, - { - "name": "minecraft:green_carpet", - "id": -609 - }, - { - "name": "minecraft:green_concrete", - "id": -640 - }, - { - "name": "minecraft:green_dye", - "id": 399 - }, - { - "name": "minecraft:green_glazed_terracotta", - "id": 233 - }, - { - "name": "minecraft:green_shulker_box", - "id": -625 - }, - { - "name": "minecraft:green_wool", - "id": -560 - }, - { - "name": "minecraft:grindstone", - "id": -195 - }, - { - "name": "minecraft:guardian_spawn_egg", - "id": 463 - }, - { - "name": "minecraft:gunpowder", - "id": 330 - }, - { - "name": "minecraft:hanging_roots", - "id": -319 - }, - { - "name": "minecraft:hard_glass", - "id": 253 - }, - { - "name": "minecraft:hard_glass_pane", - "id": 190 - }, - { - "name": "minecraft:hard_stained_glass", - "id": 254 - }, - { - "name": "minecraft:hard_stained_glass_pane", - "id": 191 - }, - { - "name": "minecraft:hardened_clay", - "id": 172 - }, - { - "name": "minecraft:hay_block", - "id": 170 - }, - { - "name": "minecraft:heart_of_the_sea", - "id": 578 - }, - { - "name": "minecraft:heart_pottery_sherd", - "id": 672 - }, - { - "name": "minecraft:heartbreak_pottery_sherd", - "id": 673 - }, - { - "name": "minecraft:heavy_weighted_pressure_plate", - "id": 148 - }, - { - "name": "minecraft:hoglin_spawn_egg", - "id": 498 - }, - { - "name": "minecraft:honey_block", - "id": -220 - }, - { - "name": "minecraft:honey_bottle", - "id": 599 - }, - { - "name": "minecraft:honeycomb", - "id": 598 - }, - { - "name": "minecraft:honeycomb_block", - "id": -221 - }, - { - "name": "minecraft:hopper", - "id": 534 - }, - { - "name": "minecraft:hopper_minecart", - "id": 533 - }, - { - "name": "minecraft:horn_coral", - "id": -584 - }, - { - "name": "minecraft:horse_spawn_egg", - "id": 460 - }, - { - "name": "minecraft:host_armor_trim_smithing_template", - "id": 700 - }, - { - "name": "minecraft:howl_pottery_sherd", - "id": 674 - }, - { - "name": "minecraft:husk_spawn_egg", - "id": 465 - }, - { - "name": "minecraft:ice", - "id": 79 - }, - { - "name": "minecraft:ice_bomb", - "id": 602 - }, - { - "name": "minecraft:infested_deepslate", - "id": -454 - }, - { - "name": "minecraft:info_update", - "id": 248 - }, - { - "name": "minecraft:info_update2", - "id": 249 - }, - { - "name": "minecraft:ink_sac", - "id": 415 - }, - { - "name": "minecraft:invisible_bedrock", - "id": 95 - }, - { - "name": "minecraft:iron_axe", - "id": 300 - }, - { - "name": "minecraft:iron_bars", - "id": 101 - }, - { - "name": "minecraft:iron_block", - "id": 42 - }, - { - "name": "minecraft:iron_boots", - "id": 348 - }, - { - "name": "minecraft:iron_chestplate", - "id": 346 - }, - { - "name": "minecraft:iron_door", - "id": 374 - }, - { - "name": "minecraft:iron_golem_spawn_egg", - "id": 506 - }, - { - "name": "minecraft:iron_helmet", - "id": 345 - }, - { - "name": "minecraft:iron_hoe", - "id": 333 - }, - { - "name": "minecraft:iron_horse_armor", - "id": 538 - }, - { - "name": "minecraft:iron_ingot", - "id": 307 - }, - { - "name": "minecraft:iron_leggings", - "id": 347 - }, - { - "name": "minecraft:iron_nugget", - "id": 576 - }, - { - "name": "minecraft:iron_ore", - "id": 15 - }, - { - "name": "minecraft:iron_pickaxe", - "id": 299 - }, - { - "name": "minecraft:iron_shovel", - "id": 298 - }, - { - "name": "minecraft:iron_sword", - "id": 309 - }, - { - "name": "minecraft:iron_trapdoor", - "id": 167 - }, - { - "name": "minecraft:item.acacia_door", - "id": 196 - }, - { - "name": "minecraft:item.bed", - "id": 26 - }, - { - "name": "minecraft:item.beetroot", - "id": 244 - }, - { - "name": "minecraft:item.birch_door", - "id": 194 - }, - { - "name": "minecraft:item.brewing_stand", - "id": 117 - }, - { - "name": "minecraft:item.cake", - "id": 92 - }, - { - "name": "minecraft:item.camera", - "id": 242 - }, - { - "name": "minecraft:item.campfire", - "id": -209 - }, - { - "name": "minecraft:item.cauldron", - "id": 118 - }, - { - "name": "minecraft:item.chain", - "id": -286 - }, - { - "name": "minecraft:item.crimson_door", - "id": -244 - }, - { - "name": "minecraft:item.dark_oak_door", - "id": 197 - }, - { - "name": "minecraft:item.flower_pot", - "id": 140 - }, - { - "name": "minecraft:item.frame", - "id": 199 - }, - { - "name": "minecraft:item.glow_frame", - "id": -339 - }, - { - "name": "minecraft:item.hopper", - "id": 154 - }, - { - "name": "minecraft:item.iron_door", - "id": 71 - }, - { - "name": "minecraft:item.jungle_door", - "id": 195 - }, - { - "name": "minecraft:item.kelp", - "id": -138 - }, - { - "name": "minecraft:item.mangrove_door", - "id": -493 - }, - { - "name": "minecraft:item.nether_sprouts", - "id": -238 - }, - { - "name": "minecraft:item.nether_wart", - "id": 115 - }, - { - "name": "minecraft:item.reeds", - "id": 83 - }, - { - "name": "minecraft:item.skull", - "id": 144 - }, - { - "name": "minecraft:item.soul_campfire", - "id": -290 - }, - { - "name": "minecraft:item.spruce_door", - "id": 193 - }, - { - "name": "minecraft:item.warped_door", - "id": -245 - }, - { - "name": "minecraft:item.wheat", - "id": 59 - }, - { - "name": "minecraft:item.wooden_door", - "id": 64 - }, - { - "name": "minecraft:jigsaw", - "id": -211 - }, - { - "name": "minecraft:jukebox", - "id": 84 - }, - { - "name": "minecraft:jungle_boat", - "id": 379 - }, - { - "name": "minecraft:jungle_button", - "id": -143 - }, - { - "name": "minecraft:jungle_chest_boat", - "id": 647 - }, - { - "name": "minecraft:jungle_door", - "id": 562 - }, - { - "name": "minecraft:jungle_fence", - "id": -578 - }, - { - "name": "minecraft:jungle_fence_gate", - "id": 185 - }, - { - "name": "minecraft:jungle_hanging_sign", - "id": -503 - }, - { - "name": "minecraft:jungle_log", - "id": -571 - }, - { - "name": "minecraft:jungle_pressure_plate", - "id": -153 - }, - { - "name": "minecraft:jungle_sign", - "id": 585 - }, - { - "name": "minecraft:jungle_stairs", - "id": 136 - }, - { - "name": "minecraft:jungle_standing_sign", - "id": -188 - }, - { - "name": "minecraft:jungle_trapdoor", - "id": -148 - }, - { - "name": "minecraft:jungle_wall_sign", - "id": -189 - }, - { - "name": "minecraft:kelp", - "id": 384 - }, - { - "name": "minecraft:ladder", - "id": 65 - }, - { - "name": "minecraft:lantern", - "id": -208 - }, - { - "name": "minecraft:lapis_block", - "id": 22 - }, - { - "name": "minecraft:lapis_lazuli", - "id": 416 - }, - { - "name": "minecraft:lapis_ore", - "id": 21 - }, - { - "name": "minecraft:large_amethyst_bud", - "id": -330 - }, - { - "name": "minecraft:lava", - "id": 11 - }, - { - "name": "minecraft:lava_bucket", - "id": 365 - }, - { - "name": "minecraft:lead", - "id": 554 - }, - { - "name": "minecraft:leather", - "id": 383 - }, - { - "name": "minecraft:leather_boots", - "id": 340 - }, - { - "name": "minecraft:leather_chestplate", - "id": 338 - }, - { - "name": "minecraft:leather_helmet", - "id": 337 - }, - { - "name": "minecraft:leather_horse_armor", - "id": 537 - }, - { - "name": "minecraft:leather_leggings", - "id": 339 - }, - { - "name": "minecraft:leaves", - "id": 18 - }, - { - "name": "minecraft:leaves2", - "id": 161 - }, - { - "name": "minecraft:lectern", - "id": -194 - }, - { - "name": "minecraft:lever", - "id": 69 - }, - { - "name": "minecraft:light_block", - "id": -215 - }, - { - "name": "minecraft:light_blue_candle", - "id": -416 - }, - { - "name": "minecraft:light_blue_candle_cake", - "id": -433 - }, - { - "name": "minecraft:light_blue_carpet", - "id": -599 - }, - { - "name": "minecraft:light_blue_concrete", - "id": -630 - }, - { - "name": "minecraft:light_blue_dye", - "id": 409 - }, - { - "name": "minecraft:light_blue_glazed_terracotta", - "id": 223 - }, - { - "name": "minecraft:light_blue_shulker_box", - "id": -615 - }, - { - "name": "minecraft:light_blue_wool", - "id": -562 - }, - { - "name": "minecraft:light_gray_candle", - "id": -421 - }, - { - "name": "minecraft:light_gray_candle_cake", - "id": -438 - }, - { - "name": "minecraft:light_gray_carpet", - "id": -604 - }, - { - "name": "minecraft:light_gray_concrete", - "id": -635 - }, - { - "name": "minecraft:light_gray_dye", - "id": 404 - }, - { - "name": "minecraft:light_gray_shulker_box", - "id": -620 - }, - { - "name": "minecraft:light_gray_wool", - "id": -552 - }, - { - "name": "minecraft:light_weighted_pressure_plate", - "id": 147 - }, - { - "name": "minecraft:lightning_rod", - "id": -312 - }, - { - "name": "minecraft:lime_candle", - "id": -418 - }, - { - "name": "minecraft:lime_candle_cake", - "id": -435 - }, - { - "name": "minecraft:lime_carpet", - "id": -601 - }, - { - "name": "minecraft:lime_concrete", - "id": -632 - }, - { - "name": "minecraft:lime_dye", - "id": 407 - }, - { - "name": "minecraft:lime_glazed_terracotta", - "id": 225 - }, - { - "name": "minecraft:lime_shulker_box", - "id": -617 - }, - { - "name": "minecraft:lime_wool", - "id": -559 - }, - { - "name": "minecraft:lingering_potion", - "id": 569 - }, - { - "name": "minecraft:lit_blast_furnace", - "id": -214 - }, - { - "name": "minecraft:lit_deepslate_redstone_ore", - "id": -404 - }, - { - "name": "minecraft:lit_furnace", - "id": 62 - }, - { - "name": "minecraft:lit_pumpkin", - "id": 91 - }, - { - "name": "minecraft:lit_redstone_lamp", - "id": 124 - }, - { - "name": "minecraft:lit_redstone_ore", - "id": 74 - }, - { - "name": "minecraft:lit_smoker", - "id": -199 - }, - { - "name": "minecraft:llama_spawn_egg", - "id": 475 - }, - { - "name": "minecraft:lodestone", - "id": -222 - }, - { - "name": "minecraft:lodestone_compass", - "id": 609 - }, - { - "name": "minecraft:log", - "id": 704 - }, - { - "name": "minecraft:log2", - "id": 707 - }, - { - "name": "minecraft:loom", - "id": -204 - }, - { - "name": "minecraft:magenta_candle", - "id": -415 - }, - { - "name": "minecraft:magenta_candle_cake", - "id": -432 - }, - { - "name": "minecraft:magenta_carpet", - "id": -598 - }, - { - "name": "minecraft:magenta_concrete", - "id": -629 - }, - { - "name": "minecraft:magenta_dye", - "id": 410 - }, - { - "name": "minecraft:magenta_glazed_terracotta", - "id": 222 - }, - { - "name": "minecraft:magenta_shulker_box", - "id": -614 - }, - { - "name": "minecraft:magenta_wool", - "id": -565 - }, - { - "name": "minecraft:magma", - "id": 213 - }, - { - "name": "minecraft:magma_cream", - "id": 432 - }, - { - "name": "minecraft:magma_cube_spawn_egg", - "id": 457 - }, - { - "name": "minecraft:mangrove_boat", - "id": 642 - }, - { - "name": "minecraft:mangrove_button", - "id": -487 - }, - { - "name": "minecraft:mangrove_chest_boat", - "id": 651 - }, - { - "name": "minecraft:mangrove_door", - "id": 640 - }, - { - "name": "minecraft:mangrove_double_slab", - "id": -499 - }, - { - "name": "minecraft:mangrove_fence", - "id": -491 - }, - { - "name": "minecraft:mangrove_fence_gate", - "id": -492 - }, - { - "name": "minecraft:mangrove_hanging_sign", - "id": -508 - }, - { - "name": "minecraft:mangrove_leaves", - "id": -472 - }, - { - "name": "minecraft:mangrove_log", - "id": -484 - }, - { - "name": "minecraft:mangrove_planks", - "id": -486 - }, - { - "name": "minecraft:mangrove_pressure_plate", - "id": -490 - }, - { - "name": "minecraft:mangrove_propagule", - "id": -474 - }, - { - "name": "minecraft:mangrove_roots", - "id": -482 - }, - { - "name": "minecraft:mangrove_sign", - "id": 641 - }, - { - "name": "minecraft:mangrove_slab", - "id": -489 - }, - { - "name": "minecraft:mangrove_stairs", - "id": -488 - }, - { - "name": "minecraft:mangrove_standing_sign", - "id": -494 - }, - { - "name": "minecraft:mangrove_trapdoor", - "id": -496 - }, - { - "name": "minecraft:mangrove_wall_sign", - "id": -495 - }, - { - "name": "minecraft:mangrove_wood", - "id": -497 - }, - { - "name": "minecraft:medicine", - "id": 606 - }, - { - "name": "minecraft:medium_amethyst_bud", - "id": -331 - }, - { - "name": "minecraft:melon_block", - "id": 103 - }, - { - "name": "minecraft:melon_seeds", - "id": 293 - }, - { - "name": "minecraft:melon_slice", - "id": 272 - }, - { - "name": "minecraft:melon_stem", - "id": 105 - }, - { - "name": "minecraft:milk_bucket", - "id": 363 - }, - { - "name": "minecraft:minecart", - "id": 372 - }, - { - "name": "minecraft:miner_pottery_sherd", - "id": 675 - }, - { - "name": "minecraft:mob_spawner", - "id": 52 - }, - { - "name": "minecraft:mojang_banner_pattern", - "id": 591 - }, - { - "name": "minecraft:monster_egg", - "id": 97 - }, - { - "name": "minecraft:mooshroom_spawn_egg", - "id": 442 - }, - { - "name": "minecraft:moss_block", - "id": -320 - }, - { - "name": "minecraft:moss_carpet", - "id": -335 - }, - { - "name": "minecraft:mossy_cobblestone", - "id": 48 - }, - { - "name": "minecraft:mossy_cobblestone_stairs", - "id": -179 - }, - { - "name": "minecraft:mossy_stone_brick_stairs", - "id": -175 - }, - { - "name": "minecraft:mourner_pottery_sherd", - "id": 676 - }, - { - "name": "minecraft:moving_block", - "id": 250 - }, - { - "name": "minecraft:mud", - "id": -473 - }, - { - "name": "minecraft:mud_brick_double_slab", - "id": -479 - }, - { - "name": "minecraft:mud_brick_slab", - "id": -478 - }, - { - "name": "minecraft:mud_brick_stairs", - "id": -480 - }, - { - "name": "minecraft:mud_brick_wall", - "id": -481 - }, - { - "name": "minecraft:mud_bricks", - "id": -475 - }, - { - "name": "minecraft:muddy_mangrove_roots", - "id": -483 - }, - { - "name": "minecraft:mule_spawn_egg", - "id": 468 - }, - { - "name": "minecraft:mushroom_stew", - "id": 260 - }, - { - "name": "minecraft:music_disc_11", - "id": 551 - }, - { - "name": "minecraft:music_disc_13", - "id": 541 - }, - { - "name": "minecraft:music_disc_5", - "id": 643 - }, - { - "name": "minecraft:music_disc_blocks", - "id": 543 - }, - { - "name": "minecraft:music_disc_cat", - "id": 542 - }, - { - "name": "minecraft:music_disc_chirp", - "id": 544 - }, - { - "name": "minecraft:music_disc_far", - "id": 545 - }, - { - "name": "minecraft:music_disc_mall", - "id": 546 - }, - { - "name": "minecraft:music_disc_mellohi", - "id": 547 - }, - { - "name": "minecraft:music_disc_otherside", - "id": 633 - }, - { - "name": "minecraft:music_disc_pigstep", - "id": 627 - }, - { - "name": "minecraft:music_disc_relic", - "id": 701 - }, - { - "name": "minecraft:music_disc_stal", - "id": 548 - }, - { - "name": "minecraft:music_disc_strad", - "id": 549 - }, - { - "name": "minecraft:music_disc_wait", - "id": 552 - }, - { - "name": "minecraft:music_disc_ward", - "id": 550 - }, - { - "name": "minecraft:mutton", - "id": 557 - }, - { - "name": "minecraft:mycelium", - "id": 110 - }, - { - "name": "minecraft:name_tag", - "id": 555 - }, - { - "name": "minecraft:nautilus_shell", - "id": 577 - }, - { - "name": "minecraft:nether_brick", - "id": 112 - }, - { - "name": "minecraft:nether_brick_fence", - "id": 113 - }, - { - "name": "minecraft:nether_brick_stairs", - "id": 114 - }, - { - "name": "minecraft:nether_gold_ore", - "id": -288 - }, - { - "name": "minecraft:nether_sprouts", - "id": 628 - }, - { - "name": "minecraft:nether_star", - "id": 525 - }, - { - "name": "minecraft:nether_wart", - "id": 294 - }, - { - "name": "minecraft:nether_wart_block", - "id": 214 - }, - { - "name": "minecraft:netherbrick", - "id": 530 - }, - { - "name": "minecraft:netherite_axe", - "id": 613 - }, - { - "name": "minecraft:netherite_block", - "id": -270 - }, - { - "name": "minecraft:netherite_boots", - "id": 619 - }, - { - "name": "minecraft:netherite_chestplate", - "id": 617 - }, - { - "name": "minecraft:netherite_helmet", - "id": 616 - }, - { - "name": "minecraft:netherite_hoe", - "id": 614 - }, - { - "name": "minecraft:netherite_ingot", - "id": 615 - }, - { - "name": "minecraft:netherite_leggings", - "id": 618 - }, - { - "name": "minecraft:netherite_pickaxe", - "id": 612 - }, - { - "name": "minecraft:netherite_scrap", - "id": 620 - }, - { - "name": "minecraft:netherite_shovel", - "id": 611 - }, - { - "name": "minecraft:netherite_sword", - "id": 610 - }, - { - "name": "minecraft:netherite_upgrade_smithing_template", - "id": 684 - }, - { - "name": "minecraft:netherrack", - "id": 87 - }, - { - "name": "minecraft:netherreactor", - "id": 247 - }, - { - "name": "minecraft:normal_stone_stairs", - "id": -180 - }, - { - "name": "minecraft:noteblock", - "id": 25 - }, - { - "name": "minecraft:npc_spawn_egg", - "id": 472 - }, - { - "name": "minecraft:oak_boat", - "id": 377 - }, - { - "name": "minecraft:oak_chest_boat", - "id": 645 - }, - { - "name": "minecraft:oak_fence", - "id": 85 - }, - { - "name": "minecraft:oak_hanging_sign", - "id": -500 - }, - { - "name": "minecraft:oak_log", - "id": 17 - }, - { - "name": "minecraft:oak_sign", - "id": 360 - }, - { - "name": "minecraft:oak_stairs", - "id": 53 - }, - { - "name": "minecraft:observer", - "id": 251 - }, - { - "name": "minecraft:obsidian", - "id": 49 - }, - { - "name": "minecraft:ocelot_spawn_egg", - "id": 453 - }, - { - "name": "minecraft:ochre_froglight", - "id": -471 - }, - { - "name": "minecraft:orange_candle", - "id": -414 - }, - { - "name": "minecraft:orange_candle_cake", - "id": -431 - }, - { - "name": "minecraft:orange_carpet", - "id": -597 - }, - { - "name": "minecraft:orange_concrete", - "id": -628 - }, - { - "name": "minecraft:orange_dye", - "id": 411 - }, - { - "name": "minecraft:orange_glazed_terracotta", - "id": 221 - }, - { - "name": "minecraft:orange_shulker_box", - "id": -613 - }, - { - "name": "minecraft:orange_wool", - "id": -557 - }, - { - "name": "minecraft:oxidized_copper", - "id": -343 - }, - { - "name": "minecraft:oxidized_cut_copper", - "id": -350 - }, - { - "name": "minecraft:oxidized_cut_copper_slab", - "id": -364 - }, - { - "name": "minecraft:oxidized_cut_copper_stairs", - "id": -357 - }, - { - "name": "minecraft:oxidized_double_cut_copper_slab", - "id": -371 - }, - { - "name": "minecraft:packed_ice", - "id": 174 - }, - { - "name": "minecraft:packed_mud", - "id": -477 - }, - { - "name": "minecraft:painting", - "id": 359 - }, - { - "name": "minecraft:panda_spawn_egg", - "id": 491 - }, - { - "name": "minecraft:paper", - "id": 388 - }, - { - "name": "minecraft:parrot_spawn_egg", - "id": 480 - }, - { - "name": "minecraft:pearlescent_froglight", - "id": -469 - }, - { - "name": "minecraft:phantom_membrane", - "id": 581 - }, - { - "name": "minecraft:phantom_spawn_egg", - "id": 488 - }, - { - "name": "minecraft:pig_spawn_egg", - "id": 439 - }, - { - "name": "minecraft:piglin_banner_pattern", - "id": 594 - }, - { - "name": "minecraft:piglin_brute_spawn_egg", - "id": 501 - }, - { - "name": "minecraft:piglin_spawn_egg", - "id": 499 - }, - { - "name": "minecraft:pillager_spawn_egg", - "id": 493 - }, - { - "name": "minecraft:pink_candle", - "id": -419 - }, - { - "name": "minecraft:pink_candle_cake", - "id": -436 - }, - { - "name": "minecraft:pink_carpet", - "id": -602 - }, - { - "name": "minecraft:pink_concrete", - "id": -633 - }, - { - "name": "minecraft:pink_dye", - "id": 406 - }, - { - "name": "minecraft:pink_glazed_terracotta", - "id": 226 - }, - { - "name": "minecraft:pink_petals", - "id": -549 - }, - { - "name": "minecraft:pink_shulker_box", - "id": -618 - }, - { - "name": "minecraft:pink_wool", - "id": -566 - }, - { - "name": "minecraft:piston", - "id": 33 - }, - { - "name": "minecraft:piston_arm_collision", - "id": 34 - }, - { - "name": "minecraft:pitcher_crop", - "id": -574 - }, - { - "name": "minecraft:pitcher_plant", - "id": -612 - }, - { - "name": "minecraft:pitcher_pod", - "id": 297 - }, - { - "name": "minecraft:planks", - "id": 5 - }, - { - "name": "minecraft:plenty_pottery_sherd", - "id": 677 - }, - { - "name": "minecraft:podzol", - "id": 243 - }, - { - "name": "minecraft:pointed_dripstone", - "id": -308 - }, - { - "name": "minecraft:poisonous_potato", - "id": 282 - }, - { - "name": "minecraft:polar_bear_spawn_egg", - "id": 474 - }, - { - "name": "minecraft:polished_andesite_stairs", - "id": -174 - }, - { - "name": "minecraft:polished_basalt", - "id": -235 - }, - { - "name": "minecraft:polished_blackstone", - "id": -291 - }, - { - "name": "minecraft:polished_blackstone_brick_double_slab", - "id": -285 - }, - { - "name": "minecraft:polished_blackstone_brick_slab", - "id": -284 - }, - { - "name": "minecraft:polished_blackstone_brick_stairs", - "id": -275 - }, - { - "name": "minecraft:polished_blackstone_brick_wall", - "id": -278 - }, - { - "name": "minecraft:polished_blackstone_bricks", - "id": -274 - }, - { - "name": "minecraft:polished_blackstone_button", - "id": -296 - }, - { - "name": "minecraft:polished_blackstone_double_slab", - "id": -294 - }, - { - "name": "minecraft:polished_blackstone_pressure_plate", - "id": -295 - }, - { - "name": "minecraft:polished_blackstone_slab", - "id": -293 - }, - { - "name": "minecraft:polished_blackstone_stairs", - "id": -292 - }, - { - "name": "minecraft:polished_blackstone_wall", - "id": -297 - }, - { - "name": "minecraft:polished_deepslate", - "id": -383 - }, - { - "name": "minecraft:polished_deepslate_double_slab", - "id": -397 - }, - { - "name": "minecraft:polished_deepslate_slab", - "id": -384 - }, - { - "name": "minecraft:polished_deepslate_stairs", - "id": -385 - }, - { - "name": "minecraft:polished_deepslate_wall", - "id": -386 - }, - { - "name": "minecraft:polished_diorite_stairs", - "id": -173 - }, - { - "name": "minecraft:polished_granite_stairs", - "id": -172 - }, - { - "name": "minecraft:popped_chorus_fruit", - "id": 566 - }, - { - "name": "minecraft:porkchop", - "id": 262 - }, - { - "name": "minecraft:portal", - "id": 90 - }, - { - "name": "minecraft:potato", - "id": 280 - }, - { - "name": "minecraft:potatoes", - "id": 142 - }, - { - "name": "minecraft:potion", - "id": 428 - }, - { - "name": "minecraft:powder_snow", - "id": -306 - }, - { - "name": "minecraft:powder_snow_bucket", - "id": 370 - }, - { - "name": "minecraft:powered_comparator", - "id": 150 - }, - { - "name": "minecraft:powered_repeater", - "id": 94 - }, - { - "name": "minecraft:prismarine", - "id": 168 - }, - { - "name": "minecraft:prismarine_bricks_stairs", - "id": -4 - }, - { - "name": "minecraft:prismarine_crystals", - "id": 556 - }, - { - "name": "minecraft:prismarine_shard", - "id": 572 - }, - { - "name": "minecraft:prismarine_stairs", - "id": -2 - }, - { - "name": "minecraft:prize_pottery_sherd", - "id": 678 - }, - { - "name": "minecraft:pufferfish", - "id": 267 - }, - { - "name": "minecraft:pufferfish_bucket", - "id": 369 - }, - { - "name": "minecraft:pufferfish_spawn_egg", - "id": 483 - }, - { - "name": "minecraft:pumpkin", - "id": 86 - }, - { - "name": "minecraft:pumpkin_pie", - "id": 284 - }, - { - "name": "minecraft:pumpkin_seeds", - "id": 292 - }, - { - "name": "minecraft:pumpkin_stem", - "id": 104 - }, - { - "name": "minecraft:purple_candle", - "id": -423 - }, - { - "name": "minecraft:purple_candle_cake", - "id": -440 - }, - { - "name": "minecraft:purple_carpet", - "id": -606 - }, - { - "name": "minecraft:purple_concrete", - "id": -637 - }, - { - "name": "minecraft:purple_dye", - "id": 402 - }, - { - "name": "minecraft:purple_glazed_terracotta", - "id": 219 - }, - { - "name": "minecraft:purple_shulker_box", - "id": -622 - }, - { - "name": "minecraft:purple_wool", - "id": -564 - }, - { - "name": "minecraft:purpur_block", - "id": 201 - }, - { - "name": "minecraft:purpur_stairs", - "id": 203 - }, - { - "name": "minecraft:quartz", - "id": 531 - }, - { - "name": "minecraft:quartz_block", - "id": 155 - }, - { - "name": "minecraft:quartz_bricks", - "id": -304 - }, - { - "name": "minecraft:quartz_ore", - "id": 153 - }, - { - "name": "minecraft:quartz_stairs", - "id": 156 - }, - { - "name": "minecraft:rabbit", - "id": 288 - }, - { - "name": "minecraft:rabbit_foot", - "id": 535 - }, - { - "name": "minecraft:rabbit_hide", - "id": 536 - }, - { - "name": "minecraft:rabbit_spawn_egg", - "id": 461 - }, - { - "name": "minecraft:rabbit_stew", - "id": 290 - }, - { - "name": "minecraft:rail", - "id": 66 - }, - { - "name": "minecraft:raiser_armor_trim_smithing_template", - "id": 698 - }, - { - "name": "minecraft:rapid_fertilizer", - "id": 604 - }, - { - "name": "minecraft:ravager_spawn_egg", - "id": 495 - }, - { - "name": "minecraft:raw_copper", - "id": 514 - }, - { - "name": "minecraft:raw_copper_block", - "id": -452 - }, - { - "name": "minecraft:raw_gold", - "id": 513 - }, - { - "name": "minecraft:raw_gold_block", - "id": -453 - }, - { - "name": "minecraft:raw_iron", - "id": 512 - }, - { - "name": "minecraft:raw_iron_block", - "id": -451 - }, - { - "name": "minecraft:recovery_compass", - "id": 653 - }, - { - "name": "minecraft:red_candle", - "id": -427 - }, - { - "name": "minecraft:red_candle_cake", - "id": -444 - }, - { - "name": "minecraft:red_carpet", - "id": -610 - }, - { - "name": "minecraft:red_concrete", - "id": -641 - }, - { - "name": "minecraft:red_dye", - "id": 398 - }, - { - "name": "minecraft:red_flower", - "id": 38 - }, - { - "name": "minecraft:red_glazed_terracotta", - "id": 234 - }, - { - "name": "minecraft:red_mushroom", - "id": 40 - }, - { - "name": "minecraft:red_mushroom_block", - "id": 100 - }, - { - "name": "minecraft:red_nether_brick", - "id": 215 - }, - { - "name": "minecraft:red_nether_brick_stairs", - "id": -184 - }, - { - "name": "minecraft:red_sandstone", - "id": 179 - }, - { - "name": "minecraft:red_sandstone_stairs", - "id": 180 - }, - { - "name": "minecraft:red_shulker_box", - "id": -626 - }, - { - "name": "minecraft:red_wool", - "id": -556 - }, - { - "name": "minecraft:redstone", - "id": 375 - }, - { - "name": "minecraft:redstone_block", - "id": 152 - }, - { - "name": "minecraft:redstone_lamp", - "id": 123 - }, - { - "name": "minecraft:redstone_ore", - "id": 73 - }, - { - "name": "minecraft:redstone_torch", - "id": 76 - }, - { - "name": "minecraft:redstone_wire", - "id": 55 - }, - { - "name": "minecraft:reinforced_deepslate", - "id": -466 - }, - { - "name": "minecraft:repeater", - "id": 421 - }, - { - "name": "minecraft:repeating_command_block", - "id": 188 - }, - { - "name": "minecraft:reserved6", - "id": 255 - }, - { - "name": "minecraft:respawn_anchor", - "id": -272 - }, - { - "name": "minecraft:rib_armor_trim_smithing_template", - "id": 694 - }, - { - "name": "minecraft:rotten_flesh", - "id": 277 - }, - { - "name": "minecraft:saddle", - "id": 373 - }, - { - "name": "minecraft:salmon", - "id": 265 - }, - { - "name": "minecraft:salmon_bucket", - "id": 367 - }, - { - "name": "minecraft:salmon_spawn_egg", - "id": 484 - }, - { - "name": "minecraft:sand", - "id": 12 - }, - { - "name": "minecraft:sandstone", - "id": 24 - }, - { - "name": "minecraft:sandstone_stairs", - "id": 128 - }, - { - "name": "minecraft:sapling", - "id": 6 - }, - { - "name": "minecraft:scaffolding", - "id": -165 - }, - { - "name": "minecraft:sculk", - "id": -458 - }, - { - "name": "minecraft:sculk_catalyst", - "id": -460 - }, - { - "name": "minecraft:sculk_sensor", - "id": -307 - }, - { - "name": "minecraft:sculk_shrieker", - "id": -461 - }, - { - "name": "minecraft:sculk_vein", - "id": -459 - }, - { - "name": "minecraft:scute", - "id": 579 - }, - { - "name": "minecraft:sea_lantern", - "id": 169 - }, - { - "name": "minecraft:sea_pickle", - "id": -156 - }, - { - "name": "minecraft:seagrass", - "id": -130 - }, - { - "name": "minecraft:sentry_armor_trim_smithing_template", - "id": 685 - }, - { - "name": "minecraft:shaper_armor_trim_smithing_template", - "id": 699 - }, - { - "name": "minecraft:sheaf_pottery_sherd", - "id": 679 - }, - { - "name": "minecraft:shears", - "id": 423 - }, - { - "name": "minecraft:sheep_spawn_egg", - "id": 440 - }, - { - "name": "minecraft:shelter_pottery_sherd", - "id": 680 - }, - { - "name": "minecraft:shield", - "id": 357 - }, - { - "name": "minecraft:shroomlight", - "id": -230 - }, - { - "name": "minecraft:shulker_box", - "id": 709 - }, - { - "name": "minecraft:shulker_shell", - "id": 573 - }, - { - "name": "minecraft:shulker_spawn_egg", - "id": 471 - }, - { - "name": "minecraft:silence_armor_trim_smithing_template", - "id": 696 - }, - { - "name": "minecraft:silver_glazed_terracotta", - "id": 228 - }, - { - "name": "minecraft:silverfish_spawn_egg", - "id": 445 - }, - { - "name": "minecraft:skeleton_horse_spawn_egg", - "id": 469 - }, - { - "name": "minecraft:skeleton_spawn_egg", - "id": 446 - }, - { - "name": "minecraft:skull", - "id": 523 - }, - { - "name": "minecraft:skull_banner_pattern", - "id": 590 - }, - { - "name": "minecraft:skull_pottery_sherd", - "id": 681 - }, - { - "name": "minecraft:slime", - "id": 165 - }, - { - "name": "minecraft:slime_ball", - "id": 390 - }, - { - "name": "minecraft:slime_spawn_egg", - "id": 447 - }, - { - "name": "minecraft:small_amethyst_bud", - "id": -332 - }, - { - "name": "minecraft:small_dripleaf_block", - "id": -336 - }, - { - "name": "minecraft:smithing_table", - "id": -202 - }, - { - "name": "minecraft:smoker", - "id": -198 - }, - { - "name": "minecraft:smooth_basalt", - "id": -377 - }, - { - "name": "minecraft:smooth_quartz_stairs", - "id": -185 - }, - { - "name": "minecraft:smooth_red_sandstone_stairs", - "id": -176 - }, - { - "name": "minecraft:smooth_sandstone_stairs", - "id": -177 - }, - { - "name": "minecraft:smooth_stone", - "id": -183 - }, - { - "name": "minecraft:sniffer_egg", - "id": -596 - }, - { - "name": "minecraft:sniffer_spawn_egg", - "id": 502 - }, - { - "name": "minecraft:snort_pottery_sherd", - "id": 682 - }, - { - "name": "minecraft:snout_armor_trim_smithing_template", - "id": 693 - }, - { - "name": "minecraft:snow", - "id": 80 - }, - { - "name": "minecraft:snow_golem_spawn_egg", - "id": 507 - }, - { - "name": "minecraft:snow_layer", - "id": 78 - }, - { - "name": "minecraft:snowball", - "id": 376 - }, - { - "name": "minecraft:soul_campfire", - "id": 629 - }, - { - "name": "minecraft:soul_fire", - "id": -237 - }, - { - "name": "minecraft:soul_lantern", - "id": -269 - }, - { - "name": "minecraft:soul_sand", - "id": 88 - }, - { - "name": "minecraft:soul_soil", - "id": -236 - }, - { - "name": "minecraft:soul_torch", - "id": -268 - }, - { - "name": "minecraft:sparkler", - "id": 607 - }, - { - "name": "minecraft:spawn_egg", - "id": 713 - }, - { - "name": "minecraft:spider_eye", - "id": 278 - }, - { - "name": "minecraft:spider_spawn_egg", - "id": 448 - }, - { - "name": "minecraft:spire_armor_trim_smithing_template", - "id": 695 - }, - { - "name": "minecraft:splash_potion", - "id": 568 - }, - { - "name": "minecraft:sponge", - "id": 19 - }, - { - "name": "minecraft:spore_blossom", - "id": -321 - }, - { - "name": "minecraft:spruce_boat", - "id": 380 - }, - { - "name": "minecraft:spruce_button", - "id": -144 - }, - { - "name": "minecraft:spruce_chest_boat", - "id": 648 - }, - { - "name": "minecraft:spruce_door", - "id": 560 - }, - { - "name": "minecraft:spruce_fence", - "id": -579 - }, - { - "name": "minecraft:spruce_fence_gate", - "id": 183 - }, - { - "name": "minecraft:spruce_hanging_sign", - "id": -501 - }, - { - "name": "minecraft:spruce_log", - "id": -569 - }, - { - "name": "minecraft:spruce_pressure_plate", - "id": -154 - }, - { - "name": "minecraft:spruce_sign", - "id": 583 - }, - { - "name": "minecraft:spruce_stairs", - "id": 134 - }, - { - "name": "minecraft:spruce_standing_sign", - "id": -181 - }, - { - "name": "minecraft:spruce_trapdoor", - "id": -149 - }, - { - "name": "minecraft:spruce_wall_sign", - "id": -182 - }, - { - "name": "minecraft:spyglass", - "id": 632 - }, - { - "name": "minecraft:squid_spawn_egg", - "id": 452 - }, - { - "name": "minecraft:stained_glass", - "id": 241 - }, - { - "name": "minecraft:stained_glass_pane", - "id": 160 - }, - { - "name": "minecraft:stained_hardened_clay", - "id": 159 - }, - { - "name": "minecraft:standing_banner", - "id": 176 - }, - { - "name": "minecraft:standing_sign", - "id": 63 - }, - { - "name": "minecraft:stick", - "id": 322 - }, - { - "name": "minecraft:sticky_piston", - "id": 29 - }, - { - "name": "minecraft:sticky_piston_arm_collision", - "id": -217 - }, - { - "name": "minecraft:stone", - "id": 1 - }, - { - "name": "minecraft:stone_axe", - "id": 317 - }, - { - "name": "minecraft:stone_block_slab", - "id": 44 - }, - { - "name": "minecraft:stone_block_slab2", - "id": 182 - }, - { - "name": "minecraft:stone_block_slab3", - "id": -162 - }, - { - "name": "minecraft:stone_block_slab4", - "id": -166 - }, - { - "name": "minecraft:stone_brick_stairs", - "id": 109 - }, - { - "name": "minecraft:stone_button", - "id": 77 - }, - { - "name": "minecraft:stone_hoe", - "id": 332 - }, - { - "name": "minecraft:stone_pickaxe", - "id": 316 - }, - { - "name": "minecraft:stone_pressure_plate", - "id": 70 - }, - { - "name": "minecraft:stone_shovel", - "id": 315 - }, - { - "name": "minecraft:stone_stairs", - "id": 67 - }, - { - "name": "minecraft:stone_sword", - "id": 314 - }, - { - "name": "minecraft:stonebrick", - "id": 98 - }, - { - "name": "minecraft:stonecutter", - "id": 245 - }, - { - "name": "minecraft:stonecutter_block", - "id": -197 - }, - { - "name": "minecraft:stray_spawn_egg", - "id": 464 - }, - { - "name": "minecraft:strider_spawn_egg", - "id": 497 - }, - { - "name": "minecraft:string", - "id": 328 - }, - { - "name": "minecraft:stripped_acacia_log", - "id": -8 - }, - { - "name": "minecraft:stripped_bamboo_block", - "id": -528 - }, - { - "name": "minecraft:stripped_birch_log", - "id": -6 - }, - { - "name": "minecraft:stripped_cherry_log", - "id": -535 - }, - { - "name": "minecraft:stripped_cherry_wood", - "id": -545 - }, - { - "name": "minecraft:stripped_crimson_hyphae", - "id": -300 - }, - { - "name": "minecraft:stripped_crimson_stem", - "id": -240 - }, - { - "name": "minecraft:stripped_dark_oak_log", - "id": -9 - }, - { - "name": "minecraft:stripped_jungle_log", - "id": -7 - }, - { - "name": "minecraft:stripped_mangrove_log", - "id": -485 - }, - { - "name": "minecraft:stripped_mangrove_wood", - "id": -498 - }, - { - "name": "minecraft:stripped_oak_log", - "id": -10 - }, - { - "name": "minecraft:stripped_spruce_log", - "id": -5 - }, - { - "name": "minecraft:stripped_warped_hyphae", - "id": -301 - }, - { - "name": "minecraft:stripped_warped_stem", - "id": -241 - }, - { - "name": "minecraft:structure_block", - "id": 252 - }, - { - "name": "minecraft:structure_void", - "id": 217 - }, - { - "name": "minecraft:sugar", - "id": 418 - }, - { - "name": "minecraft:sugar_cane", - "id": 387 - }, - { - "name": "minecraft:suspicious_gravel", - "id": -573 - }, - { - "name": "minecraft:suspicious_sand", - "id": -529 - }, - { - "name": "minecraft:suspicious_stew", - "id": 597 - }, - { - "name": "minecraft:sweet_berries", - "id": 287 - }, - { - "name": "minecraft:sweet_berry_bush", - "id": -207 - }, - { - "name": "minecraft:tadpole_bucket", - "id": 637 - }, - { - "name": "minecraft:tadpole_spawn_egg", - "id": 636 - }, - { - "name": "minecraft:tallgrass", - "id": 31 - }, - { - "name": "minecraft:target", - "id": -239 - }, - { - "name": "minecraft:tide_armor_trim_smithing_template", - "id": 692 - }, - { - "name": "minecraft:tinted_glass", - "id": -334 - }, - { - "name": "minecraft:tnt", - "id": 46 - }, - { - "name": "minecraft:tnt_minecart", - "id": 532 - }, - { - "name": "minecraft:torch", - "id": 50 - }, - { - "name": "minecraft:torchflower", - "id": -568 - }, - { - "name": "minecraft:torchflower_crop", - "id": -567 - }, - { - "name": "minecraft:torchflower_seeds", - "id": 296 - }, - { - "name": "minecraft:totem_of_undying", - "id": 575 - }, - { - "name": "minecraft:trader_llama_spawn_egg", - "id": 655 - }, - { - "name": "minecraft:trapdoor", - "id": 96 - }, - { - "name": "minecraft:trapped_chest", - "id": 146 - }, - { - "name": "minecraft:trident", - "id": 553 - }, - { - "name": "minecraft:trip_wire", - "id": 132 - }, - { - "name": "minecraft:tripwire_hook", - "id": 131 - }, - { - "name": "minecraft:tropical_fish", - "id": 266 - }, - { - "name": "minecraft:tropical_fish_bucket", - "id": 368 - }, - { - "name": "minecraft:tropical_fish_spawn_egg", - "id": 481 - }, - { - "name": "minecraft:tube_coral", - "id": -131 - }, - { - "name": "minecraft:tuff", - "id": -333 - }, - { - "name": "minecraft:turtle_egg", - "id": -159 - }, - { - "name": "minecraft:turtle_helmet", - "id": 580 - }, - { - "name": "minecraft:turtle_spawn_egg", - "id": 487 - }, - { - "name": "minecraft:twisting_vines", - "id": -287 - }, - { - "name": "minecraft:underwater_torch", - "id": 239 - }, - { - "name": "minecraft:undyed_shulker_box", - "id": 205 - }, - { - "name": "minecraft:unknown", - "id": -305 - }, - { - "name": "minecraft:unlit_redstone_torch", - "id": 75 - }, - { - "name": "minecraft:unpowered_comparator", - "id": 149 - }, - { - "name": "minecraft:unpowered_repeater", - "id": 93 - }, - { - "name": "minecraft:verdant_froglight", - "id": -470 - }, - { - "name": "minecraft:vex_armor_trim_smithing_template", - "id": 691 - }, - { - "name": "minecraft:vex_spawn_egg", - "id": 478 - }, - { - "name": "minecraft:villager_spawn_egg", - "id": 451 - }, - { - "name": "minecraft:vindicator_spawn_egg", - "id": 476 - }, - { - "name": "minecraft:vine", - "id": 106 - }, - { - "name": "minecraft:wall_banner", - "id": 177 - }, - { - "name": "minecraft:wall_sign", - "id": 68 - }, - { - "name": "minecraft:wandering_trader_spawn_egg", - "id": 494 - }, - { - "name": "minecraft:ward_armor_trim_smithing_template", - "id": 689 - }, - { - "name": "minecraft:warden_spawn_egg", - "id": 639 - }, - { - "name": "minecraft:warped_button", - "id": -261 - }, - { - "name": "minecraft:warped_door", - "id": 624 - }, - { - "name": "minecraft:warped_double_slab", - "id": -267 - }, - { - "name": "minecraft:warped_fence", - "id": -257 - }, - { - "name": "minecraft:warped_fence_gate", - "id": -259 - }, - { - "name": "minecraft:warped_fungus", - "id": -229 - }, - { - "name": "minecraft:warped_fungus_on_a_stick", - "id": 625 - }, - { - "name": "minecraft:warped_hanging_sign", - "id": -507 - }, - { - "name": "minecraft:warped_hyphae", - "id": -298 - }, - { - "name": "minecraft:warped_nylium", - "id": -233 - }, - { - "name": "minecraft:warped_planks", - "id": -243 - }, - { - "name": "minecraft:warped_pressure_plate", - "id": -263 - }, - { - "name": "minecraft:warped_roots", - "id": -224 - }, - { - "name": "minecraft:warped_sign", - "id": 622 - }, - { - "name": "minecraft:warped_slab", - "id": -265 - }, - { - "name": "minecraft:warped_stairs", - "id": -255 - }, - { - "name": "minecraft:warped_standing_sign", - "id": -251 - }, - { - "name": "minecraft:warped_stem", - "id": -226 - }, - { - "name": "minecraft:warped_trapdoor", - "id": -247 - }, - { - "name": "minecraft:warped_wall_sign", - "id": -253 - }, - { - "name": "minecraft:warped_wart_block", - "id": -227 - }, - { - "name": "minecraft:water", - "id": 9 - }, - { - "name": "minecraft:water_bucket", - "id": 364 - }, - { - "name": "minecraft:waterlily", - "id": 111 - }, - { - "name": "minecraft:waxed_copper", - "id": -344 - }, - { - "name": "minecraft:waxed_cut_copper", - "id": -351 - }, - { - "name": "minecraft:waxed_cut_copper_slab", - "id": -365 - }, - { - "name": "minecraft:waxed_cut_copper_stairs", - "id": -358 - }, - { - "name": "minecraft:waxed_double_cut_copper_slab", - "id": -372 - }, - { - "name": "minecraft:waxed_exposed_copper", - "id": -345 - }, - { - "name": "minecraft:waxed_exposed_cut_copper", - "id": -352 - }, - { - "name": "minecraft:waxed_exposed_cut_copper_slab", - "id": -366 - }, - { - "name": "minecraft:waxed_exposed_cut_copper_stairs", - "id": -359 - }, - { - "name": "minecraft:waxed_exposed_double_cut_copper_slab", - "id": -373 - }, - { - "name": "minecraft:waxed_oxidized_copper", - "id": -446 - }, - { - "name": "minecraft:waxed_oxidized_cut_copper", - "id": -447 - }, - { - "name": "minecraft:waxed_oxidized_cut_copper_slab", - "id": -449 - }, - { - "name": "minecraft:waxed_oxidized_cut_copper_stairs", - "id": -448 - }, - { - "name": "minecraft:waxed_oxidized_double_cut_copper_slab", - "id": -450 - }, - { - "name": "minecraft:waxed_weathered_copper", - "id": -346 - }, - { - "name": "minecraft:waxed_weathered_cut_copper", - "id": -353 - }, - { - "name": "minecraft:waxed_weathered_cut_copper_slab", - "id": -367 - }, - { - "name": "minecraft:waxed_weathered_cut_copper_stairs", - "id": -360 - }, - { - "name": "minecraft:waxed_weathered_double_cut_copper_slab", - "id": -374 - }, - { - "name": "minecraft:wayfinder_armor_trim_smithing_template", - "id": 697 - }, - { - "name": "minecraft:weathered_copper", - "id": -342 - }, - { - "name": "minecraft:weathered_cut_copper", - "id": -349 - }, - { - "name": "minecraft:weathered_cut_copper_slab", - "id": -363 - }, - { - "name": "minecraft:weathered_cut_copper_stairs", - "id": -356 - }, - { - "name": "minecraft:weathered_double_cut_copper_slab", - "id": -370 - }, - { - "name": "minecraft:web", - "id": 30 - }, - { - "name": "minecraft:weeping_vines", - "id": -231 - }, - { - "name": "minecraft:wheat", - "id": 336 - }, - { - "name": "minecraft:wheat_seeds", - "id": 291 - }, - { - "name": "minecraft:white_candle", - "id": -413 - }, - { - "name": "minecraft:white_candle_cake", - "id": -430 - }, - { - "name": "minecraft:white_carpet", - "id": 171 - }, - { - "name": "minecraft:white_concrete", - "id": 236 - }, - { - "name": "minecraft:white_dye", - "id": 412 - }, - { - "name": "minecraft:white_glazed_terracotta", - "id": 220 - }, - { - "name": "minecraft:white_shulker_box", - "id": 218 - }, - { - "name": "minecraft:white_wool", - "id": 35 - }, - { - "name": "minecraft:wild_armor_trim_smithing_template", - "id": 688 - }, - { - "name": "minecraft:witch_spawn_egg", - "id": 454 - }, - { - "name": "minecraft:wither_rose", - "id": -216 - }, - { - "name": "minecraft:wither_skeleton_spawn_egg", - "id": 466 - }, - { - "name": "minecraft:wither_spawn_egg", - "id": 509 - }, - { - "name": "minecraft:wolf_spawn_egg", - "id": 441 - }, - { - "name": "minecraft:wood", - "id": -212 - }, - { - "name": "minecraft:wooden_axe", - "id": 313 - }, - { - "name": "minecraft:wooden_button", - "id": 143 - }, - { - "name": "minecraft:wooden_door", - "id": 361 - }, - { - "name": "minecraft:wooden_hoe", - "id": 331 - }, - { - "name": "minecraft:wooden_pickaxe", - "id": 312 - }, - { - "name": "minecraft:wooden_pressure_plate", - "id": 72 - }, - { - "name": "minecraft:wooden_shovel", - "id": 311 - }, - { - "name": "minecraft:wooden_slab", - "id": 158 - }, - { - "name": "minecraft:wooden_sword", - "id": 310 - }, - { - "name": "minecraft:wool", - "id": 702 - }, - { - "name": "minecraft:writable_book", - "id": 517 - }, - { - "name": "minecraft:written_book", - "id": 518 - }, - { - "name": "minecraft:yellow_candle", - "id": -417 - }, - { - "name": "minecraft:yellow_candle_cake", - "id": -434 - }, - { - "name": "minecraft:yellow_carpet", - "id": -600 - }, - { - "name": "minecraft:yellow_concrete", - "id": -631 - }, - { - "name": "minecraft:yellow_dye", - "id": 408 - }, - { - "name": "minecraft:yellow_flower", - "id": 37 - }, - { - "name": "minecraft:yellow_glazed_terracotta", - "id": 224 - }, - { - "name": "minecraft:yellow_shulker_box", - "id": -616 - }, - { - "name": "minecraft:yellow_wool", - "id": -558 - }, - { - "name": "minecraft:zoglin_spawn_egg", - "id": 500 - }, - { - "name": "minecraft:zombie_horse_spawn_egg", - "id": 470 - }, - { - "name": "minecraft:zombie_pigman_spawn_egg", - "id": 450 - }, - { - "name": "minecraft:zombie_spawn_egg", - "id": 449 - }, - { - "name": "minecraft:zombie_villager_spawn_egg", - "id": 479 - } -] \ No newline at end of file diff --git a/core/src/main/resources/bedrock/runtime_item_states.1_20_30.json b/core/src/main/resources/bedrock/runtime_item_states.1_20_30.json deleted file mode 100644 index 861b29c8a..000000000 --- a/core/src/main/resources/bedrock/runtime_item_states.1_20_30.json +++ /dev/null @@ -1,5570 +0,0 @@ -[ - { - "name": "minecraft:acacia_boat", - "id": 381 - }, - { - "name": "minecraft:acacia_button", - "id": -140 - }, - { - "name": "minecraft:acacia_chest_boat", - "id": 649 - }, - { - "name": "minecraft:acacia_door", - "id": 563 - }, - { - "name": "minecraft:acacia_fence", - "id": -575 - }, - { - "name": "minecraft:acacia_fence_gate", - "id": 187 - }, - { - "name": "minecraft:acacia_hanging_sign", - "id": -504 - }, - { - "name": "minecraft:acacia_log", - "id": 162 - }, - { - "name": "minecraft:acacia_pressure_plate", - "id": -150 - }, - { - "name": "minecraft:acacia_sign", - "id": 586 - }, - { - "name": "minecraft:acacia_stairs", - "id": 163 - }, - { - "name": "minecraft:acacia_standing_sign", - "id": -190 - }, - { - "name": "minecraft:acacia_trapdoor", - "id": -145 - }, - { - "name": "minecraft:acacia_wall_sign", - "id": -191 - }, - { - "name": "minecraft:activator_rail", - "id": 126 - }, - { - "name": "minecraft:agent_spawn_egg", - "id": 489 - }, - { - "name": "minecraft:air", - "id": -158 - }, - { - "name": "minecraft:allay_spawn_egg", - "id": 638 - }, - { - "name": "minecraft:allow", - "id": 210 - }, - { - "name": "minecraft:amethyst_block", - "id": -327 - }, - { - "name": "minecraft:amethyst_cluster", - "id": -329 - }, - { - "name": "minecraft:amethyst_shard", - "id": 631 - }, - { - "name": "minecraft:ancient_debris", - "id": -271 - }, - { - "name": "minecraft:andesite_stairs", - "id": -171 - }, - { - "name": "minecraft:angler_pottery_sherd", - "id": 663 - }, - { - "name": "minecraft:anvil", - "id": 145 - }, - { - "name": "minecraft:apple", - "id": 257 - }, - { - "name": "minecraft:archer_pottery_sherd", - "id": 664 - }, - { - "name": "minecraft:armor_stand", - "id": 559 - }, - { - "name": "minecraft:arms_up_pottery_sherd", - "id": 665 - }, - { - "name": "minecraft:arrow", - "id": 303 - }, - { - "name": "minecraft:axolotl_bucket", - "id": 371 - }, - { - "name": "minecraft:axolotl_spawn_egg", - "id": 503 - }, - { - "name": "minecraft:azalea", - "id": -337 - }, - { - "name": "minecraft:azalea_leaves", - "id": -324 - }, - { - "name": "minecraft:azalea_leaves_flowered", - "id": -325 - }, - { - "name": "minecraft:baked_potato", - "id": 281 - }, - { - "name": "minecraft:balloon", - "id": 605 - }, - { - "name": "minecraft:bamboo", - "id": -163 - }, - { - "name": "minecraft:bamboo_block", - "id": -527 - }, - { - "name": "minecraft:bamboo_button", - "id": -511 - }, - { - "name": "minecraft:bamboo_chest_raft", - "id": 661 - }, - { - "name": "minecraft:bamboo_door", - "id": -517 - }, - { - "name": "minecraft:bamboo_double_slab", - "id": -521 - }, - { - "name": "minecraft:bamboo_fence", - "id": -515 - }, - { - "name": "minecraft:bamboo_fence_gate", - "id": -516 - }, - { - "name": "minecraft:bamboo_hanging_sign", - "id": -522 - }, - { - "name": "minecraft:bamboo_mosaic", - "id": -509 - }, - { - "name": "minecraft:bamboo_mosaic_double_slab", - "id": -525 - }, - { - "name": "minecraft:bamboo_mosaic_slab", - "id": -524 - }, - { - "name": "minecraft:bamboo_mosaic_stairs", - "id": -523 - }, - { - "name": "minecraft:bamboo_planks", - "id": -510 - }, - { - "name": "minecraft:bamboo_pressure_plate", - "id": -514 - }, - { - "name": "minecraft:bamboo_raft", - "id": 660 - }, - { - "name": "minecraft:bamboo_sapling", - "id": -164 - }, - { - "name": "minecraft:bamboo_sign", - "id": 659 - }, - { - "name": "minecraft:bamboo_slab", - "id": -513 - }, - { - "name": "minecraft:bamboo_stairs", - "id": -512 - }, - { - "name": "minecraft:bamboo_standing_sign", - "id": -518 - }, - { - "name": "minecraft:bamboo_trapdoor", - "id": -520 - }, - { - "name": "minecraft:bamboo_wall_sign", - "id": -519 - }, - { - "name": "minecraft:banner", - "id": 574 - }, - { - "name": "minecraft:banner_pattern", - "id": 716 - }, - { - "name": "minecraft:barrel", - "id": -203 - }, - { - "name": "minecraft:barrier", - "id": -161 - }, - { - "name": "minecraft:basalt", - "id": -234 - }, - { - "name": "minecraft:bat_spawn_egg", - "id": 455 - }, - { - "name": "minecraft:beacon", - "id": 138 - }, - { - "name": "minecraft:bed", - "id": 420 - }, - { - "name": "minecraft:bedrock", - "id": 7 - }, - { - "name": "minecraft:bee_nest", - "id": -218 - }, - { - "name": "minecraft:bee_spawn_egg", - "id": 496 - }, - { - "name": "minecraft:beef", - "id": 273 - }, - { - "name": "minecraft:beehive", - "id": -219 - }, - { - "name": "minecraft:beetroot", - "id": 285 - }, - { - "name": "minecraft:beetroot_seeds", - "id": 295 - }, - { - "name": "minecraft:beetroot_soup", - "id": 286 - }, - { - "name": "minecraft:bell", - "id": -206 - }, - { - "name": "minecraft:big_dripleaf", - "id": -323 - }, - { - "name": "minecraft:birch_boat", - "id": 378 - }, - { - "name": "minecraft:birch_button", - "id": -141 - }, - { - "name": "minecraft:birch_chest_boat", - "id": 646 - }, - { - "name": "minecraft:birch_door", - "id": 561 - }, - { - "name": "minecraft:birch_fence", - "id": -576 - }, - { - "name": "minecraft:birch_fence_gate", - "id": 184 - }, - { - "name": "minecraft:birch_hanging_sign", - "id": -502 - }, - { - "name": "minecraft:birch_log", - "id": -570 - }, - { - "name": "minecraft:birch_pressure_plate", - "id": -151 - }, - { - "name": "minecraft:birch_sign", - "id": 584 - }, - { - "name": "minecraft:birch_stairs", - "id": 135 - }, - { - "name": "minecraft:birch_standing_sign", - "id": -186 - }, - { - "name": "minecraft:birch_trapdoor", - "id": -146 - }, - { - "name": "minecraft:birch_wall_sign", - "id": -187 - }, - { - "name": "minecraft:black_candle", - "id": -428 - }, - { - "name": "minecraft:black_candle_cake", - "id": -445 - }, - { - "name": "minecraft:black_carpet", - "id": -611 - }, - { - "name": "minecraft:black_concrete", - "id": -642 - }, - { - "name": "minecraft:black_concrete_powder", - "id": -723 - }, - { - "name": "minecraft:black_dye", - "id": 397 - }, - { - "name": "minecraft:black_glazed_terracotta", - "id": 235 - }, - { - "name": "minecraft:black_shulker_box", - "id": -627 - }, - { - "name": "minecraft:black_stained_glass", - "id": -687 - }, - { - "name": "minecraft:black_stained_glass_pane", - "id": -657 - }, - { - "name": "minecraft:black_terracotta", - "id": -738 - }, - { - "name": "minecraft:black_wool", - "id": -554 - }, - { - "name": "minecraft:blackstone", - "id": -273 - }, - { - "name": "minecraft:blackstone_double_slab", - "id": -283 - }, - { - "name": "minecraft:blackstone_slab", - "id": -282 - }, - { - "name": "minecraft:blackstone_stairs", - "id": -276 - }, - { - "name": "minecraft:blackstone_wall", - "id": -277 - }, - { - "name": "minecraft:blade_pottery_sherd", - "id": 666 - }, - { - "name": "minecraft:blast_furnace", - "id": -196 - }, - { - "name": "minecraft:blaze_powder", - "id": 431 - }, - { - "name": "minecraft:blaze_rod", - "id": 425 - }, - { - "name": "minecraft:blaze_spawn_egg", - "id": 458 - }, - { - "name": "minecraft:bleach", - "id": 603 - }, - { - "name": "minecraft:blue_candle", - "id": -424 - }, - { - "name": "minecraft:blue_candle_cake", - "id": -441 - }, - { - "name": "minecraft:blue_carpet", - "id": -607 - }, - { - "name": "minecraft:blue_concrete", - "id": -638 - }, - { - "name": "minecraft:blue_concrete_powder", - "id": -719 - }, - { - "name": "minecraft:blue_dye", - "id": 401 - }, - { - "name": "minecraft:blue_glazed_terracotta", - "id": 231 - }, - { - "name": "minecraft:blue_ice", - "id": -11 - }, - { - "name": "minecraft:blue_shulker_box", - "id": -623 - }, - { - "name": "minecraft:blue_stained_glass", - "id": -683 - }, - { - "name": "minecraft:blue_stained_glass_pane", - "id": -653 - }, - { - "name": "minecraft:blue_terracotta", - "id": -734 - }, - { - "name": "minecraft:blue_wool", - "id": -563 - }, - { - "name": "minecraft:boat", - "id": 714 - }, - { - "name": "minecraft:bone", - "id": 417 - }, - { - "name": "minecraft:bone_block", - "id": 216 - }, - { - "name": "minecraft:bone_meal", - "id": 413 - }, - { - "name": "minecraft:book", - "id": 389 - }, - { - "name": "minecraft:bookshelf", - "id": 47 - }, - { - "name": "minecraft:border_block", - "id": 212 - }, - { - "name": "minecraft:bordure_indented_banner_pattern", - "id": 593 - }, - { - "name": "minecraft:bow", - "id": 302 - }, - { - "name": "minecraft:bowl", - "id": 323 - }, - { - "name": "minecraft:brain_coral", - "id": -581 - }, - { - "name": "minecraft:bread", - "id": 261 - }, - { - "name": "minecraft:brewer_pottery_sherd", - "id": 667 - }, - { - "name": "minecraft:brewing_stand", - "id": 433 - }, - { - "name": "minecraft:brick", - "id": 385 - }, - { - "name": "minecraft:brick_block", - "id": 45 - }, - { - "name": "minecraft:brick_stairs", - "id": 108 - }, - { - "name": "minecraft:brown_candle", - "id": -425 - }, - { - "name": "minecraft:brown_candle_cake", - "id": -442 - }, - { - "name": "minecraft:brown_carpet", - "id": -608 - }, - { - "name": "minecraft:brown_concrete", - "id": -639 - }, - { - "name": "minecraft:brown_concrete_powder", - "id": -720 - }, - { - "name": "minecraft:brown_dye", - "id": 400 - }, - { - "name": "minecraft:brown_glazed_terracotta", - "id": 232 - }, - { - "name": "minecraft:brown_mushroom", - "id": 39 - }, - { - "name": "minecraft:brown_mushroom_block", - "id": 99 - }, - { - "name": "minecraft:brown_shulker_box", - "id": -624 - }, - { - "name": "minecraft:brown_stained_glass", - "id": -684 - }, - { - "name": "minecraft:brown_stained_glass_pane", - "id": -654 - }, - { - "name": "minecraft:brown_terracotta", - "id": -735 - }, - { - "name": "minecraft:brown_wool", - "id": -555 - }, - { - "name": "minecraft:brush", - "id": 683 - }, - { - "name": "minecraft:bubble_column", - "id": -160 - }, - { - "name": "minecraft:bubble_coral", - "id": -582 - }, - { - "name": "minecraft:bucket", - "id": 362 - }, - { - "name": "minecraft:budding_amethyst", - "id": -328 - }, - { - "name": "minecraft:burn_pottery_sherd", - "id": 668 - }, - { - "name": "minecraft:cactus", - "id": 81 - }, - { - "name": "minecraft:cake", - "id": 419 - }, - { - "name": "minecraft:calcite", - "id": -326 - }, - { - "name": "minecraft:calibrated_sculk_sensor", - "id": -580 - }, - { - "name": "minecraft:camel_spawn_egg", - "id": 662 - }, - { - "name": "minecraft:camera", - "id": 600 - }, - { - "name": "minecraft:campfire", - "id": 596 - }, - { - "name": "minecraft:candle", - "id": -412 - }, - { - "name": "minecraft:candle_cake", - "id": -429 - }, - { - "name": "minecraft:carpet", - "id": 704 - }, - { - "name": "minecraft:carrot", - "id": 279 - }, - { - "name": "minecraft:carrot_on_a_stick", - "id": 524 - }, - { - "name": "minecraft:carrots", - "id": 141 - }, - { - "name": "minecraft:cartography_table", - "id": -200 - }, - { - "name": "minecraft:carved_pumpkin", - "id": -155 - }, - { - "name": "minecraft:cat_spawn_egg", - "id": 490 - }, - { - "name": "minecraft:cauldron", - "id": 434 - }, - { - "name": "minecraft:cave_spider_spawn_egg", - "id": 459 - }, - { - "name": "minecraft:cave_vines", - "id": -322 - }, - { - "name": "minecraft:cave_vines_body_with_berries", - "id": -375 - }, - { - "name": "minecraft:cave_vines_head_with_berries", - "id": -376 - }, - { - "name": "minecraft:chain", - "id": 626 - }, - { - "name": "minecraft:chain_command_block", - "id": 189 - }, - { - "name": "minecraft:chainmail_boots", - "id": 344 - }, - { - "name": "minecraft:chainmail_chestplate", - "id": 342 - }, - { - "name": "minecraft:chainmail_helmet", - "id": 341 - }, - { - "name": "minecraft:chainmail_leggings", - "id": 343 - }, - { - "name": "minecraft:charcoal", - "id": 305 - }, - { - "name": "minecraft:chemical_heat", - "id": 192 - }, - { - "name": "minecraft:chemistry_table", - "id": 238 - }, - { - "name": "minecraft:cherry_boat", - "id": 656 - }, - { - "name": "minecraft:cherry_button", - "id": -530 - }, - { - "name": "minecraft:cherry_chest_boat", - "id": 657 - }, - { - "name": "minecraft:cherry_door", - "id": -531 - }, - { - "name": "minecraft:cherry_double_slab", - "id": -540 - }, - { - "name": "minecraft:cherry_fence", - "id": -532 - }, - { - "name": "minecraft:cherry_fence_gate", - "id": -533 - }, - { - "name": "minecraft:cherry_hanging_sign", - "id": -534 - }, - { - "name": "minecraft:cherry_leaves", - "id": -548 - }, - { - "name": "minecraft:cherry_log", - "id": -536 - }, - { - "name": "minecraft:cherry_planks", - "id": -537 - }, - { - "name": "minecraft:cherry_pressure_plate", - "id": -538 - }, - { - "name": "minecraft:cherry_sapling", - "id": -547 - }, - { - "name": "minecraft:cherry_sign", - "id": 658 - }, - { - "name": "minecraft:cherry_slab", - "id": -539 - }, - { - "name": "minecraft:cherry_stairs", - "id": -541 - }, - { - "name": "minecraft:cherry_standing_sign", - "id": -542 - }, - { - "name": "minecraft:cherry_trapdoor", - "id": -543 - }, - { - "name": "minecraft:cherry_wall_sign", - "id": -544 - }, - { - "name": "minecraft:cherry_wood", - "id": -546 - }, - { - "name": "minecraft:chest", - "id": 54 - }, - { - "name": "minecraft:chest_boat", - "id": 652 - }, - { - "name": "minecraft:chest_minecart", - "id": 391 - }, - { - "name": "minecraft:chicken", - "id": 275 - }, - { - "name": "minecraft:chicken_spawn_egg", - "id": 437 - }, - { - "name": "minecraft:chiseled_bookshelf", - "id": -526 - }, - { - "name": "minecraft:chiseled_deepslate", - "id": -395 - }, - { - "name": "minecraft:chiseled_nether_bricks", - "id": -302 - }, - { - "name": "minecraft:chiseled_polished_blackstone", - "id": -279 - }, - { - "name": "minecraft:chorus_flower", - "id": 200 - }, - { - "name": "minecraft:chorus_fruit", - "id": 565 - }, - { - "name": "minecraft:chorus_plant", - "id": 240 - }, - { - "name": "minecraft:clay", - "id": 82 - }, - { - "name": "minecraft:clay_ball", - "id": 386 - }, - { - "name": "minecraft:client_request_placeholder_block", - "id": -465 - }, - { - "name": "minecraft:clock", - "id": 395 - }, - { - "name": "minecraft:coal", - "id": 304 - }, - { - "name": "minecraft:coal_block", - "id": 173 - }, - { - "name": "minecraft:coal_ore", - "id": 16 - }, - { - "name": "minecraft:coast_armor_trim_smithing_template", - "id": 687 - }, - { - "name": "minecraft:cobbled_deepslate", - "id": -379 - }, - { - "name": "minecraft:cobbled_deepslate_double_slab", - "id": -396 - }, - { - "name": "minecraft:cobbled_deepslate_slab", - "id": -380 - }, - { - "name": "minecraft:cobbled_deepslate_stairs", - "id": -381 - }, - { - "name": "minecraft:cobbled_deepslate_wall", - "id": -382 - }, - { - "name": "minecraft:cobblestone", - "id": 4 - }, - { - "name": "minecraft:cobblestone_wall", - "id": 139 - }, - { - "name": "minecraft:cocoa", - "id": 127 - }, - { - "name": "minecraft:cocoa_beans", - "id": 414 - }, - { - "name": "minecraft:cod", - "id": 264 - }, - { - "name": "minecraft:cod_bucket", - "id": 366 - }, - { - "name": "minecraft:cod_spawn_egg", - "id": 482 - }, - { - "name": "minecraft:colored_torch_bp", - "id": 204 - }, - { - "name": "minecraft:colored_torch_rg", - "id": 202 - }, - { - "name": "minecraft:command_block", - "id": 137 - }, - { - "name": "minecraft:command_block_minecart", - "id": 570 - }, - { - "name": "minecraft:comparator", - "id": 529 - }, - { - "name": "minecraft:compass", - "id": 393 - }, - { - "name": "minecraft:composter", - "id": -213 - }, - { - "name": "minecraft:compound", - "id": 601 - }, - { - "name": "minecraft:concrete", - "id": 709 - }, - { - "name": "minecraft:concrete_powder", - "id": 710 - }, - { - "name": "minecraft:conduit", - "id": -157 - }, - { - "name": "minecraft:cooked_beef", - "id": 274 - }, - { - "name": "minecraft:cooked_chicken", - "id": 276 - }, - { - "name": "minecraft:cooked_cod", - "id": 268 - }, - { - "name": "minecraft:cooked_mutton", - "id": 558 - }, - { - "name": "minecraft:cooked_porkchop", - "id": 263 - }, - { - "name": "minecraft:cooked_rabbit", - "id": 289 - }, - { - "name": "minecraft:cooked_salmon", - "id": 269 - }, - { - "name": "minecraft:cookie", - "id": 271 - }, - { - "name": "minecraft:copper_block", - "id": -340 - }, - { - "name": "minecraft:copper_ingot", - "id": 511 - }, - { - "name": "minecraft:copper_ore", - "id": -311 - }, - { - "name": "minecraft:coral", - "id": 707 - }, - { - "name": "minecraft:coral_block", - "id": -132 - }, - { - "name": "minecraft:coral_fan", - "id": -133 - }, - { - "name": "minecraft:coral_fan_dead", - "id": -134 - }, - { - "name": "minecraft:coral_fan_hang", - "id": -135 - }, - { - "name": "minecraft:coral_fan_hang2", - "id": -136 - }, - { - "name": "minecraft:coral_fan_hang3", - "id": -137 - }, - { - "name": "minecraft:cow_spawn_egg", - "id": 438 - }, - { - "name": "minecraft:cracked_deepslate_bricks", - "id": -410 - }, - { - "name": "minecraft:cracked_deepslate_tiles", - "id": -409 - }, - { - "name": "minecraft:cracked_nether_bricks", - "id": -303 - }, - { - "name": "minecraft:cracked_polished_blackstone_bricks", - "id": -280 - }, - { - "name": "minecraft:crafting_table", - "id": 58 - }, - { - "name": "minecraft:creeper_banner_pattern", - "id": 589 - }, - { - "name": "minecraft:creeper_spawn_egg", - "id": 443 - }, - { - "name": "minecraft:crimson_button", - "id": -260 - }, - { - "name": "minecraft:crimson_door", - "id": 623 - }, - { - "name": "minecraft:crimson_double_slab", - "id": -266 - }, - { - "name": "minecraft:crimson_fence", - "id": -256 - }, - { - "name": "minecraft:crimson_fence_gate", - "id": -258 - }, - { - "name": "minecraft:crimson_fungus", - "id": -228 - }, - { - "name": "minecraft:crimson_hanging_sign", - "id": -506 - }, - { - "name": "minecraft:crimson_hyphae", - "id": -299 - }, - { - "name": "minecraft:crimson_nylium", - "id": -232 - }, - { - "name": "minecraft:crimson_planks", - "id": -242 - }, - { - "name": "minecraft:crimson_pressure_plate", - "id": -262 - }, - { - "name": "minecraft:crimson_roots", - "id": -223 - }, - { - "name": "minecraft:crimson_sign", - "id": 621 - }, - { - "name": "minecraft:crimson_slab", - "id": -264 - }, - { - "name": "minecraft:crimson_stairs", - "id": -254 - }, - { - "name": "minecraft:crimson_standing_sign", - "id": -250 - }, - { - "name": "minecraft:crimson_stem", - "id": -225 - }, - { - "name": "minecraft:crimson_trapdoor", - "id": -246 - }, - { - "name": "minecraft:crimson_wall_sign", - "id": -252 - }, - { - "name": "minecraft:crossbow", - "id": 582 - }, - { - "name": "minecraft:crying_obsidian", - "id": -289 - }, - { - "name": "minecraft:cut_copper", - "id": -347 - }, - { - "name": "minecraft:cut_copper_slab", - "id": -361 - }, - { - "name": "minecraft:cut_copper_stairs", - "id": -354 - }, - { - "name": "minecraft:cyan_candle", - "id": -422 - }, - { - "name": "minecraft:cyan_candle_cake", - "id": -439 - }, - { - "name": "minecraft:cyan_carpet", - "id": -605 - }, - { - "name": "minecraft:cyan_concrete", - "id": -636 - }, - { - "name": "minecraft:cyan_concrete_powder", - "id": -717 - }, - { - "name": "minecraft:cyan_dye", - "id": 403 - }, - { - "name": "minecraft:cyan_glazed_terracotta", - "id": 229 - }, - { - "name": "minecraft:cyan_shulker_box", - "id": -621 - }, - { - "name": "minecraft:cyan_stained_glass", - "id": -681 - }, - { - "name": "minecraft:cyan_stained_glass_pane", - "id": -651 - }, - { - "name": "minecraft:cyan_terracotta", - "id": -732 - }, - { - "name": "minecraft:cyan_wool", - "id": -561 - }, - { - "name": "minecraft:danger_pottery_sherd", - "id": 669 - }, - { - "name": "minecraft:dark_oak_boat", - "id": 382 - }, - { - "name": "minecraft:dark_oak_button", - "id": -142 - }, - { - "name": "minecraft:dark_oak_chest_boat", - "id": 650 - }, - { - "name": "minecraft:dark_oak_door", - "id": 564 - }, - { - "name": "minecraft:dark_oak_fence", - "id": -577 - }, - { - "name": "minecraft:dark_oak_fence_gate", - "id": 186 - }, - { - "name": "minecraft:dark_oak_hanging_sign", - "id": -505 - }, - { - "name": "minecraft:dark_oak_log", - "id": -572 - }, - { - "name": "minecraft:dark_oak_pressure_plate", - "id": -152 - }, - { - "name": "minecraft:dark_oak_sign", - "id": 587 - }, - { - "name": "minecraft:dark_oak_stairs", - "id": 164 - }, - { - "name": "minecraft:dark_oak_trapdoor", - "id": -147 - }, - { - "name": "minecraft:dark_prismarine_stairs", - "id": -3 - }, - { - "name": "minecraft:darkoak_standing_sign", - "id": -192 - }, - { - "name": "minecraft:darkoak_wall_sign", - "id": -193 - }, - { - "name": "minecraft:daylight_detector", - "id": 151 - }, - { - "name": "minecraft:daylight_detector_inverted", - "id": 178 - }, - { - "name": "minecraft:dead_brain_coral", - "id": -586 - }, - { - "name": "minecraft:dead_bubble_coral", - "id": -587 - }, - { - "name": "minecraft:dead_fire_coral", - "id": -588 - }, - { - "name": "minecraft:dead_horn_coral", - "id": -589 - }, - { - "name": "minecraft:dead_tube_coral", - "id": -585 - }, - { - "name": "minecraft:deadbush", - "id": 32 - }, - { - "name": "minecraft:decorated_pot", - "id": -551 - }, - { - "name": "minecraft:deepslate", - "id": -378 - }, - { - "name": "minecraft:deepslate_brick_double_slab", - "id": -399 - }, - { - "name": "minecraft:deepslate_brick_slab", - "id": -392 - }, - { - "name": "minecraft:deepslate_brick_stairs", - "id": -393 - }, - { - "name": "minecraft:deepslate_brick_wall", - "id": -394 - }, - { - "name": "minecraft:deepslate_bricks", - "id": -391 - }, - { - "name": "minecraft:deepslate_coal_ore", - "id": -406 - }, - { - "name": "minecraft:deepslate_copper_ore", - "id": -408 - }, - { - "name": "minecraft:deepslate_diamond_ore", - "id": -405 - }, - { - "name": "minecraft:deepslate_emerald_ore", - "id": -407 - }, - { - "name": "minecraft:deepslate_gold_ore", - "id": -402 - }, - { - "name": "minecraft:deepslate_iron_ore", - "id": -401 - }, - { - "name": "minecraft:deepslate_lapis_ore", - "id": -400 - }, - { - "name": "minecraft:deepslate_redstone_ore", - "id": -403 - }, - { - "name": "minecraft:deepslate_tile_double_slab", - "id": -398 - }, - { - "name": "minecraft:deepslate_tile_slab", - "id": -388 - }, - { - "name": "minecraft:deepslate_tile_stairs", - "id": -389 - }, - { - "name": "minecraft:deepslate_tile_wall", - "id": -390 - }, - { - "name": "minecraft:deepslate_tiles", - "id": -387 - }, - { - "name": "minecraft:deny", - "id": 211 - }, - { - "name": "minecraft:detector_rail", - "id": 28 - }, - { - "name": "minecraft:diamond", - "id": 306 - }, - { - "name": "minecraft:diamond_axe", - "id": 321 - }, - { - "name": "minecraft:diamond_block", - "id": 57 - }, - { - "name": "minecraft:diamond_boots", - "id": 352 - }, - { - "name": "minecraft:diamond_chestplate", - "id": 350 - }, - { - "name": "minecraft:diamond_helmet", - "id": 349 - }, - { - "name": "minecraft:diamond_hoe", - "id": 334 - }, - { - "name": "minecraft:diamond_horse_armor", - "id": 540 - }, - { - "name": "minecraft:diamond_leggings", - "id": 351 - }, - { - "name": "minecraft:diamond_ore", - "id": 56 - }, - { - "name": "minecraft:diamond_pickaxe", - "id": 320 - }, - { - "name": "minecraft:diamond_shovel", - "id": 319 - }, - { - "name": "minecraft:diamond_sword", - "id": 318 - }, - { - "name": "minecraft:diorite_stairs", - "id": -170 - }, - { - "name": "minecraft:dirt", - "id": 3 - }, - { - "name": "minecraft:dirt_with_roots", - "id": -318 - }, - { - "name": "minecraft:disc_fragment_5", - "id": 644 - }, - { - "name": "minecraft:dispenser", - "id": 23 - }, - { - "name": "minecraft:dolphin_spawn_egg", - "id": 486 - }, - { - "name": "minecraft:donkey_spawn_egg", - "id": 467 - }, - { - "name": "minecraft:double_cut_copper_slab", - "id": -368 - }, - { - "name": "minecraft:double_plant", - "id": 175 - }, - { - "name": "minecraft:double_stone_block_slab", - "id": 43 - }, - { - "name": "minecraft:double_stone_block_slab2", - "id": 181 - }, - { - "name": "minecraft:double_stone_block_slab3", - "id": -167 - }, - { - "name": "minecraft:double_stone_block_slab4", - "id": -168 - }, - { - "name": "minecraft:double_wooden_slab", - "id": 157 - }, - { - "name": "minecraft:dragon_breath", - "id": 567 - }, - { - "name": "minecraft:dragon_egg", - "id": 122 - }, - { - "name": "minecraft:dried_kelp", - "id": 270 - }, - { - "name": "minecraft:dried_kelp_block", - "id": -139 - }, - { - "name": "minecraft:dripstone_block", - "id": -317 - }, - { - "name": "minecraft:dropper", - "id": 125 - }, - { - "name": "minecraft:drowned_spawn_egg", - "id": 485 - }, - { - "name": "minecraft:dune_armor_trim_smithing_template", - "id": 686 - }, - { - "name": "minecraft:dye", - "id": 715 - }, - { - "name": "minecraft:echo_shard", - "id": 654 - }, - { - "name": "minecraft:egg", - "id": 392 - }, - { - "name": "minecraft:elder_guardian_spawn_egg", - "id": 473 - }, - { - "name": "minecraft:element_0", - "id": 36 - }, - { - "name": "minecraft:element_1", - "id": -12 - }, - { - "name": "minecraft:element_10", - "id": -21 - }, - { - "name": "minecraft:element_100", - "id": -111 - }, - { - "name": "minecraft:element_101", - "id": -112 - }, - { - "name": "minecraft:element_102", - "id": -113 - }, - { - "name": "minecraft:element_103", - "id": -114 - }, - { - "name": "minecraft:element_104", - "id": -115 - }, - { - "name": "minecraft:element_105", - "id": -116 - }, - { - "name": "minecraft:element_106", - "id": -117 - }, - { - "name": "minecraft:element_107", - "id": -118 - }, - { - "name": "minecraft:element_108", - "id": -119 - }, - { - "name": "minecraft:element_109", - "id": -120 - }, - { - "name": "minecraft:element_11", - "id": -22 - }, - { - "name": "minecraft:element_110", - "id": -121 - }, - { - "name": "minecraft:element_111", - "id": -122 - }, - { - "name": "minecraft:element_112", - "id": -123 - }, - { - "name": "minecraft:element_113", - "id": -124 - }, - { - "name": "minecraft:element_114", - "id": -125 - }, - { - "name": "minecraft:element_115", - "id": -126 - }, - { - "name": "minecraft:element_116", - "id": -127 - }, - { - "name": "minecraft:element_117", - "id": -128 - }, - { - "name": "minecraft:element_118", - "id": -129 - }, - { - "name": "minecraft:element_12", - "id": -23 - }, - { - "name": "minecraft:element_13", - "id": -24 - }, - { - "name": "minecraft:element_14", - "id": -25 - }, - { - "name": "minecraft:element_15", - "id": -26 - }, - { - "name": "minecraft:element_16", - "id": -27 - }, - { - "name": "minecraft:element_17", - "id": -28 - }, - { - "name": "minecraft:element_18", - "id": -29 - }, - { - "name": "minecraft:element_19", - "id": -30 - }, - { - "name": "minecraft:element_2", - "id": -13 - }, - { - "name": "minecraft:element_20", - "id": -31 - }, - { - "name": "minecraft:element_21", - "id": -32 - }, - { - "name": "minecraft:element_22", - "id": -33 - }, - { - "name": "minecraft:element_23", - "id": -34 - }, - { - "name": "minecraft:element_24", - "id": -35 - }, - { - "name": "minecraft:element_25", - "id": -36 - }, - { - "name": "minecraft:element_26", - "id": -37 - }, - { - "name": "minecraft:element_27", - "id": -38 - }, - { - "name": "minecraft:element_28", - "id": -39 - }, - { - "name": "minecraft:element_29", - "id": -40 - }, - { - "name": "minecraft:element_3", - "id": -14 - }, - { - "name": "minecraft:element_30", - "id": -41 - }, - { - "name": "minecraft:element_31", - "id": -42 - }, - { - "name": "minecraft:element_32", - "id": -43 - }, - { - "name": "minecraft:element_33", - "id": -44 - }, - { - "name": "minecraft:element_34", - "id": -45 - }, - { - "name": "minecraft:element_35", - "id": -46 - }, - { - "name": "minecraft:element_36", - "id": -47 - }, - { - "name": "minecraft:element_37", - "id": -48 - }, - { - "name": "minecraft:element_38", - "id": -49 - }, - { - "name": "minecraft:element_39", - "id": -50 - }, - { - "name": "minecraft:element_4", - "id": -15 - }, - { - "name": "minecraft:element_40", - "id": -51 - }, - { - "name": "minecraft:element_41", - "id": -52 - }, - { - "name": "minecraft:element_42", - "id": -53 - }, - { - "name": "minecraft:element_43", - "id": -54 - }, - { - "name": "minecraft:element_44", - "id": -55 - }, - { - "name": "minecraft:element_45", - "id": -56 - }, - { - "name": "minecraft:element_46", - "id": -57 - }, - { - "name": "minecraft:element_47", - "id": -58 - }, - { - "name": "minecraft:element_48", - "id": -59 - }, - { - "name": "minecraft:element_49", - "id": -60 - }, - { - "name": "minecraft:element_5", - "id": -16 - }, - { - "name": "minecraft:element_50", - "id": -61 - }, - { - "name": "minecraft:element_51", - "id": -62 - }, - { - "name": "minecraft:element_52", - "id": -63 - }, - { - "name": "minecraft:element_53", - "id": -64 - }, - { - "name": "minecraft:element_54", - "id": -65 - }, - { - "name": "minecraft:element_55", - "id": -66 - }, - { - "name": "minecraft:element_56", - "id": -67 - }, - { - "name": "minecraft:element_57", - "id": -68 - }, - { - "name": "minecraft:element_58", - "id": -69 - }, - { - "name": "minecraft:element_59", - "id": -70 - }, - { - "name": "minecraft:element_6", - "id": -17 - }, - { - "name": "minecraft:element_60", - "id": -71 - }, - { - "name": "minecraft:element_61", - "id": -72 - }, - { - "name": "minecraft:element_62", - "id": -73 - }, - { - "name": "minecraft:element_63", - "id": -74 - }, - { - "name": "minecraft:element_64", - "id": -75 - }, - { - "name": "minecraft:element_65", - "id": -76 - }, - { - "name": "minecraft:element_66", - "id": -77 - }, - { - "name": "minecraft:element_67", - "id": -78 - }, - { - "name": "minecraft:element_68", - "id": -79 - }, - { - "name": "minecraft:element_69", - "id": -80 - }, - { - "name": "minecraft:element_7", - "id": -18 - }, - { - "name": "minecraft:element_70", - "id": -81 - }, - { - "name": "minecraft:element_71", - "id": -82 - }, - { - "name": "minecraft:element_72", - "id": -83 - }, - { - "name": "minecraft:element_73", - "id": -84 - }, - { - "name": "minecraft:element_74", - "id": -85 - }, - { - "name": "minecraft:element_75", - "id": -86 - }, - { - "name": "minecraft:element_76", - "id": -87 - }, - { - "name": "minecraft:element_77", - "id": -88 - }, - { - "name": "minecraft:element_78", - "id": -89 - }, - { - "name": "minecraft:element_79", - "id": -90 - }, - { - "name": "minecraft:element_8", - "id": -19 - }, - { - "name": "minecraft:element_80", - "id": -91 - }, - { - "name": "minecraft:element_81", - "id": -92 - }, - { - "name": "minecraft:element_82", - "id": -93 - }, - { - "name": "minecraft:element_83", - "id": -94 - }, - { - "name": "minecraft:element_84", - "id": -95 - }, - { - "name": "minecraft:element_85", - "id": -96 - }, - { - "name": "minecraft:element_86", - "id": -97 - }, - { - "name": "minecraft:element_87", - "id": -98 - }, - { - "name": "minecraft:element_88", - "id": -99 - }, - { - "name": "minecraft:element_89", - "id": -100 - }, - { - "name": "minecraft:element_9", - "id": -20 - }, - { - "name": "minecraft:element_90", - "id": -101 - }, - { - "name": "minecraft:element_91", - "id": -102 - }, - { - "name": "minecraft:element_92", - "id": -103 - }, - { - "name": "minecraft:element_93", - "id": -104 - }, - { - "name": "minecraft:element_94", - "id": -105 - }, - { - "name": "minecraft:element_95", - "id": -106 - }, - { - "name": "minecraft:element_96", - "id": -107 - }, - { - "name": "minecraft:element_97", - "id": -108 - }, - { - "name": "minecraft:element_98", - "id": -109 - }, - { - "name": "minecraft:element_99", - "id": -110 - }, - { - "name": "minecraft:elytra", - "id": 571 - }, - { - "name": "minecraft:emerald", - "id": 519 - }, - { - "name": "minecraft:emerald_block", - "id": 133 - }, - { - "name": "minecraft:emerald_ore", - "id": 129 - }, - { - "name": "minecraft:empty_map", - "id": 522 - }, - { - "name": "minecraft:enchanted_book", - "id": 528 - }, - { - "name": "minecraft:enchanted_golden_apple", - "id": 259 - }, - { - "name": "minecraft:enchanting_table", - "id": 116 - }, - { - "name": "minecraft:end_brick_stairs", - "id": -178 - }, - { - "name": "minecraft:end_bricks", - "id": 206 - }, - { - "name": "minecraft:end_crystal", - "id": 718 - }, - { - "name": "minecraft:end_gateway", - "id": 209 - }, - { - "name": "minecraft:end_portal", - "id": 119 - }, - { - "name": "minecraft:end_portal_frame", - "id": 120 - }, - { - "name": "minecraft:end_rod", - "id": 208 - }, - { - "name": "minecraft:end_stone", - "id": 121 - }, - { - "name": "minecraft:ender_chest", - "id": 130 - }, - { - "name": "minecraft:ender_dragon_spawn_egg", - "id": 508 - }, - { - "name": "minecraft:ender_eye", - "id": 435 - }, - { - "name": "minecraft:ender_pearl", - "id": 424 - }, - { - "name": "minecraft:enderman_spawn_egg", - "id": 444 - }, - { - "name": "minecraft:endermite_spawn_egg", - "id": 462 - }, - { - "name": "minecraft:evoker_spawn_egg", - "id": 477 - }, - { - "name": "minecraft:experience_bottle", - "id": 515 - }, - { - "name": "minecraft:explorer_pottery_sherd", - "id": 670 - }, - { - "name": "minecraft:exposed_copper", - "id": -341 - }, - { - "name": "minecraft:exposed_cut_copper", - "id": -348 - }, - { - "name": "minecraft:exposed_cut_copper_slab", - "id": -362 - }, - { - "name": "minecraft:exposed_cut_copper_stairs", - "id": -355 - }, - { - "name": "minecraft:exposed_double_cut_copper_slab", - "id": -369 - }, - { - "name": "minecraft:eye_armor_trim_smithing_template", - "id": 690 - }, - { - "name": "minecraft:farmland", - "id": 60 - }, - { - "name": "minecraft:feather", - "id": 329 - }, - { - "name": "minecraft:fence", - "id": 706 - }, - { - "name": "minecraft:fence_gate", - "id": 107 - }, - { - "name": "minecraft:fermented_spider_eye", - "id": 430 - }, - { - "name": "minecraft:field_masoned_banner_pattern", - "id": 592 - }, - { - "name": "minecraft:filled_map", - "id": 422 - }, - { - "name": "minecraft:fire", - "id": 51 - }, - { - "name": "minecraft:fire_charge", - "id": 516 - }, - { - "name": "minecraft:fire_coral", - "id": -583 - }, - { - "name": "minecraft:firework_rocket", - "id": 526 - }, - { - "name": "minecraft:firework_star", - "id": 527 - }, - { - "name": "minecraft:fishing_rod", - "id": 394 - }, - { - "name": "minecraft:fletching_table", - "id": -201 - }, - { - "name": "minecraft:flint", - "id": 358 - }, - { - "name": "minecraft:flint_and_steel", - "id": 301 - }, - { - "name": "minecraft:flower_banner_pattern", - "id": 588 - }, - { - "name": "minecraft:flower_pot", - "id": 521 - }, - { - "name": "minecraft:flowering_azalea", - "id": -338 - }, - { - "name": "minecraft:flowing_lava", - "id": 10 - }, - { - "name": "minecraft:flowing_water", - "id": 8 - }, - { - "name": "minecraft:fox_spawn_egg", - "id": 492 - }, - { - "name": "minecraft:frame", - "id": 520 - }, - { - "name": "minecraft:friend_pottery_sherd", - "id": 671 - }, - { - "name": "minecraft:frog_spawn", - "id": -468 - }, - { - "name": "minecraft:frog_spawn_egg", - "id": 635 - }, - { - "name": "minecraft:frosted_ice", - "id": 207 - }, - { - "name": "minecraft:furnace", - "id": 61 - }, - { - "name": "minecraft:ghast_spawn_egg", - "id": 456 - }, - { - "name": "minecraft:ghast_tear", - "id": 426 - }, - { - "name": "minecraft:gilded_blackstone", - "id": -281 - }, - { - "name": "minecraft:glass", - "id": 20 - }, - { - "name": "minecraft:glass_bottle", - "id": 429 - }, - { - "name": "minecraft:glass_pane", - "id": 102 - }, - { - "name": "minecraft:glistering_melon_slice", - "id": 436 - }, - { - "name": "minecraft:globe_banner_pattern", - "id": 595 - }, - { - "name": "minecraft:glow_berries", - "id": 719 - }, - { - "name": "minecraft:glow_frame", - "id": 630 - }, - { - "name": "minecraft:glow_ink_sac", - "id": 510 - }, - { - "name": "minecraft:glow_lichen", - "id": -411 - }, - { - "name": "minecraft:glow_squid_spawn_egg", - "id": 505 - }, - { - "name": "minecraft:glow_stick", - "id": 608 - }, - { - "name": "minecraft:glowingobsidian", - "id": 246 - }, - { - "name": "minecraft:glowstone", - "id": 89 - }, - { - "name": "minecraft:glowstone_dust", - "id": 396 - }, - { - "name": "minecraft:goat_horn", - "id": 634 - }, - { - "name": "minecraft:goat_spawn_egg", - "id": 504 - }, - { - "name": "minecraft:gold_block", - "id": 41 - }, - { - "name": "minecraft:gold_ingot", - "id": 308 - }, - { - "name": "minecraft:gold_nugget", - "id": 427 - }, - { - "name": "minecraft:gold_ore", - "id": 14 - }, - { - "name": "minecraft:golden_apple", - "id": 258 - }, - { - "name": "minecraft:golden_axe", - "id": 327 - }, - { - "name": "minecraft:golden_boots", - "id": 356 - }, - { - "name": "minecraft:golden_carrot", - "id": 283 - }, - { - "name": "minecraft:golden_chestplate", - "id": 354 - }, - { - "name": "minecraft:golden_helmet", - "id": 353 - }, - { - "name": "minecraft:golden_hoe", - "id": 335 - }, - { - "name": "minecraft:golden_horse_armor", - "id": 539 - }, - { - "name": "minecraft:golden_leggings", - "id": 355 - }, - { - "name": "minecraft:golden_pickaxe", - "id": 326 - }, - { - "name": "minecraft:golden_rail", - "id": 27 - }, - { - "name": "minecraft:golden_shovel", - "id": 325 - }, - { - "name": "minecraft:golden_sword", - "id": 324 - }, - { - "name": "minecraft:granite_stairs", - "id": -169 - }, - { - "name": "minecraft:grass", - "id": 2 - }, - { - "name": "minecraft:grass_path", - "id": 198 - }, - { - "name": "minecraft:gravel", - "id": 13 - }, - { - "name": "minecraft:gray_candle", - "id": -420 - }, - { - "name": "minecraft:gray_candle_cake", - "id": -437 - }, - { - "name": "minecraft:gray_carpet", - "id": -603 - }, - { - "name": "minecraft:gray_concrete", - "id": -634 - }, - { - "name": "minecraft:gray_concrete_powder", - "id": -715 - }, - { - "name": "minecraft:gray_dye", - "id": 405 - }, - { - "name": "minecraft:gray_glazed_terracotta", - "id": 227 - }, - { - "name": "minecraft:gray_shulker_box", - "id": -619 - }, - { - "name": "minecraft:gray_stained_glass", - "id": -679 - }, - { - "name": "minecraft:gray_stained_glass_pane", - "id": -649 - }, - { - "name": "minecraft:gray_terracotta", - "id": -730 - }, - { - "name": "minecraft:gray_wool", - "id": -553 - }, - { - "name": "minecraft:green_candle", - "id": -426 - }, - { - "name": "minecraft:green_candle_cake", - "id": -443 - }, - { - "name": "minecraft:green_carpet", - "id": -609 - }, - { - "name": "minecraft:green_concrete", - "id": -640 - }, - { - "name": "minecraft:green_concrete_powder", - "id": -721 - }, - { - "name": "minecraft:green_dye", - "id": 399 - }, - { - "name": "minecraft:green_glazed_terracotta", - "id": 233 - }, - { - "name": "minecraft:green_shulker_box", - "id": -625 - }, - { - "name": "minecraft:green_stained_glass", - "id": -685 - }, - { - "name": "minecraft:green_stained_glass_pane", - "id": -655 - }, - { - "name": "minecraft:green_terracotta", - "id": -736 - }, - { - "name": "minecraft:green_wool", - "id": -560 - }, - { - "name": "minecraft:grindstone", - "id": -195 - }, - { - "name": "minecraft:guardian_spawn_egg", - "id": 463 - }, - { - "name": "minecraft:gunpowder", - "id": 330 - }, - { - "name": "minecraft:hanging_roots", - "id": -319 - }, - { - "name": "minecraft:hard_glass", - "id": 253 - }, - { - "name": "minecraft:hard_glass_pane", - "id": 190 - }, - { - "name": "minecraft:hard_stained_glass", - "id": 254 - }, - { - "name": "minecraft:hard_stained_glass_pane", - "id": 191 - }, - { - "name": "minecraft:hardened_clay", - "id": 172 - }, - { - "name": "minecraft:hay_block", - "id": 170 - }, - { - "name": "minecraft:heart_of_the_sea", - "id": 578 - }, - { - "name": "minecraft:heart_pottery_sherd", - "id": 672 - }, - { - "name": "minecraft:heartbreak_pottery_sherd", - "id": 673 - }, - { - "name": "minecraft:heavy_weighted_pressure_plate", - "id": 148 - }, - { - "name": "minecraft:hoglin_spawn_egg", - "id": 498 - }, - { - "name": "minecraft:honey_block", - "id": -220 - }, - { - "name": "minecraft:honey_bottle", - "id": 599 - }, - { - "name": "minecraft:honeycomb", - "id": 598 - }, - { - "name": "minecraft:honeycomb_block", - "id": -221 - }, - { - "name": "minecraft:hopper", - "id": 534 - }, - { - "name": "minecraft:hopper_minecart", - "id": 533 - }, - { - "name": "minecraft:horn_coral", - "id": -584 - }, - { - "name": "minecraft:horse_spawn_egg", - "id": 460 - }, - { - "name": "minecraft:host_armor_trim_smithing_template", - "id": 700 - }, - { - "name": "minecraft:howl_pottery_sherd", - "id": 674 - }, - { - "name": "minecraft:husk_spawn_egg", - "id": 465 - }, - { - "name": "minecraft:ice", - "id": 79 - }, - { - "name": "minecraft:ice_bomb", - "id": 602 - }, - { - "name": "minecraft:infested_deepslate", - "id": -454 - }, - { - "name": "minecraft:info_update", - "id": 248 - }, - { - "name": "minecraft:info_update2", - "id": 249 - }, - { - "name": "minecraft:ink_sac", - "id": 415 - }, - { - "name": "minecraft:invisible_bedrock", - "id": 95 - }, - { - "name": "minecraft:iron_axe", - "id": 300 - }, - { - "name": "minecraft:iron_bars", - "id": 101 - }, - { - "name": "minecraft:iron_block", - "id": 42 - }, - { - "name": "minecraft:iron_boots", - "id": 348 - }, - { - "name": "minecraft:iron_chestplate", - "id": 346 - }, - { - "name": "minecraft:iron_door", - "id": 374 - }, - { - "name": "minecraft:iron_golem_spawn_egg", - "id": 506 - }, - { - "name": "minecraft:iron_helmet", - "id": 345 - }, - { - "name": "minecraft:iron_hoe", - "id": 333 - }, - { - "name": "minecraft:iron_horse_armor", - "id": 538 - }, - { - "name": "minecraft:iron_ingot", - "id": 307 - }, - { - "name": "minecraft:iron_leggings", - "id": 347 - }, - { - "name": "minecraft:iron_nugget", - "id": 576 - }, - { - "name": "minecraft:iron_ore", - "id": 15 - }, - { - "name": "minecraft:iron_pickaxe", - "id": 299 - }, - { - "name": "minecraft:iron_shovel", - "id": 298 - }, - { - "name": "minecraft:iron_sword", - "id": 309 - }, - { - "name": "minecraft:iron_trapdoor", - "id": 167 - }, - { - "name": "minecraft:item.acacia_door", - "id": 196 - }, - { - "name": "minecraft:item.bed", - "id": 26 - }, - { - "name": "minecraft:item.beetroot", - "id": 244 - }, - { - "name": "minecraft:item.birch_door", - "id": 194 - }, - { - "name": "minecraft:item.brewing_stand", - "id": 117 - }, - { - "name": "minecraft:item.cake", - "id": 92 - }, - { - "name": "minecraft:item.camera", - "id": 242 - }, - { - "name": "minecraft:item.campfire", - "id": -209 - }, - { - "name": "minecraft:item.cauldron", - "id": 118 - }, - { - "name": "minecraft:item.chain", - "id": -286 - }, - { - "name": "minecraft:item.crimson_door", - "id": -244 - }, - { - "name": "minecraft:item.dark_oak_door", - "id": 197 - }, - { - "name": "minecraft:item.flower_pot", - "id": 140 - }, - { - "name": "minecraft:item.frame", - "id": 199 - }, - { - "name": "minecraft:item.glow_frame", - "id": -339 - }, - { - "name": "minecraft:item.hopper", - "id": 154 - }, - { - "name": "minecraft:item.iron_door", - "id": 71 - }, - { - "name": "minecraft:item.jungle_door", - "id": 195 - }, - { - "name": "minecraft:item.kelp", - "id": -138 - }, - { - "name": "minecraft:item.mangrove_door", - "id": -493 - }, - { - "name": "minecraft:item.nether_sprouts", - "id": -238 - }, - { - "name": "minecraft:item.nether_wart", - "id": 115 - }, - { - "name": "minecraft:item.reeds", - "id": 83 - }, - { - "name": "minecraft:item.skull", - "id": 144 - }, - { - "name": "minecraft:item.soul_campfire", - "id": -290 - }, - { - "name": "minecraft:item.spruce_door", - "id": 193 - }, - { - "name": "minecraft:item.warped_door", - "id": -245 - }, - { - "name": "minecraft:item.wheat", - "id": 59 - }, - { - "name": "minecraft:item.wooden_door", - "id": 64 - }, - { - "name": "minecraft:jigsaw", - "id": -211 - }, - { - "name": "minecraft:jukebox", - "id": 84 - }, - { - "name": "minecraft:jungle_boat", - "id": 379 - }, - { - "name": "minecraft:jungle_button", - "id": -143 - }, - { - "name": "minecraft:jungle_chest_boat", - "id": 647 - }, - { - "name": "minecraft:jungle_door", - "id": 562 - }, - { - "name": "minecraft:jungle_fence", - "id": -578 - }, - { - "name": "minecraft:jungle_fence_gate", - "id": 185 - }, - { - "name": "minecraft:jungle_hanging_sign", - "id": -503 - }, - { - "name": "minecraft:jungle_log", - "id": -571 - }, - { - "name": "minecraft:jungle_pressure_plate", - "id": -153 - }, - { - "name": "minecraft:jungle_sign", - "id": 585 - }, - { - "name": "minecraft:jungle_stairs", - "id": 136 - }, - { - "name": "minecraft:jungle_standing_sign", - "id": -188 - }, - { - "name": "minecraft:jungle_trapdoor", - "id": -148 - }, - { - "name": "minecraft:jungle_wall_sign", - "id": -189 - }, - { - "name": "minecraft:kelp", - "id": 384 - }, - { - "name": "minecraft:ladder", - "id": 65 - }, - { - "name": "minecraft:lantern", - "id": -208 - }, - { - "name": "minecraft:lapis_block", - "id": 22 - }, - { - "name": "minecraft:lapis_lazuli", - "id": 416 - }, - { - "name": "minecraft:lapis_ore", - "id": 21 - }, - { - "name": "minecraft:large_amethyst_bud", - "id": -330 - }, - { - "name": "minecraft:lava", - "id": 11 - }, - { - "name": "minecraft:lava_bucket", - "id": 365 - }, - { - "name": "minecraft:lead", - "id": 554 - }, - { - "name": "minecraft:leather", - "id": 383 - }, - { - "name": "minecraft:leather_boots", - "id": 340 - }, - { - "name": "minecraft:leather_chestplate", - "id": 338 - }, - { - "name": "minecraft:leather_helmet", - "id": 337 - }, - { - "name": "minecraft:leather_horse_armor", - "id": 537 - }, - { - "name": "minecraft:leather_leggings", - "id": 339 - }, - { - "name": "minecraft:leaves", - "id": 18 - }, - { - "name": "minecraft:leaves2", - "id": 161 - }, - { - "name": "minecraft:lectern", - "id": -194 - }, - { - "name": "minecraft:lever", - "id": 69 - }, - { - "name": "minecraft:light_block", - "id": -215 - }, - { - "name": "minecraft:light_blue_candle", - "id": -416 - }, - { - "name": "minecraft:light_blue_candle_cake", - "id": -433 - }, - { - "name": "minecraft:light_blue_carpet", - "id": -599 - }, - { - "name": "minecraft:light_blue_concrete", - "id": -630 - }, - { - "name": "minecraft:light_blue_concrete_powder", - "id": -711 - }, - { - "name": "minecraft:light_blue_dye", - "id": 409 - }, - { - "name": "minecraft:light_blue_glazed_terracotta", - "id": 223 - }, - { - "name": "minecraft:light_blue_shulker_box", - "id": -615 - }, - { - "name": "minecraft:light_blue_stained_glass", - "id": -675 - }, - { - "name": "minecraft:light_blue_stained_glass_pane", - "id": -645 - }, - { - "name": "minecraft:light_blue_terracotta", - "id": -726 - }, - { - "name": "minecraft:light_blue_wool", - "id": -562 - }, - { - "name": "minecraft:light_gray_candle", - "id": -421 - }, - { - "name": "minecraft:light_gray_candle_cake", - "id": -438 - }, - { - "name": "minecraft:light_gray_carpet", - "id": -604 - }, - { - "name": "minecraft:light_gray_concrete", - "id": -635 - }, - { - "name": "minecraft:light_gray_concrete_powder", - "id": -716 - }, - { - "name": "minecraft:light_gray_dye", - "id": 404 - }, - { - "name": "minecraft:light_gray_shulker_box", - "id": -620 - }, - { - "name": "minecraft:light_gray_stained_glass", - "id": -680 - }, - { - "name": "minecraft:light_gray_stained_glass_pane", - "id": -650 - }, - { - "name": "minecraft:light_gray_terracotta", - "id": -731 - }, - { - "name": "minecraft:light_gray_wool", - "id": -552 - }, - { - "name": "minecraft:light_weighted_pressure_plate", - "id": 147 - }, - { - "name": "minecraft:lightning_rod", - "id": -312 - }, - { - "name": "minecraft:lime_candle", - "id": -418 - }, - { - "name": "minecraft:lime_candle_cake", - "id": -435 - }, - { - "name": "minecraft:lime_carpet", - "id": -601 - }, - { - "name": "minecraft:lime_concrete", - "id": -632 - }, - { - "name": "minecraft:lime_concrete_powder", - "id": -713 - }, - { - "name": "minecraft:lime_dye", - "id": 407 - }, - { - "name": "minecraft:lime_glazed_terracotta", - "id": 225 - }, - { - "name": "minecraft:lime_shulker_box", - "id": -617 - }, - { - "name": "minecraft:lime_stained_glass", - "id": -677 - }, - { - "name": "minecraft:lime_stained_glass_pane", - "id": -647 - }, - { - "name": "minecraft:lime_terracotta", - "id": -728 - }, - { - "name": "minecraft:lime_wool", - "id": -559 - }, - { - "name": "minecraft:lingering_potion", - "id": 569 - }, - { - "name": "minecraft:lit_blast_furnace", - "id": -214 - }, - { - "name": "minecraft:lit_deepslate_redstone_ore", - "id": -404 - }, - { - "name": "minecraft:lit_furnace", - "id": 62 - }, - { - "name": "minecraft:lit_pumpkin", - "id": 91 - }, - { - "name": "minecraft:lit_redstone_lamp", - "id": 124 - }, - { - "name": "minecraft:lit_redstone_ore", - "id": 74 - }, - { - "name": "minecraft:lit_smoker", - "id": -199 - }, - { - "name": "minecraft:llama_spawn_egg", - "id": 475 - }, - { - "name": "minecraft:lodestone", - "id": -222 - }, - { - "name": "minecraft:lodestone_compass", - "id": 609 - }, - { - "name": "minecraft:log", - "id": 705 - }, - { - "name": "minecraft:log2", - "id": 708 - }, - { - "name": "minecraft:loom", - "id": -204 - }, - { - "name": "minecraft:magenta_candle", - "id": -415 - }, - { - "name": "minecraft:magenta_candle_cake", - "id": -432 - }, - { - "name": "minecraft:magenta_carpet", - "id": -598 - }, - { - "name": "minecraft:magenta_concrete", - "id": -629 - }, - { - "name": "minecraft:magenta_concrete_powder", - "id": -710 - }, - { - "name": "minecraft:magenta_dye", - "id": 410 - }, - { - "name": "minecraft:magenta_glazed_terracotta", - "id": 222 - }, - { - "name": "minecraft:magenta_shulker_box", - "id": -614 - }, - { - "name": "minecraft:magenta_stained_glass", - "id": -674 - }, - { - "name": "minecraft:magenta_stained_glass_pane", - "id": -644 - }, - { - "name": "minecraft:magenta_terracotta", - "id": -725 - }, - { - "name": "minecraft:magenta_wool", - "id": -565 - }, - { - "name": "minecraft:magma", - "id": 213 - }, - { - "name": "minecraft:magma_cream", - "id": 432 - }, - { - "name": "minecraft:magma_cube_spawn_egg", - "id": 457 - }, - { - "name": "minecraft:mangrove_boat", - "id": 642 - }, - { - "name": "minecraft:mangrove_button", - "id": -487 - }, - { - "name": "minecraft:mangrove_chest_boat", - "id": 651 - }, - { - "name": "minecraft:mangrove_door", - "id": 640 - }, - { - "name": "minecraft:mangrove_double_slab", - "id": -499 - }, - { - "name": "minecraft:mangrove_fence", - "id": -491 - }, - { - "name": "minecraft:mangrove_fence_gate", - "id": -492 - }, - { - "name": "minecraft:mangrove_hanging_sign", - "id": -508 - }, - { - "name": "minecraft:mangrove_leaves", - "id": -472 - }, - { - "name": "minecraft:mangrove_log", - "id": -484 - }, - { - "name": "minecraft:mangrove_planks", - "id": -486 - }, - { - "name": "minecraft:mangrove_pressure_plate", - "id": -490 - }, - { - "name": "minecraft:mangrove_propagule", - "id": -474 - }, - { - "name": "minecraft:mangrove_roots", - "id": -482 - }, - { - "name": "minecraft:mangrove_sign", - "id": 641 - }, - { - "name": "minecraft:mangrove_slab", - "id": -489 - }, - { - "name": "minecraft:mangrove_stairs", - "id": -488 - }, - { - "name": "minecraft:mangrove_standing_sign", - "id": -494 - }, - { - "name": "minecraft:mangrove_trapdoor", - "id": -496 - }, - { - "name": "minecraft:mangrove_wall_sign", - "id": -495 - }, - { - "name": "minecraft:mangrove_wood", - "id": -497 - }, - { - "name": "minecraft:medicine", - "id": 606 - }, - { - "name": "minecraft:medium_amethyst_bud", - "id": -331 - }, - { - "name": "minecraft:melon_block", - "id": 103 - }, - { - "name": "minecraft:melon_seeds", - "id": 293 - }, - { - "name": "minecraft:melon_slice", - "id": 272 - }, - { - "name": "minecraft:melon_stem", - "id": 105 - }, - { - "name": "minecraft:milk_bucket", - "id": 363 - }, - { - "name": "minecraft:minecart", - "id": 372 - }, - { - "name": "minecraft:miner_pottery_sherd", - "id": 675 - }, - { - "name": "minecraft:mob_spawner", - "id": 52 - }, - { - "name": "minecraft:mojang_banner_pattern", - "id": 591 - }, - { - "name": "minecraft:monster_egg", - "id": 97 - }, - { - "name": "minecraft:mooshroom_spawn_egg", - "id": 442 - }, - { - "name": "minecraft:moss_block", - "id": -320 - }, - { - "name": "minecraft:moss_carpet", - "id": -335 - }, - { - "name": "minecraft:mossy_cobblestone", - "id": 48 - }, - { - "name": "minecraft:mossy_cobblestone_stairs", - "id": -179 - }, - { - "name": "minecraft:mossy_stone_brick_stairs", - "id": -175 - }, - { - "name": "minecraft:mourner_pottery_sherd", - "id": 676 - }, - { - "name": "minecraft:moving_block", - "id": 250 - }, - { - "name": "minecraft:mud", - "id": -473 - }, - { - "name": "minecraft:mud_brick_double_slab", - "id": -479 - }, - { - "name": "minecraft:mud_brick_slab", - "id": -478 - }, - { - "name": "minecraft:mud_brick_stairs", - "id": -480 - }, - { - "name": "minecraft:mud_brick_wall", - "id": -481 - }, - { - "name": "minecraft:mud_bricks", - "id": -475 - }, - { - "name": "minecraft:muddy_mangrove_roots", - "id": -483 - }, - { - "name": "minecraft:mule_spawn_egg", - "id": 468 - }, - { - "name": "minecraft:mushroom_stew", - "id": 260 - }, - { - "name": "minecraft:music_disc_11", - "id": 551 - }, - { - "name": "minecraft:music_disc_13", - "id": 541 - }, - { - "name": "minecraft:music_disc_5", - "id": 643 - }, - { - "name": "minecraft:music_disc_blocks", - "id": 543 - }, - { - "name": "minecraft:music_disc_cat", - "id": 542 - }, - { - "name": "minecraft:music_disc_chirp", - "id": 544 - }, - { - "name": "minecraft:music_disc_far", - "id": 545 - }, - { - "name": "minecraft:music_disc_mall", - "id": 546 - }, - { - "name": "minecraft:music_disc_mellohi", - "id": 547 - }, - { - "name": "minecraft:music_disc_otherside", - "id": 633 - }, - { - "name": "minecraft:music_disc_pigstep", - "id": 627 - }, - { - "name": "minecraft:music_disc_relic", - "id": 701 - }, - { - "name": "minecraft:music_disc_stal", - "id": 548 - }, - { - "name": "minecraft:music_disc_strad", - "id": 549 - }, - { - "name": "minecraft:music_disc_wait", - "id": 552 - }, - { - "name": "minecraft:music_disc_ward", - "id": 550 - }, - { - "name": "minecraft:mutton", - "id": 557 - }, - { - "name": "minecraft:mycelium", - "id": 110 - }, - { - "name": "minecraft:name_tag", - "id": 555 - }, - { - "name": "minecraft:nautilus_shell", - "id": 577 - }, - { - "name": "minecraft:nether_brick", - "id": 112 - }, - { - "name": "minecraft:nether_brick_fence", - "id": 113 - }, - { - "name": "minecraft:nether_brick_stairs", - "id": 114 - }, - { - "name": "minecraft:nether_gold_ore", - "id": -288 - }, - { - "name": "minecraft:nether_sprouts", - "id": 628 - }, - { - "name": "minecraft:nether_star", - "id": 525 - }, - { - "name": "minecraft:nether_wart", - "id": 294 - }, - { - "name": "minecraft:nether_wart_block", - "id": 214 - }, - { - "name": "minecraft:netherbrick", - "id": 530 - }, - { - "name": "minecraft:netherite_axe", - "id": 613 - }, - { - "name": "minecraft:netherite_block", - "id": -270 - }, - { - "name": "minecraft:netherite_boots", - "id": 619 - }, - { - "name": "minecraft:netherite_chestplate", - "id": 617 - }, - { - "name": "minecraft:netherite_helmet", - "id": 616 - }, - { - "name": "minecraft:netherite_hoe", - "id": 614 - }, - { - "name": "minecraft:netherite_ingot", - "id": 615 - }, - { - "name": "minecraft:netherite_leggings", - "id": 618 - }, - { - "name": "minecraft:netherite_pickaxe", - "id": 612 - }, - { - "name": "minecraft:netherite_scrap", - "id": 620 - }, - { - "name": "minecraft:netherite_shovel", - "id": 611 - }, - { - "name": "minecraft:netherite_sword", - "id": 610 - }, - { - "name": "minecraft:netherite_upgrade_smithing_template", - "id": 684 - }, - { - "name": "minecraft:netherrack", - "id": 87 - }, - { - "name": "minecraft:netherreactor", - "id": 247 - }, - { - "name": "minecraft:normal_stone_stairs", - "id": -180 - }, - { - "name": "minecraft:noteblock", - "id": 25 - }, - { - "name": "minecraft:npc_spawn_egg", - "id": 472 - }, - { - "name": "minecraft:oak_boat", - "id": 377 - }, - { - "name": "minecraft:oak_chest_boat", - "id": 645 - }, - { - "name": "minecraft:oak_fence", - "id": 85 - }, - { - "name": "minecraft:oak_hanging_sign", - "id": -500 - }, - { - "name": "minecraft:oak_log", - "id": 17 - }, - { - "name": "minecraft:oak_sign", - "id": 360 - }, - { - "name": "minecraft:oak_stairs", - "id": 53 - }, - { - "name": "minecraft:observer", - "id": 251 - }, - { - "name": "minecraft:obsidian", - "id": 49 - }, - { - "name": "minecraft:ocelot_spawn_egg", - "id": 453 - }, - { - "name": "minecraft:ochre_froglight", - "id": -471 - }, - { - "name": "minecraft:orange_candle", - "id": -414 - }, - { - "name": "minecraft:orange_candle_cake", - "id": -431 - }, - { - "name": "minecraft:orange_carpet", - "id": -597 - }, - { - "name": "minecraft:orange_concrete", - "id": -628 - }, - { - "name": "minecraft:orange_concrete_powder", - "id": -709 - }, - { - "name": "minecraft:orange_dye", - "id": 411 - }, - { - "name": "minecraft:orange_glazed_terracotta", - "id": 221 - }, - { - "name": "minecraft:orange_shulker_box", - "id": -613 - }, - { - "name": "minecraft:orange_stained_glass", - "id": -673 - }, - { - "name": "minecraft:orange_stained_glass_pane", - "id": -643 - }, - { - "name": "minecraft:orange_terracotta", - "id": -724 - }, - { - "name": "minecraft:orange_wool", - "id": -557 - }, - { - "name": "minecraft:oxidized_copper", - "id": -343 - }, - { - "name": "minecraft:oxidized_cut_copper", - "id": -350 - }, - { - "name": "minecraft:oxidized_cut_copper_slab", - "id": -364 - }, - { - "name": "minecraft:oxidized_cut_copper_stairs", - "id": -357 - }, - { - "name": "minecraft:oxidized_double_cut_copper_slab", - "id": -371 - }, - { - "name": "minecraft:packed_ice", - "id": 174 - }, - { - "name": "minecraft:packed_mud", - "id": -477 - }, - { - "name": "minecraft:painting", - "id": 359 - }, - { - "name": "minecraft:panda_spawn_egg", - "id": 491 - }, - { - "name": "minecraft:paper", - "id": 388 - }, - { - "name": "minecraft:parrot_spawn_egg", - "id": 480 - }, - { - "name": "minecraft:pearlescent_froglight", - "id": -469 - }, - { - "name": "minecraft:phantom_membrane", - "id": 581 - }, - { - "name": "minecraft:phantom_spawn_egg", - "id": 488 - }, - { - "name": "minecraft:pig_spawn_egg", - "id": 439 - }, - { - "name": "minecraft:piglin_banner_pattern", - "id": 594 - }, - { - "name": "minecraft:piglin_brute_spawn_egg", - "id": 501 - }, - { - "name": "minecraft:piglin_spawn_egg", - "id": 499 - }, - { - "name": "minecraft:pillager_spawn_egg", - "id": 493 - }, - { - "name": "minecraft:pink_candle", - "id": -419 - }, - { - "name": "minecraft:pink_candle_cake", - "id": -436 - }, - { - "name": "minecraft:pink_carpet", - "id": -602 - }, - { - "name": "minecraft:pink_concrete", - "id": -633 - }, - { - "name": "minecraft:pink_concrete_powder", - "id": -714 - }, - { - "name": "minecraft:pink_dye", - "id": 406 - }, - { - "name": "minecraft:pink_glazed_terracotta", - "id": 226 - }, - { - "name": "minecraft:pink_petals", - "id": -549 - }, - { - "name": "minecraft:pink_shulker_box", - "id": -618 - }, - { - "name": "minecraft:pink_stained_glass", - "id": -678 - }, - { - "name": "minecraft:pink_stained_glass_pane", - "id": -648 - }, - { - "name": "minecraft:pink_terracotta", - "id": -729 - }, - { - "name": "minecraft:pink_wool", - "id": -566 - }, - { - "name": "minecraft:piston", - "id": 33 - }, - { - "name": "minecraft:piston_arm_collision", - "id": 34 - }, - { - "name": "minecraft:pitcher_crop", - "id": -574 - }, - { - "name": "minecraft:pitcher_plant", - "id": -612 - }, - { - "name": "minecraft:pitcher_pod", - "id": 297 - }, - { - "name": "minecraft:planks", - "id": 5 - }, - { - "name": "minecraft:plenty_pottery_sherd", - "id": 677 - }, - { - "name": "minecraft:podzol", - "id": 243 - }, - { - "name": "minecraft:pointed_dripstone", - "id": -308 - }, - { - "name": "minecraft:poisonous_potato", - "id": 282 - }, - { - "name": "minecraft:polar_bear_spawn_egg", - "id": 474 - }, - { - "name": "minecraft:polished_andesite_stairs", - "id": -174 - }, - { - "name": "minecraft:polished_basalt", - "id": -235 - }, - { - "name": "minecraft:polished_blackstone", - "id": -291 - }, - { - "name": "minecraft:polished_blackstone_brick_double_slab", - "id": -285 - }, - { - "name": "minecraft:polished_blackstone_brick_slab", - "id": -284 - }, - { - "name": "minecraft:polished_blackstone_brick_stairs", - "id": -275 - }, - { - "name": "minecraft:polished_blackstone_brick_wall", - "id": -278 - }, - { - "name": "minecraft:polished_blackstone_bricks", - "id": -274 - }, - { - "name": "minecraft:polished_blackstone_button", - "id": -296 - }, - { - "name": "minecraft:polished_blackstone_double_slab", - "id": -294 - }, - { - "name": "minecraft:polished_blackstone_pressure_plate", - "id": -295 - }, - { - "name": "minecraft:polished_blackstone_slab", - "id": -293 - }, - { - "name": "minecraft:polished_blackstone_stairs", - "id": -292 - }, - { - "name": "minecraft:polished_blackstone_wall", - "id": -297 - }, - { - "name": "minecraft:polished_deepslate", - "id": -383 - }, - { - "name": "minecraft:polished_deepslate_double_slab", - "id": -397 - }, - { - "name": "minecraft:polished_deepslate_slab", - "id": -384 - }, - { - "name": "minecraft:polished_deepslate_stairs", - "id": -385 - }, - { - "name": "minecraft:polished_deepslate_wall", - "id": -386 - }, - { - "name": "minecraft:polished_diorite_stairs", - "id": -173 - }, - { - "name": "minecraft:polished_granite_stairs", - "id": -172 - }, - { - "name": "minecraft:popped_chorus_fruit", - "id": 566 - }, - { - "name": "minecraft:porkchop", - "id": 262 - }, - { - "name": "minecraft:portal", - "id": 90 - }, - { - "name": "minecraft:potato", - "id": 280 - }, - { - "name": "minecraft:potatoes", - "id": 142 - }, - { - "name": "minecraft:potion", - "id": 428 - }, - { - "name": "minecraft:powder_snow", - "id": -306 - }, - { - "name": "minecraft:powder_snow_bucket", - "id": 370 - }, - { - "name": "minecraft:powered_comparator", - "id": 150 - }, - { - "name": "minecraft:powered_repeater", - "id": 94 - }, - { - "name": "minecraft:prismarine", - "id": 168 - }, - { - "name": "minecraft:prismarine_bricks_stairs", - "id": -4 - }, - { - "name": "minecraft:prismarine_crystals", - "id": 556 - }, - { - "name": "minecraft:prismarine_shard", - "id": 572 - }, - { - "name": "minecraft:prismarine_stairs", - "id": -2 - }, - { - "name": "minecraft:prize_pottery_sherd", - "id": 678 - }, - { - "name": "minecraft:pufferfish", - "id": 267 - }, - { - "name": "minecraft:pufferfish_bucket", - "id": 369 - }, - { - "name": "minecraft:pufferfish_spawn_egg", - "id": 483 - }, - { - "name": "minecraft:pumpkin", - "id": 86 - }, - { - "name": "minecraft:pumpkin_pie", - "id": 284 - }, - { - "name": "minecraft:pumpkin_seeds", - "id": 292 - }, - { - "name": "minecraft:pumpkin_stem", - "id": 104 - }, - { - "name": "minecraft:purple_candle", - "id": -423 - }, - { - "name": "minecraft:purple_candle_cake", - "id": -440 - }, - { - "name": "minecraft:purple_carpet", - "id": -606 - }, - { - "name": "minecraft:purple_concrete", - "id": -637 - }, - { - "name": "minecraft:purple_concrete_powder", - "id": -718 - }, - { - "name": "minecraft:purple_dye", - "id": 402 - }, - { - "name": "minecraft:purple_glazed_terracotta", - "id": 219 - }, - { - "name": "minecraft:purple_shulker_box", - "id": -622 - }, - { - "name": "minecraft:purple_stained_glass", - "id": -682 - }, - { - "name": "minecraft:purple_stained_glass_pane", - "id": -652 - }, - { - "name": "minecraft:purple_terracotta", - "id": -733 - }, - { - "name": "minecraft:purple_wool", - "id": -564 - }, - { - "name": "minecraft:purpur_block", - "id": 201 - }, - { - "name": "minecraft:purpur_stairs", - "id": 203 - }, - { - "name": "minecraft:quartz", - "id": 531 - }, - { - "name": "minecraft:quartz_block", - "id": 155 - }, - { - "name": "minecraft:quartz_bricks", - "id": -304 - }, - { - "name": "minecraft:quartz_ore", - "id": 153 - }, - { - "name": "minecraft:quartz_stairs", - "id": 156 - }, - { - "name": "minecraft:rabbit", - "id": 288 - }, - { - "name": "minecraft:rabbit_foot", - "id": 535 - }, - { - "name": "minecraft:rabbit_hide", - "id": 536 - }, - { - "name": "minecraft:rabbit_spawn_egg", - "id": 461 - }, - { - "name": "minecraft:rabbit_stew", - "id": 290 - }, - { - "name": "minecraft:rail", - "id": 66 - }, - { - "name": "minecraft:raiser_armor_trim_smithing_template", - "id": 698 - }, - { - "name": "minecraft:rapid_fertilizer", - "id": 604 - }, - { - "name": "minecraft:ravager_spawn_egg", - "id": 495 - }, - { - "name": "minecraft:raw_copper", - "id": 514 - }, - { - "name": "minecraft:raw_copper_block", - "id": -452 - }, - { - "name": "minecraft:raw_gold", - "id": 513 - }, - { - "name": "minecraft:raw_gold_block", - "id": -453 - }, - { - "name": "minecraft:raw_iron", - "id": 512 - }, - { - "name": "minecraft:raw_iron_block", - "id": -451 - }, - { - "name": "minecraft:recovery_compass", - "id": 653 - }, - { - "name": "minecraft:red_candle", - "id": -427 - }, - { - "name": "minecraft:red_candle_cake", - "id": -444 - }, - { - "name": "minecraft:red_carpet", - "id": -610 - }, - { - "name": "minecraft:red_concrete", - "id": -641 - }, - { - "name": "minecraft:red_concrete_powder", - "id": -722 - }, - { - "name": "minecraft:red_dye", - "id": 398 - }, - { - "name": "minecraft:red_flower", - "id": 38 - }, - { - "name": "minecraft:red_glazed_terracotta", - "id": 234 - }, - { - "name": "minecraft:red_mushroom", - "id": 40 - }, - { - "name": "minecraft:red_mushroom_block", - "id": 100 - }, - { - "name": "minecraft:red_nether_brick", - "id": 215 - }, - { - "name": "minecraft:red_nether_brick_stairs", - "id": -184 - }, - { - "name": "minecraft:red_sandstone", - "id": 179 - }, - { - "name": "minecraft:red_sandstone_stairs", - "id": 180 - }, - { - "name": "minecraft:red_shulker_box", - "id": -626 - }, - { - "name": "minecraft:red_stained_glass", - "id": -686 - }, - { - "name": "minecraft:red_stained_glass_pane", - "id": -656 - }, - { - "name": "minecraft:red_terracotta", - "id": -737 - }, - { - "name": "minecraft:red_wool", - "id": -556 - }, - { - "name": "minecraft:redstone", - "id": 375 - }, - { - "name": "minecraft:redstone_block", - "id": 152 - }, - { - "name": "minecraft:redstone_lamp", - "id": 123 - }, - { - "name": "minecraft:redstone_ore", - "id": 73 - }, - { - "name": "minecraft:redstone_torch", - "id": 76 - }, - { - "name": "minecraft:redstone_wire", - "id": 55 - }, - { - "name": "minecraft:reinforced_deepslate", - "id": -466 - }, - { - "name": "minecraft:repeater", - "id": 421 - }, - { - "name": "minecraft:repeating_command_block", - "id": 188 - }, - { - "name": "minecraft:reserved6", - "id": 255 - }, - { - "name": "minecraft:respawn_anchor", - "id": -272 - }, - { - "name": "minecraft:rib_armor_trim_smithing_template", - "id": 694 - }, - { - "name": "minecraft:rotten_flesh", - "id": 277 - }, - { - "name": "minecraft:saddle", - "id": 373 - }, - { - "name": "minecraft:salmon", - "id": 265 - }, - { - "name": "minecraft:salmon_bucket", - "id": 367 - }, - { - "name": "minecraft:salmon_spawn_egg", - "id": 484 - }, - { - "name": "minecraft:sand", - "id": 12 - }, - { - "name": "minecraft:sandstone", - "id": 24 - }, - { - "name": "minecraft:sandstone_stairs", - "id": 128 - }, - { - "name": "minecraft:sapling", - "id": 6 - }, - { - "name": "minecraft:scaffolding", - "id": -165 - }, - { - "name": "minecraft:sculk", - "id": -458 - }, - { - "name": "minecraft:sculk_catalyst", - "id": -460 - }, - { - "name": "minecraft:sculk_sensor", - "id": -307 - }, - { - "name": "minecraft:sculk_shrieker", - "id": -461 - }, - { - "name": "minecraft:sculk_vein", - "id": -459 - }, - { - "name": "minecraft:scute", - "id": 579 - }, - { - "name": "minecraft:sea_lantern", - "id": 169 - }, - { - "name": "minecraft:sea_pickle", - "id": -156 - }, - { - "name": "minecraft:seagrass", - "id": -130 - }, - { - "name": "minecraft:sentry_armor_trim_smithing_template", - "id": 685 - }, - { - "name": "minecraft:shaper_armor_trim_smithing_template", - "id": 699 - }, - { - "name": "minecraft:sheaf_pottery_sherd", - "id": 679 - }, - { - "name": "minecraft:shears", - "id": 423 - }, - { - "name": "minecraft:sheep_spawn_egg", - "id": 440 - }, - { - "name": "minecraft:shelter_pottery_sherd", - "id": 680 - }, - { - "name": "minecraft:shield", - "id": 357 - }, - { - "name": "minecraft:shroomlight", - "id": -230 - }, - { - "name": "minecraft:shulker_box", - "id": 713 - }, - { - "name": "minecraft:shulker_shell", - "id": 573 - }, - { - "name": "minecraft:shulker_spawn_egg", - "id": 471 - }, - { - "name": "minecraft:silence_armor_trim_smithing_template", - "id": 696 - }, - { - "name": "minecraft:silver_glazed_terracotta", - "id": 228 - }, - { - "name": "minecraft:silverfish_spawn_egg", - "id": 445 - }, - { - "name": "minecraft:skeleton_horse_spawn_egg", - "id": 469 - }, - { - "name": "minecraft:skeleton_spawn_egg", - "id": 446 - }, - { - "name": "minecraft:skull", - "id": 523 - }, - { - "name": "minecraft:skull_banner_pattern", - "id": 590 - }, - { - "name": "minecraft:skull_pottery_sherd", - "id": 681 - }, - { - "name": "minecraft:slime", - "id": 165 - }, - { - "name": "minecraft:slime_ball", - "id": 390 - }, - { - "name": "minecraft:slime_spawn_egg", - "id": 447 - }, - { - "name": "minecraft:small_amethyst_bud", - "id": -332 - }, - { - "name": "minecraft:small_dripleaf_block", - "id": -336 - }, - { - "name": "minecraft:smithing_table", - "id": -202 - }, - { - "name": "minecraft:smoker", - "id": -198 - }, - { - "name": "minecraft:smooth_basalt", - "id": -377 - }, - { - "name": "minecraft:smooth_quartz_stairs", - "id": -185 - }, - { - "name": "minecraft:smooth_red_sandstone_stairs", - "id": -176 - }, - { - "name": "minecraft:smooth_sandstone_stairs", - "id": -177 - }, - { - "name": "minecraft:smooth_stone", - "id": -183 - }, - { - "name": "minecraft:sniffer_egg", - "id": -596 - }, - { - "name": "minecraft:sniffer_spawn_egg", - "id": 502 - }, - { - "name": "minecraft:snort_pottery_sherd", - "id": 682 - }, - { - "name": "minecraft:snout_armor_trim_smithing_template", - "id": 693 - }, - { - "name": "minecraft:snow", - "id": 80 - }, - { - "name": "minecraft:snow_golem_spawn_egg", - "id": 507 - }, - { - "name": "minecraft:snow_layer", - "id": 78 - }, - { - "name": "minecraft:snowball", - "id": 376 - }, - { - "name": "minecraft:soul_campfire", - "id": 629 - }, - { - "name": "minecraft:soul_fire", - "id": -237 - }, - { - "name": "minecraft:soul_lantern", - "id": -269 - }, - { - "name": "minecraft:soul_sand", - "id": 88 - }, - { - "name": "minecraft:soul_soil", - "id": -236 - }, - { - "name": "minecraft:soul_torch", - "id": -268 - }, - { - "name": "minecraft:sparkler", - "id": 607 - }, - { - "name": "minecraft:spawn_egg", - "id": 717 - }, - { - "name": "minecraft:spider_eye", - "id": 278 - }, - { - "name": "minecraft:spider_spawn_egg", - "id": 448 - }, - { - "name": "minecraft:spire_armor_trim_smithing_template", - "id": 695 - }, - { - "name": "minecraft:splash_potion", - "id": 568 - }, - { - "name": "minecraft:sponge", - "id": 19 - }, - { - "name": "minecraft:spore_blossom", - "id": -321 - }, - { - "name": "minecraft:spruce_boat", - "id": 380 - }, - { - "name": "minecraft:spruce_button", - "id": -144 - }, - { - "name": "minecraft:spruce_chest_boat", - "id": 648 - }, - { - "name": "minecraft:spruce_door", - "id": 560 - }, - { - "name": "minecraft:spruce_fence", - "id": -579 - }, - { - "name": "minecraft:spruce_fence_gate", - "id": 183 - }, - { - "name": "minecraft:spruce_hanging_sign", - "id": -501 - }, - { - "name": "minecraft:spruce_log", - "id": -569 - }, - { - "name": "minecraft:spruce_pressure_plate", - "id": -154 - }, - { - "name": "minecraft:spruce_sign", - "id": 583 - }, - { - "name": "minecraft:spruce_stairs", - "id": 134 - }, - { - "name": "minecraft:spruce_standing_sign", - "id": -181 - }, - { - "name": "minecraft:spruce_trapdoor", - "id": -149 - }, - { - "name": "minecraft:spruce_wall_sign", - "id": -182 - }, - { - "name": "minecraft:spyglass", - "id": 632 - }, - { - "name": "minecraft:squid_spawn_egg", - "id": 452 - }, - { - "name": "minecraft:stained_glass", - "id": 711 - }, - { - "name": "minecraft:stained_glass_pane", - "id": 712 - }, - { - "name": "minecraft:stained_hardened_clay", - "id": 702 - }, - { - "name": "minecraft:standing_banner", - "id": 176 - }, - { - "name": "minecraft:standing_sign", - "id": 63 - }, - { - "name": "minecraft:stick", - "id": 322 - }, - { - "name": "minecraft:sticky_piston", - "id": 29 - }, - { - "name": "minecraft:sticky_piston_arm_collision", - "id": -217 - }, - { - "name": "minecraft:stone", - "id": 1 - }, - { - "name": "minecraft:stone_axe", - "id": 317 - }, - { - "name": "minecraft:stone_block_slab", - "id": 44 - }, - { - "name": "minecraft:stone_block_slab2", - "id": 182 - }, - { - "name": "minecraft:stone_block_slab3", - "id": -162 - }, - { - "name": "minecraft:stone_block_slab4", - "id": -166 - }, - { - "name": "minecraft:stone_brick_stairs", - "id": 109 - }, - { - "name": "minecraft:stone_button", - "id": 77 - }, - { - "name": "minecraft:stone_hoe", - "id": 332 - }, - { - "name": "minecraft:stone_pickaxe", - "id": 316 - }, - { - "name": "minecraft:stone_pressure_plate", - "id": 70 - }, - { - "name": "minecraft:stone_shovel", - "id": 315 - }, - { - "name": "minecraft:stone_stairs", - "id": 67 - }, - { - "name": "minecraft:stone_sword", - "id": 314 - }, - { - "name": "minecraft:stonebrick", - "id": 98 - }, - { - "name": "minecraft:stonecutter", - "id": 245 - }, - { - "name": "minecraft:stonecutter_block", - "id": -197 - }, - { - "name": "minecraft:stray_spawn_egg", - "id": 464 - }, - { - "name": "minecraft:strider_spawn_egg", - "id": 497 - }, - { - "name": "minecraft:string", - "id": 328 - }, - { - "name": "minecraft:stripped_acacia_log", - "id": -8 - }, - { - "name": "minecraft:stripped_bamboo_block", - "id": -528 - }, - { - "name": "minecraft:stripped_birch_log", - "id": -6 - }, - { - "name": "minecraft:stripped_cherry_log", - "id": -535 - }, - { - "name": "minecraft:stripped_cherry_wood", - "id": -545 - }, - { - "name": "minecraft:stripped_crimson_hyphae", - "id": -300 - }, - { - "name": "minecraft:stripped_crimson_stem", - "id": -240 - }, - { - "name": "minecraft:stripped_dark_oak_log", - "id": -9 - }, - { - "name": "minecraft:stripped_jungle_log", - "id": -7 - }, - { - "name": "minecraft:stripped_mangrove_log", - "id": -485 - }, - { - "name": "minecraft:stripped_mangrove_wood", - "id": -498 - }, - { - "name": "minecraft:stripped_oak_log", - "id": -10 - }, - { - "name": "minecraft:stripped_spruce_log", - "id": -5 - }, - { - "name": "minecraft:stripped_warped_hyphae", - "id": -301 - }, - { - "name": "minecraft:stripped_warped_stem", - "id": -241 - }, - { - "name": "minecraft:structure_block", - "id": 252 - }, - { - "name": "minecraft:structure_void", - "id": 217 - }, - { - "name": "minecraft:sugar", - "id": 418 - }, - { - "name": "minecraft:sugar_cane", - "id": 387 - }, - { - "name": "minecraft:suspicious_gravel", - "id": -573 - }, - { - "name": "minecraft:suspicious_sand", - "id": -529 - }, - { - "name": "minecraft:suspicious_stew", - "id": 597 - }, - { - "name": "minecraft:sweet_berries", - "id": 287 - }, - { - "name": "minecraft:sweet_berry_bush", - "id": -207 - }, - { - "name": "minecraft:tadpole_bucket", - "id": 637 - }, - { - "name": "minecraft:tadpole_spawn_egg", - "id": 636 - }, - { - "name": "minecraft:tallgrass", - "id": 31 - }, - { - "name": "minecraft:target", - "id": -239 - }, - { - "name": "minecraft:tide_armor_trim_smithing_template", - "id": 692 - }, - { - "name": "minecraft:tinted_glass", - "id": -334 - }, - { - "name": "minecraft:tnt", - "id": 46 - }, - { - "name": "minecraft:tnt_minecart", - "id": 532 - }, - { - "name": "minecraft:torch", - "id": 50 - }, - { - "name": "minecraft:torchflower", - "id": -568 - }, - { - "name": "minecraft:torchflower_crop", - "id": -567 - }, - { - "name": "minecraft:torchflower_seeds", - "id": 296 - }, - { - "name": "minecraft:totem_of_undying", - "id": 575 - }, - { - "name": "minecraft:trader_llama_spawn_egg", - "id": 655 - }, - { - "name": "minecraft:trapdoor", - "id": 96 - }, - { - "name": "minecraft:trapped_chest", - "id": 146 - }, - { - "name": "minecraft:trident", - "id": 553 - }, - { - "name": "minecraft:trip_wire", - "id": 132 - }, - { - "name": "minecraft:tripwire_hook", - "id": 131 - }, - { - "name": "minecraft:tropical_fish", - "id": 266 - }, - { - "name": "minecraft:tropical_fish_bucket", - "id": 368 - }, - { - "name": "minecraft:tropical_fish_spawn_egg", - "id": 481 - }, - { - "name": "minecraft:tube_coral", - "id": -131 - }, - { - "name": "minecraft:tuff", - "id": -333 - }, - { - "name": "minecraft:turtle_egg", - "id": -159 - }, - { - "name": "minecraft:turtle_helmet", - "id": 580 - }, - { - "name": "minecraft:turtle_spawn_egg", - "id": 487 - }, - { - "name": "minecraft:twisting_vines", - "id": -287 - }, - { - "name": "minecraft:underwater_torch", - "id": 239 - }, - { - "name": "minecraft:undyed_shulker_box", - "id": 205 - }, - { - "name": "minecraft:unknown", - "id": -305 - }, - { - "name": "minecraft:unlit_redstone_torch", - "id": 75 - }, - { - "name": "minecraft:unpowered_comparator", - "id": 149 - }, - { - "name": "minecraft:unpowered_repeater", - "id": 93 - }, - { - "name": "minecraft:verdant_froglight", - "id": -470 - }, - { - "name": "minecraft:vex_armor_trim_smithing_template", - "id": 691 - }, - { - "name": "minecraft:vex_spawn_egg", - "id": 478 - }, - { - "name": "minecraft:villager_spawn_egg", - "id": 451 - }, - { - "name": "minecraft:vindicator_spawn_egg", - "id": 476 - }, - { - "name": "minecraft:vine", - "id": 106 - }, - { - "name": "minecraft:wall_banner", - "id": 177 - }, - { - "name": "minecraft:wall_sign", - "id": 68 - }, - { - "name": "minecraft:wandering_trader_spawn_egg", - "id": 494 - }, - { - "name": "minecraft:ward_armor_trim_smithing_template", - "id": 689 - }, - { - "name": "minecraft:warden_spawn_egg", - "id": 639 - }, - { - "name": "minecraft:warped_button", - "id": -261 - }, - { - "name": "minecraft:warped_door", - "id": 624 - }, - { - "name": "minecraft:warped_double_slab", - "id": -267 - }, - { - "name": "minecraft:warped_fence", - "id": -257 - }, - { - "name": "minecraft:warped_fence_gate", - "id": -259 - }, - { - "name": "minecraft:warped_fungus", - "id": -229 - }, - { - "name": "minecraft:warped_fungus_on_a_stick", - "id": 625 - }, - { - "name": "minecraft:warped_hanging_sign", - "id": -507 - }, - { - "name": "minecraft:warped_hyphae", - "id": -298 - }, - { - "name": "minecraft:warped_nylium", - "id": -233 - }, - { - "name": "minecraft:warped_planks", - "id": -243 - }, - { - "name": "minecraft:warped_pressure_plate", - "id": -263 - }, - { - "name": "minecraft:warped_roots", - "id": -224 - }, - { - "name": "minecraft:warped_sign", - "id": 622 - }, - { - "name": "minecraft:warped_slab", - "id": -265 - }, - { - "name": "minecraft:warped_stairs", - "id": -255 - }, - { - "name": "minecraft:warped_standing_sign", - "id": -251 - }, - { - "name": "minecraft:warped_stem", - "id": -226 - }, - { - "name": "minecraft:warped_trapdoor", - "id": -247 - }, - { - "name": "minecraft:warped_wall_sign", - "id": -253 - }, - { - "name": "minecraft:warped_wart_block", - "id": -227 - }, - { - "name": "minecraft:water", - "id": 9 - }, - { - "name": "minecraft:water_bucket", - "id": 364 - }, - { - "name": "minecraft:waterlily", - "id": 111 - }, - { - "name": "minecraft:waxed_copper", - "id": -344 - }, - { - "name": "minecraft:waxed_cut_copper", - "id": -351 - }, - { - "name": "minecraft:waxed_cut_copper_slab", - "id": -365 - }, - { - "name": "minecraft:waxed_cut_copper_stairs", - "id": -358 - }, - { - "name": "minecraft:waxed_double_cut_copper_slab", - "id": -372 - }, - { - "name": "minecraft:waxed_exposed_copper", - "id": -345 - }, - { - "name": "minecraft:waxed_exposed_cut_copper", - "id": -352 - }, - { - "name": "minecraft:waxed_exposed_cut_copper_slab", - "id": -366 - }, - { - "name": "minecraft:waxed_exposed_cut_copper_stairs", - "id": -359 - }, - { - "name": "minecraft:waxed_exposed_double_cut_copper_slab", - "id": -373 - }, - { - "name": "minecraft:waxed_oxidized_copper", - "id": -446 - }, - { - "name": "minecraft:waxed_oxidized_cut_copper", - "id": -447 - }, - { - "name": "minecraft:waxed_oxidized_cut_copper_slab", - "id": -449 - }, - { - "name": "minecraft:waxed_oxidized_cut_copper_stairs", - "id": -448 - }, - { - "name": "minecraft:waxed_oxidized_double_cut_copper_slab", - "id": -450 - }, - { - "name": "minecraft:waxed_weathered_copper", - "id": -346 - }, - { - "name": "minecraft:waxed_weathered_cut_copper", - "id": -353 - }, - { - "name": "minecraft:waxed_weathered_cut_copper_slab", - "id": -367 - }, - { - "name": "minecraft:waxed_weathered_cut_copper_stairs", - "id": -360 - }, - { - "name": "minecraft:waxed_weathered_double_cut_copper_slab", - "id": -374 - }, - { - "name": "minecraft:wayfinder_armor_trim_smithing_template", - "id": 697 - }, - { - "name": "minecraft:weathered_copper", - "id": -342 - }, - { - "name": "minecraft:weathered_cut_copper", - "id": -349 - }, - { - "name": "minecraft:weathered_cut_copper_slab", - "id": -363 - }, - { - "name": "minecraft:weathered_cut_copper_stairs", - "id": -356 - }, - { - "name": "minecraft:weathered_double_cut_copper_slab", - "id": -370 - }, - { - "name": "minecraft:web", - "id": 30 - }, - { - "name": "minecraft:weeping_vines", - "id": -231 - }, - { - "name": "minecraft:wheat", - "id": 336 - }, - { - "name": "minecraft:wheat_seeds", - "id": 291 - }, - { - "name": "minecraft:white_candle", - "id": -413 - }, - { - "name": "minecraft:white_candle_cake", - "id": -430 - }, - { - "name": "minecraft:white_carpet", - "id": 171 - }, - { - "name": "minecraft:white_concrete", - "id": 236 - }, - { - "name": "minecraft:white_concrete_powder", - "id": 237 - }, - { - "name": "minecraft:white_dye", - "id": 412 - }, - { - "name": "minecraft:white_glazed_terracotta", - "id": 220 - }, - { - "name": "minecraft:white_shulker_box", - "id": 218 - }, - { - "name": "minecraft:white_stained_glass", - "id": 241 - }, - { - "name": "minecraft:white_stained_glass_pane", - "id": 160 - }, - { - "name": "minecraft:white_terracotta", - "id": 159 - }, - { - "name": "minecraft:white_wool", - "id": 35 - }, - { - "name": "minecraft:wild_armor_trim_smithing_template", - "id": 688 - }, - { - "name": "minecraft:witch_spawn_egg", - "id": 454 - }, - { - "name": "minecraft:wither_rose", - "id": -216 - }, - { - "name": "minecraft:wither_skeleton_spawn_egg", - "id": 466 - }, - { - "name": "minecraft:wither_spawn_egg", - "id": 509 - }, - { - "name": "minecraft:wolf_spawn_egg", - "id": 441 - }, - { - "name": "minecraft:wood", - "id": -212 - }, - { - "name": "minecraft:wooden_axe", - "id": 313 - }, - { - "name": "minecraft:wooden_button", - "id": 143 - }, - { - "name": "minecraft:wooden_door", - "id": 361 - }, - { - "name": "minecraft:wooden_hoe", - "id": 331 - }, - { - "name": "minecraft:wooden_pickaxe", - "id": 312 - }, - { - "name": "minecraft:wooden_pressure_plate", - "id": 72 - }, - { - "name": "minecraft:wooden_shovel", - "id": 311 - }, - { - "name": "minecraft:wooden_slab", - "id": 158 - }, - { - "name": "minecraft:wooden_sword", - "id": 310 - }, - { - "name": "minecraft:wool", - "id": 703 - }, - { - "name": "minecraft:writable_book", - "id": 517 - }, - { - "name": "minecraft:written_book", - "id": 518 - }, - { - "name": "minecraft:yellow_candle", - "id": -417 - }, - { - "name": "minecraft:yellow_candle_cake", - "id": -434 - }, - { - "name": "minecraft:yellow_carpet", - "id": -600 - }, - { - "name": "minecraft:yellow_concrete", - "id": -631 - }, - { - "name": "minecraft:yellow_concrete_powder", - "id": -712 - }, - { - "name": "minecraft:yellow_dye", - "id": 408 - }, - { - "name": "minecraft:yellow_flower", - "id": 37 - }, - { - "name": "minecraft:yellow_glazed_terracotta", - "id": 224 - }, - { - "name": "minecraft:yellow_shulker_box", - "id": -616 - }, - { - "name": "minecraft:yellow_stained_glass", - "id": -676 - }, - { - "name": "minecraft:yellow_stained_glass_pane", - "id": -646 - }, - { - "name": "minecraft:yellow_terracotta", - "id": -727 - }, - { - "name": "minecraft:yellow_wool", - "id": -558 - }, - { - "name": "minecraft:zoglin_spawn_egg", - "id": 500 - }, - { - "name": "minecraft:zombie_horse_spawn_egg", - "id": 470 - }, - { - "name": "minecraft:zombie_pigman_spawn_egg", - "id": 450 - }, - { - "name": "minecraft:zombie_spawn_egg", - "id": 449 - }, - { - "name": "minecraft:zombie_villager_spawn_egg", - "id": 479 - } -] \ No newline at end of file From f0e983977a35e80ed19f7488ec58dadcb8b9ab04 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Mon, 27 Nov 2023 10:39:52 -0500 Subject: [PATCH 147/344] update mappings --- core/src/main/resources/mappings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/resources/mappings b/core/src/main/resources/mappings index 31ce17e12..ad4b7952e 160000 --- a/core/src/main/resources/mappings +++ b/core/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit 31ce17e12e991bd841270b99f461641093f42564 +Subproject commit ad4b7952e997aaff144e2ce80e9552c8db93b8f1 From c7da8fe16302eb9ebfa6a584dc45b0f0b0ba1955 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Thu, 30 Nov 2023 01:58:35 -0500 Subject: [PATCH 148/344] Better nullability annotations/handling for ItemStacks --- .../org/geysermc/geyser/inventory/GeyserItemStack.java | 7 ++++--- .../geyser/inventory/recipe/GeyserShapedRecipe.java | 3 ++- .../geyser/inventory/recipe/GeyserShapelessRecipe.java | 3 ++- .../geyser/inventory/recipe/GeyserStonecutterData.java | 3 ++- core/src/main/java/org/geysermc/geyser/item/Items.java | 2 ++ .../main/java/org/geysermc/geyser/item/type/Item.java | 3 ++- .../org/geysermc/geyser/registry/type/ItemMappings.java | 2 +- .../geyser/translator/inventory/item/ItemTranslator.java | 5 +++-- .../bedrock/BedrockBlockPickRequestTranslator.java | 2 +- .../java/inventory/JavaContainerSetSlotTranslator.java | 2 +- .../java/inventory/JavaMerchantOffersTranslator.java | 5 +++-- .../java/org/geysermc/geyser/util/InventoryUtils.java | 9 +++++---- gradle/libs.versions.toml | 2 +- 13 files changed, 29 insertions(+), 19 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java b/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java index a67516c5c..4ff8db9f0 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java @@ -34,6 +34,7 @@ import lombok.Getter; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; +import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.type.ItemMapping; @@ -42,7 +43,7 @@ import org.geysermc.geyser.translator.inventory.item.ItemTranslator; @Data public class GeyserItemStack { - public static final GeyserItemStack EMPTY = new GeyserItemStack(0, 0, null); + public static final GeyserItemStack EMPTY = new GeyserItemStack(Items.AIR_ID, 0, null); private final int javaId; private int amount; @@ -64,7 +65,7 @@ public class GeyserItemStack { this.netId = netId; } - public static @NonNull GeyserItemStack from(ItemStack itemStack) { + public static @NonNull GeyserItemStack from(@Nullable ItemStack itemStack) { return itemStack == null ? EMPTY : new GeyserItemStack(itemStack.getId(), itemStack.getAmount(), itemStack.getNbt()); } @@ -122,7 +123,7 @@ public class GeyserItemStack { } public boolean isEmpty() { - return amount <= 0 || javaId == 0; + return amount <= 0 || javaId == Items.AIR_ID; } public GeyserItemStack copy() { diff --git a/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserShapedRecipe.java b/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserShapedRecipe.java index d61945ad8..05c17cf9f 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserShapedRecipe.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserShapedRecipe.java @@ -28,8 +28,9 @@ package org.geysermc.geyser.inventory.recipe; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapedRecipeData; +import org.checkerframework.checker.nullness.qual.Nullable; -public record GeyserShapedRecipe(int width, int height, Ingredient[] ingredients, ItemStack result) implements GeyserRecipe { +public record GeyserShapedRecipe(int width, int height, Ingredient[] ingredients, @Nullable ItemStack result) implements GeyserRecipe { public GeyserShapedRecipe(ShapedRecipeData data) { this(data.getWidth(), data.getHeight(), data.getIngredients(), data.getResult()); diff --git a/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserShapelessRecipe.java b/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserShapelessRecipe.java index 6c7665bbb..e300e3ec8 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserShapelessRecipe.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserShapelessRecipe.java @@ -28,8 +28,9 @@ package org.geysermc.geyser.inventory.recipe; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapelessRecipeData; +import org.checkerframework.checker.nullness.qual.Nullable; -public record GeyserShapelessRecipe(Ingredient[] ingredients, ItemStack result) implements GeyserRecipe { +public record GeyserShapelessRecipe(Ingredient[] ingredients, @Nullable ItemStack result) implements GeyserRecipe { public GeyserShapelessRecipe(ShapelessRecipeData data) { this(data.getIngredients(), data.getResult()); diff --git a/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserStonecutterData.java b/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserStonecutterData.java index 04a772c31..22163eced 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserStonecutterData.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserStonecutterData.java @@ -26,10 +26,11 @@ package org.geysermc.geyser.inventory.recipe; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import org.checkerframework.checker.nullness.qual.Nullable; /** * @param buttonId the button that needs to be pressed for Java Edition to accept this item. * @param output the expected output of this item when cut. */ -public record GeyserStonecutterData(int buttonId, ItemStack output) { +public record GeyserStonecutterData(int buttonId, @Nullable ItemStack output) { } diff --git a/core/src/main/java/org/geysermc/geyser/item/Items.java b/core/src/main/java/org/geysermc/geyser/item/Items.java index 92c446f68..e84315fd8 100644 --- a/core/src/main/java/org/geysermc/geyser/item/Items.java +++ b/core/src/main/java/org/geysermc/geyser/item/Items.java @@ -1351,6 +1351,8 @@ public final class Items { public static final Item TRIAL_SPAWNER = register(new BlockItem("trial_spawner", builder())); public static final Item TRIAL_KEY = register(new Item("trial_key", builder())); + public static final int AIR_ID = AIR.javaId(); + private static T register(T item) { return register(item, Registries.JAVA_ITEMS.get().size()); } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/Item.java b/core/src/main/java/org/geysermc/geyser/item/type/Item.java index a7a59f6af..94bb3324e 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/Item.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/Item.java @@ -40,6 +40,7 @@ import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.translator.inventory.item.ItemTranslator; import org.geysermc.geyser.translator.text.MessageTranslator; +import org.geysermc.geyser.util.InventoryUtils; import java.util.ArrayList; import java.util.List; @@ -82,7 +83,7 @@ public class Item { /* Translation methods to Bedrock and back */ public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { - if (itemStack == null) { + if (InventoryUtils.isEmpty(itemStack)) { // Return, essentially, air return ItemData.builder(); } 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 704d5c211..40359b437 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 @@ -83,7 +83,7 @@ public class ItemMappings implements DefinitionRegistry { * @return an item entry from the given java edition identifier */ @NonNull - public ItemMapping getMapping(ItemStack itemStack) { + public ItemMapping getMapping(@NonNull ItemStack itemStack) { return this.getMapping(itemStack.getId()); } 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 856b22c9b..d1a256551 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 @@ -67,6 +67,7 @@ import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.translator.text.MessageTranslator; +import org.geysermc.geyser.util.InventoryUtils; import java.text.DecimalFormat; import java.util.*; @@ -89,7 +90,7 @@ public final class ItemTranslator { */ public static ItemStack translateToJava(ItemData data, ItemMappings mappings) { if (data == null) { - return new ItemStack(0); + return new ItemStack(Items.AIR_ID); } ItemMapping bedrockItem = mappings.getMapping(data); @@ -118,7 +119,7 @@ public final class ItemTranslator { @NonNull public static ItemData translateToBedrock(GeyserSession session, ItemStack stack) { - if (stack == null) { + if (InventoryUtils.isEmpty(stack)) { return ItemData.AIR; } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java index dd1a259fd..381adf2b7 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java @@ -56,7 +56,7 @@ public class BedrockBlockPickRequestTranslator extends PacketTranslator true") public static boolean isEmpty(@Nullable ItemStack itemStack) { - return itemStack == null || itemStack.getId() == Items.AIR.javaId() || itemStack.getAmount() <= 0; + return itemStack == null || itemStack.getId() == Items.AIR_ID || itemStack.getAmount() <= 0; } /** @@ -233,11 +235,10 @@ public class InventoryUtils { * @param itemStack the item to try to find a match for. NBT will also be accounted for. */ public static void findOrCreateItem(GeyserSession session, ItemStack itemStack) { - PlayerInventory inventory = session.getPlayerInventory(); - - if (itemStack == null || itemStack.getId() == 0) { + if (isEmpty(itemStack)) { return; } + PlayerInventory inventory = session.getPlayerInventory(); // Check hotbar for item for (int i = 36; i < 45; i++) { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 22332880a..faacaca2a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,7 +14,7 @@ protocol-connection = "3.0.0.Beta1-20231107.190703-112" raknet = "1.0.0.CR1-20230703.195238-9" blockstateupdater="1.20.50-20231106.161340-1" mcauthlib = "d9d773e" -mcprotocollib = "00bce42" +mcprotocollib = "c6ba2fa" adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" From 701e567818abc20e6ac549653284985337c0f56f Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Thu, 30 Nov 2023 02:51:48 -0500 Subject: [PATCH 149/344] Enable 1.21 experimental features --- .../org/geysermc/geyser/network/UpstreamPacketHandler.java | 3 +++ .../main/java/org/geysermc/geyser/session/GeyserSession.java | 2 ++ 2 files changed, 5 insertions(+) diff --git a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java index 358d8df59..a0b104adb 100644 --- a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java +++ b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java @@ -232,6 +232,9 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { stackPacket.getExperiments().add(new ExperimentData("data_driven_items", true)); } + // Required for experimental 1.21 features + stackPacket.getExperiments().add(new ExperimentData("updateAnnouncedLive2023", true)); + session.sendUpstreamPacket(stackPacket); break; diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 265a978ff..28ad5887c 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -1544,6 +1544,8 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { startGamePacket.getExperiments().add(new ExperimentData("upcoming_creator_features", true)); // Needed for certain molang queries used in blocks and items startGamePacket.getExperiments().add(new ExperimentData("experimental_molang_features", true)); + // Required for experimental 1.21 features + startGamePacket.getExperiments().add(new ExperimentData("updateAnnouncedLive2023", true)); startGamePacket.setVanillaVersion("*"); startGamePacket.setInventoriesServerAuthoritative(true); From 9b53f2efd140846ccabba075d9785d60a26c10be Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Thu, 30 Nov 2023 02:53:05 -0500 Subject: [PATCH 150/344] Update 1.20.50 creative items to include experimental items also remove the old unused ones --- .../bedrock/creative_items.1_20_0.json | 6580 ----------------- .../bedrock/creative_items.1_20_10.json | 5793 --------------- .../bedrock/creative_items.1_20_30.json | 5787 --------------- .../bedrock/creative_items.1_20_50.json | 208 + 4 files changed, 208 insertions(+), 18160 deletions(-) delete mode 100644 core/src/main/resources/bedrock/creative_items.1_20_0.json delete mode 100644 core/src/main/resources/bedrock/creative_items.1_20_10.json delete mode 100644 core/src/main/resources/bedrock/creative_items.1_20_30.json diff --git a/core/src/main/resources/bedrock/creative_items.1_20_0.json b/core/src/main/resources/bedrock/creative_items.1_20_0.json deleted file mode 100644 index 0c37c88a0..000000000 --- a/core/src/main/resources/bedrock/creative_items.1_20_0.json +++ /dev/null @@ -1,6580 +0,0 @@ -{ - "items": [ - { - "id": "minecraft:planks", - "blockRuntimeId": 10437 - }, - { - "id": "minecraft:planks", - "blockRuntimeId": 10438 - }, - { - "id": "minecraft:planks", - "blockRuntimeId": 10439 - }, - { - "id": "minecraft:planks", - "blockRuntimeId": 10440 - }, - { - "id": "minecraft:planks", - "blockRuntimeId": 10441 - }, - { - "id": "minecraft:planks", - "blockRuntimeId": 10442 - }, - { - "id": "minecraft:mangrove_planks", - "blockRuntimeId": 2068 - }, - { - "id": "minecraft:cherry_planks", - "blockRuntimeId": 12582 - }, - { - "id": "minecraft:bamboo_planks", - "blockRuntimeId": 8786 - }, - { - "id": "minecraft:bamboo_mosaic", - "blockRuntimeId": 13109 - }, - { - "id": "minecraft:crimson_planks", - "blockRuntimeId": 7977 - }, - { - "id": "minecraft:warped_planks", - "blockRuntimeId": 2039 - }, - { - "id": "minecraft:cobblestone_wall", - "blockRuntimeId": 2296 - }, - { - "id": "minecraft:cobblestone_wall", - "blockRuntimeId": 2297 - }, - { - "id": "minecraft:cobblestone_wall", - "blockRuntimeId": 2298 - }, - { - "id": "minecraft:cobblestone_wall", - "blockRuntimeId": 2299 - }, - { - "id": "minecraft:cobblestone_wall", - "blockRuntimeId": 2300 - }, - { - "id": "minecraft:cobblestone_wall", - "blockRuntimeId": 2301 - }, - { - "id": "minecraft:cobblestone_wall", - "blockRuntimeId": 2308 - }, - { - "id": "minecraft:cobblestone_wall", - "blockRuntimeId": 2303 - }, - { - "id": "minecraft:cobblestone_wall", - "blockRuntimeId": 2304 - }, - { - "id": "minecraft:cobblestone_wall", - "blockRuntimeId": 2302 - }, - { - "id": "minecraft:cobblestone_wall", - "blockRuntimeId": 2305 - }, - { - "id": "minecraft:cobblestone_wall", - "blockRuntimeId": 2309 - }, - { - "id": "minecraft:cobblestone_wall", - "blockRuntimeId": 2306 - }, - { - "id": "minecraft:cobblestone_wall", - "blockRuntimeId": 2307 - }, - { - "id": "minecraft:blackstone_wall", - "blockRuntimeId": 6189 - }, - { - "id": "minecraft:polished_blackstone_wall", - "blockRuntimeId": 11115 - }, - { - "id": "minecraft:polished_blackstone_brick_wall", - "blockRuntimeId": 2077 - }, - { - "id": "minecraft:cobbled_deepslate_wall", - "blockRuntimeId": 12915 - }, - { - "id": "minecraft:deepslate_tile_wall", - "blockRuntimeId": 8217 - }, - { - "id": "minecraft:polished_deepslate_wall", - "blockRuntimeId": 12647 - }, - { - "id": "minecraft:deepslate_brick_wall", - "blockRuntimeId": 1154 - }, - { - "id": "minecraft:mud_brick_wall", - "blockRuntimeId": 1833 - }, - { - "id": "minecraft:oak_fence", - "blockRuntimeId": 8915 - }, - { - "id": "minecraft:spruce_fence", - "blockRuntimeId": 1116 - }, - { - "id": "minecraft:birch_fence", - "blockRuntimeId": 12910 - }, - { - "id": "minecraft:jungle_fence", - "blockRuntimeId": 1109 - }, - { - "id": "minecraft:acacia_fence", - "blockRuntimeId": 12913 - }, - { - "id": "minecraft:dark_oak_fence", - "blockRuntimeId": 11485 - }, - { - "id": "minecraft:mangrove_fence", - "blockRuntimeId": 11031 - }, - { - "id": "minecraft:cherry_fence", - "blockRuntimeId": 2067 - }, - { - "id": "minecraft:bamboo_fence", - "blockRuntimeId": 1337 - }, - { - "id": "minecraft:nether_brick_fence", - "blockRuntimeId": 6556 - }, - { - "id": "minecraft:crimson_fence", - "blockRuntimeId": 12826 - }, - { - "id": "minecraft:warped_fence", - "blockRuntimeId": 9420 - }, - { - "id": "minecraft:fence_gate", - "blockRuntimeId": 79 - }, - { - "id": "minecraft:spruce_fence_gate", - "blockRuntimeId": 10982 - }, - { - "id": "minecraft:birch_fence_gate", - "blockRuntimeId": 5658 - }, - { - "id": "minecraft:jungle_fence_gate", - "blockRuntimeId": 8528 - }, - { - "id": "minecraft:acacia_fence_gate", - "blockRuntimeId": 12406 - }, - { - "id": "minecraft:dark_oak_fence_gate", - "blockRuntimeId": 6432 - }, - { - "id": "minecraft:mangrove_fence_gate", - "blockRuntimeId": 6943 - }, - { - "id": "minecraft:cherry_fence_gate", - "blockRuntimeId": 13086 - }, - { - "id": "minecraft:bamboo_fence_gate", - "blockRuntimeId": 8192 - }, - { - "id": "minecraft:crimson_fence_gate", - "blockRuntimeId": 7395 - }, - { - "id": "minecraft:warped_fence_gate", - "blockRuntimeId": 8563 - }, - { - "id": "minecraft:normal_stone_stairs", - "blockRuntimeId": 1338 - }, - { - "id": "minecraft:stone_stairs", - "blockRuntimeId": 5584 - }, - { - "id": "minecraft:mossy_cobblestone_stairs", - "blockRuntimeId": 6351 - }, - { - "id": "minecraft:oak_stairs", - "blockRuntimeId": 702 - }, - { - "id": "minecraft:spruce_stairs", - "blockRuntimeId": 132 - }, - { - "id": "minecraft:birch_stairs", - "blockRuntimeId": 11403 - }, - { - "id": "minecraft:jungle_stairs", - "blockRuntimeId": 11364 - }, - { - "id": "minecraft:acacia_stairs", - "blockRuntimeId": 10582 - }, - { - "id": "minecraft:dark_oak_stairs", - "blockRuntimeId": 8209 - }, - { - "id": "minecraft:mangrove_stairs", - "blockRuntimeId": 6901 - }, - { - "id": "minecraft:cherry_stairs", - "blockRuntimeId": 11534 - }, - { - "id": "minecraft:bamboo_stairs", - "blockRuntimeId": 1819 - }, - { - "id": "minecraft:bamboo_mosaic_stairs", - "blockRuntimeId": 10590 - }, - { - "id": "minecraft:stone_brick_stairs", - "blockRuntimeId": 2051 - }, - { - "id": "minecraft:mossy_stone_brick_stairs", - "blockRuntimeId": 9850 - }, - { - "id": "minecraft:sandstone_stairs", - "blockRuntimeId": 5458 - }, - { - "id": "minecraft:smooth_sandstone_stairs", - "blockRuntimeId": 5503 - }, - { - "id": "minecraft:red_sandstone_stairs", - "blockRuntimeId": 8513 - }, - { - "id": "minecraft:smooth_red_sandstone_stairs", - "blockRuntimeId": 8711 - }, - { - "id": "minecraft:granite_stairs", - "blockRuntimeId": 5024 - }, - { - "id": "minecraft:polished_granite_stairs", - "blockRuntimeId": 6409 - }, - { - "id": "minecraft:diorite_stairs", - "blockRuntimeId": 6694 - }, - { - "id": "minecraft:polished_diorite_stairs", - "blockRuntimeId": 11100 - }, - { - "id": "minecraft:andesite_stairs", - "blockRuntimeId": 8470 - }, - { - "id": "minecraft:polished_andesite_stairs", - "blockRuntimeId": 11428 - }, - { - "id": "minecraft:brick_stairs", - "blockRuntimeId": 10928 - }, - { - "id": "minecraft:nether_brick_stairs", - "blockRuntimeId": 109 - }, - { - "id": "minecraft:red_nether_brick_stairs", - "blockRuntimeId": 11000 - }, - { - "id": "minecraft:end_brick_stairs", - "blockRuntimeId": 10776 - }, - { - "id": "minecraft:quartz_stairs", - "blockRuntimeId": 7509 - }, - { - "id": "minecraft:smooth_quartz_stairs", - "blockRuntimeId": 12521 - }, - { - "id": "minecraft:purpur_stairs", - "blockRuntimeId": 12584 - }, - { - "id": "minecraft:prismarine_stairs", - "blockRuntimeId": 12087 - }, - { - "id": "minecraft:dark_prismarine_stairs", - "blockRuntimeId": 12250 - }, - { - "id": "minecraft:prismarine_bricks_stairs", - "blockRuntimeId": 612 - }, - { - "id": "minecraft:crimson_stairs", - "blockRuntimeId": 10674 - }, - { - "id": "minecraft:warped_stairs", - "blockRuntimeId": 5594 - }, - { - "id": "minecraft:blackstone_stairs", - "blockRuntimeId": 11419 - }, - { - "id": "minecraft:polished_blackstone_stairs", - "blockRuntimeId": 6596 - }, - { - "id": "minecraft:polished_blackstone_brick_stairs", - "blockRuntimeId": 6783 - }, - { - "id": "minecraft:cut_copper_stairs", - "blockRuntimeId": 6910 - }, - { - "id": "minecraft:exposed_cut_copper_stairs", - "blockRuntimeId": 6893 - }, - { - "id": "minecraft:weathered_cut_copper_stairs", - "blockRuntimeId": 6604 - }, - { - "id": "minecraft:oxidized_cut_copper_stairs", - "blockRuntimeId": 1073 - }, - { - "id": "minecraft:waxed_cut_copper_stairs", - "blockRuntimeId": 1118 - }, - { - "id": "minecraft:waxed_exposed_cut_copper_stairs", - "blockRuntimeId": 6161 - }, - { - "id": "minecraft:waxed_weathered_cut_copper_stairs", - "blockRuntimeId": 10549 - }, - { - "id": "minecraft:waxed_oxidized_cut_copper_stairs", - "blockRuntimeId": 9395 - }, - { - "id": "minecraft:cobbled_deepslate_stairs", - "blockRuntimeId": 552 - }, - { - "id": "minecraft:deepslate_tile_stairs", - "blockRuntimeId": 7387 - }, - { - "id": "minecraft:polished_deepslate_stairs", - "blockRuntimeId": 1014 - }, - { - "id": "minecraft:deepslate_brick_stairs", - "blockRuntimeId": 12242 - }, - { - "id": "minecraft:mud_brick_stairs", - "blockRuntimeId": 8687 - }, - { - "id": "minecraft:wooden_door", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:spruce_door", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:birch_door", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:jungle_door", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:acacia_door", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:dark_oak_door", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:mangrove_door", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cherry_door", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bamboo_door", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:iron_door", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:crimson_door", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:warped_door", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:trapdoor", - "blockRuntimeId": 640 - }, - { - "id": "minecraft:spruce_trapdoor", - "blockRuntimeId": 10950 - }, - { - "id": "minecraft:birch_trapdoor", - "blockRuntimeId": 11048 - }, - { - "id": "minecraft:jungle_trapdoor", - "blockRuntimeId": 8544 - }, - { - "id": "minecraft:acacia_trapdoor", - "blockRuntimeId": 8754 - }, - { - "id": "minecraft:dark_oak_trapdoor", - "blockRuntimeId": 12322 - }, - { - "id": "minecraft:mangrove_trapdoor", - "blockRuntimeId": 6791 - }, - { - "id": "minecraft:cherry_trapdoor", - "blockRuntimeId": 2013 - }, - { - "id": "minecraft:bamboo_trapdoor", - "blockRuntimeId": 8409 - }, - { - "id": "minecraft:iron_trapdoor", - "blockRuntimeId": 1041 - }, - { - "id": "minecraft:crimson_trapdoor", - "blockRuntimeId": 6635 - }, - { - "id": "minecraft:warped_trapdoor", - "blockRuntimeId": 7475 - }, - { - "id": "minecraft:iron_bars", - "blockRuntimeId": 7543 - }, - { - "id": "minecraft:glass", - "blockRuntimeId": 10546 - }, - { - "id": "minecraft:stained_glass", - "blockRuntimeId": 2239 - }, - { - "id": "minecraft:stained_glass", - "blockRuntimeId": 2247 - }, - { - "id": "minecraft:stained_glass", - "blockRuntimeId": 2246 - }, - { - "id": "minecraft:stained_glass", - "blockRuntimeId": 2254 - }, - { - "id": "minecraft:stained_glass", - "blockRuntimeId": 2251 - }, - { - "id": "minecraft:stained_glass", - "blockRuntimeId": 2253 - }, - { - "id": "minecraft:stained_glass", - "blockRuntimeId": 2240 - }, - { - "id": "minecraft:stained_glass", - "blockRuntimeId": 2243 - }, - { - "id": "minecraft:stained_glass", - "blockRuntimeId": 2244 - }, - { - "id": "minecraft:stained_glass", - "blockRuntimeId": 2252 - }, - { - "id": "minecraft:stained_glass", - "blockRuntimeId": 2248 - }, - { - "id": "minecraft:stained_glass", - "blockRuntimeId": 2242 - }, - { - "id": "minecraft:stained_glass", - "blockRuntimeId": 2250 - }, - { - "id": "minecraft:stained_glass", - "blockRuntimeId": 2249 - }, - { - "id": "minecraft:stained_glass", - "blockRuntimeId": 2241 - }, - { - "id": "minecraft:stained_glass", - "blockRuntimeId": 2245 - }, - { - "id": "minecraft:tinted_glass", - "blockRuntimeId": 9944 - }, - { - "id": "minecraft:glass_pane", - "blockRuntimeId": 8379 - }, - { - "id": "minecraft:stained_glass_pane", - "blockRuntimeId": 7979 - }, - { - "id": "minecraft:stained_glass_pane", - "blockRuntimeId": 7987 - }, - { - "id": "minecraft:stained_glass_pane", - "blockRuntimeId": 7986 - }, - { - "id": "minecraft:stained_glass_pane", - "blockRuntimeId": 7994 - }, - { - "id": "minecraft:stained_glass_pane", - "blockRuntimeId": 7991 - }, - { - "id": "minecraft:stained_glass_pane", - "blockRuntimeId": 7993 - }, - { - "id": "minecraft:stained_glass_pane", - "blockRuntimeId": 7980 - }, - { - "id": "minecraft:stained_glass_pane", - "blockRuntimeId": 7983 - }, - { - "id": "minecraft:stained_glass_pane", - "blockRuntimeId": 7984 - }, - { - "id": "minecraft:stained_glass_pane", - "blockRuntimeId": 7992 - }, - { - "id": "minecraft:stained_glass_pane", - "blockRuntimeId": 7988 - }, - { - "id": "minecraft:stained_glass_pane", - "blockRuntimeId": 7982 - }, - { - "id": "minecraft:stained_glass_pane", - "blockRuntimeId": 7990 - }, - { - "id": "minecraft:stained_glass_pane", - "blockRuntimeId": 7989 - }, - { - "id": "minecraft:stained_glass_pane", - "blockRuntimeId": 7981 - }, - { - "id": "minecraft:stained_glass_pane", - "blockRuntimeId": 7985 - }, - { - "id": "minecraft:ladder", - "blockRuntimeId": 13114 - }, - { - "id": "minecraft:scaffolding", - "blockRuntimeId": 5442 - }, - { - "id": "minecraft:stone_block_slab", - "blockRuntimeId": 6534 - }, - { - "id": "minecraft:stone_block_slab4", - "blockRuntimeId": 8989 - }, - { - "id": "minecraft:stone_block_slab", - "blockRuntimeId": 6537 - }, - { - "id": "minecraft:stone_block_slab2", - "blockRuntimeId": 8960 - }, - { - "id": "minecraft:wooden_slab", - "blockRuntimeId": 8432 - }, - { - "id": "minecraft:wooden_slab", - "blockRuntimeId": 8433 - }, - { - "id": "minecraft:wooden_slab", - "blockRuntimeId": 8434 - }, - { - "id": "minecraft:wooden_slab", - "blockRuntimeId": 8435 - }, - { - "id": "minecraft:wooden_slab", - "blockRuntimeId": 8436 - }, - { - "id": "minecraft:wooden_slab", - "blockRuntimeId": 8437 - }, - { - "id": "minecraft:mangrove_slab", - "blockRuntimeId": 2255 - }, - { - "id": "minecraft:cherry_slab", - "blockRuntimeId": 10614 - }, - { - "id": "minecraft:bamboo_slab", - "blockRuntimeId": 10926 - }, - { - "id": "minecraft:bamboo_mosaic_slab", - "blockRuntimeId": 4572 - }, - { - "id": "minecraft:stone_block_slab", - "blockRuntimeId": 6539 - }, - { - "id": "minecraft:stone_block_slab4", - "blockRuntimeId": 8987 - }, - { - "id": "minecraft:stone_block_slab", - "blockRuntimeId": 6535 - }, - { - "id": "minecraft:stone_block_slab4", - "blockRuntimeId": 8990 - }, - { - "id": "minecraft:stone_block_slab2", - "blockRuntimeId": 8961 - }, - { - "id": "minecraft:stone_block_slab2", - "blockRuntimeId": 8955 - }, - { - "id": "minecraft:stone_block_slab4", - "blockRuntimeId": 8991 - }, - { - "id": "minecraft:stone_block_slab3", - "blockRuntimeId": 8972 - }, - { - "id": "minecraft:stone_block_slab3", - "blockRuntimeId": 8977 - }, - { - "id": "minecraft:stone_block_slab3", - "blockRuntimeId": 8978 - }, - { - "id": "minecraft:stone_block_slab3", - "blockRuntimeId": 8975 - }, - { - "id": "minecraft:stone_block_slab3", - "blockRuntimeId": 8976 - }, - { - "id": "minecraft:stone_block_slab3", - "blockRuntimeId": 8974 - }, - { - "id": "minecraft:stone_block_slab3", - "blockRuntimeId": 8973 - }, - { - "id": "minecraft:stone_block_slab", - "blockRuntimeId": 6538 - }, - { - "id": "minecraft:stone_block_slab", - "blockRuntimeId": 6541 - }, - { - "id": "minecraft:stone_block_slab2", - "blockRuntimeId": 8962 - }, - { - "id": "minecraft:stone_block_slab3", - "blockRuntimeId": 8971 - }, - { - "id": "minecraft:stone_block_slab", - "blockRuntimeId": 6540 - }, - { - "id": "minecraft:stone_block_slab4", - "blockRuntimeId": 8988 - }, - { - "id": "minecraft:stone_block_slab2", - "blockRuntimeId": 8956 - }, - { - "id": "minecraft:stone_block_slab2", - "blockRuntimeId": 8957 - }, - { - "id": "minecraft:stone_block_slab2", - "blockRuntimeId": 8958 - }, - { - "id": "minecraft:stone_block_slab2", - "blockRuntimeId": 8959 - }, - { - "id": "minecraft:crimson_slab", - "blockRuntimeId": 9867 - }, - { - "id": "minecraft:warped_slab", - "blockRuntimeId": 10890 - }, - { - "id": "minecraft:blackstone_slab", - "blockRuntimeId": 2029 - }, - { - "id": "minecraft:polished_blackstone_slab", - "blockRuntimeId": 10372 - }, - { - "id": "minecraft:polished_blackstone_brick_slab", - "blockRuntimeId": 6453 - }, - { - "id": "minecraft:cut_copper_slab", - "blockRuntimeId": 8381 - }, - { - "id": "minecraft:exposed_cut_copper_slab", - "blockRuntimeId": 10998 - }, - { - "id": "minecraft:weathered_cut_copper_slab", - "blockRuntimeId": 10418 - }, - { - "id": "minecraft:oxidized_cut_copper_slab", - "blockRuntimeId": 8444 - }, - { - "id": "minecraft:waxed_cut_copper_slab", - "blockRuntimeId": 12645 - }, - { - "id": "minecraft:waxed_exposed_cut_copper_slab", - "blockRuntimeId": 660 - }, - { - "id": "minecraft:waxed_weathered_cut_copper_slab", - "blockRuntimeId": 10943 - }, - { - "id": "minecraft:waxed_oxidized_cut_copper_slab", - "blockRuntimeId": 1803 - }, - { - "id": "minecraft:cobbled_deepslate_slab", - "blockRuntimeId": 12135 - }, - { - "id": "minecraft:polished_deepslate_slab", - "blockRuntimeId": 720 - }, - { - "id": "minecraft:deepslate_tile_slab", - "blockRuntimeId": 6557 - }, - { - "id": "minecraft:deepslate_brick_slab", - "blockRuntimeId": 5592 - }, - { - "id": "minecraft:mud_brick_slab", - "blockRuntimeId": 6169 - }, - { - "id": "minecraft:brick_block", - "blockRuntimeId": 7507 - }, - { - "id": "minecraft:chiseled_nether_bricks", - "blockRuntimeId": 12067 - }, - { - "id": "minecraft:cracked_nether_bricks", - "blockRuntimeId": 6858 - }, - { - "id": "minecraft:quartz_bricks", - "blockRuntimeId": 10745 - }, - { - "id": "minecraft:stonebrick", - "blockRuntimeId": 10945 - }, - { - "id": "minecraft:stonebrick", - "blockRuntimeId": 10946 - }, - { - "id": "minecraft:stonebrick", - "blockRuntimeId": 10947 - }, - { - "id": "minecraft:stonebrick", - "blockRuntimeId": 10948 - }, - { - "id": "minecraft:end_bricks", - "blockRuntimeId": 713 - }, - { - "id": "minecraft:prismarine", - "blockRuntimeId": 10469 - }, - { - "id": "minecraft:polished_blackstone_bricks", - "blockRuntimeId": 7414 - }, - { - "id": "minecraft:cracked_polished_blackstone_bricks", - "blockRuntimeId": 12016 - }, - { - "id": "minecraft:gilded_blackstone", - "blockRuntimeId": 6892 - }, - { - "id": "minecraft:chiseled_polished_blackstone", - "blockRuntimeId": 8208 - }, - { - "id": "minecraft:deepslate_tiles", - "blockRuntimeId": 6887 - }, - { - "id": "minecraft:cracked_deepslate_tiles", - "blockRuntimeId": 6419 - }, - { - "id": "minecraft:deepslate_bricks", - "blockRuntimeId": 8628 - }, - { - "id": "minecraft:cracked_deepslate_bricks", - "blockRuntimeId": 8527 - }, - { - "id": "minecraft:chiseled_deepslate", - "blockRuntimeId": 8380 - }, - { - "id": "minecraft:cobblestone", - "blockRuntimeId": 5489 - }, - { - "id": "minecraft:mossy_cobblestone", - "blockRuntimeId": 663 - }, - { - "id": "minecraft:cobbled_deepslate", - "blockRuntimeId": 11068 - }, - { - "id": "minecraft:smooth_stone", - "blockRuntimeId": 6888 - }, - { - "id": "minecraft:sandstone", - "blockRuntimeId": 5529 - }, - { - "id": "minecraft:sandstone", - "blockRuntimeId": 5530 - }, - { - "id": "minecraft:sandstone", - "blockRuntimeId": 5531 - }, - { - "id": "minecraft:sandstone", - "blockRuntimeId": 5532 - }, - { - "id": "minecraft:red_sandstone", - "blockRuntimeId": 10978 - }, - { - "id": "minecraft:red_sandstone", - "blockRuntimeId": 10979 - }, - { - "id": "minecraft:red_sandstone", - "blockRuntimeId": 10980 - }, - { - "id": "minecraft:red_sandstone", - "blockRuntimeId": 10981 - }, - { - "id": "minecraft:coal_block", - "blockRuntimeId": 8561 - }, - { - "id": "minecraft:dried_kelp_block", - "blockRuntimeId": 12809 - }, - { - "id": "minecraft:gold_block", - "blockRuntimeId": 755 - }, - { - "id": "minecraft:iron_block", - "blockRuntimeId": 13113 - }, - { - "id": "minecraft:copper_block", - "blockRuntimeId": 7385 - }, - { - "id": "minecraft:exposed_copper", - "blockRuntimeId": 1318 - }, - { - "id": "minecraft:weathered_copper", - "blockRuntimeId": 13079 - }, - { - "id": "minecraft:oxidized_copper", - "blockRuntimeId": 5424 - }, - { - "id": "minecraft:waxed_copper", - "blockRuntimeId": 12561 - }, - { - "id": "minecraft:waxed_exposed_copper", - "blockRuntimeId": 1789 - }, - { - "id": "minecraft:waxed_weathered_copper", - "blockRuntimeId": 1802 - }, - { - "id": "minecraft:waxed_oxidized_copper", - "blockRuntimeId": 12362 - }, - { - "id": "minecraft:cut_copper", - "blockRuntimeId": 7423 - }, - { - "id": "minecraft:exposed_cut_copper", - "blockRuntimeId": 10548 - }, - { - "id": "minecraft:weathered_cut_copper", - "blockRuntimeId": 11999 - }, - { - "id": "minecraft:oxidized_cut_copper", - "blockRuntimeId": 8642 - }, - { - "id": "minecraft:waxed_cut_copper", - "blockRuntimeId": 12118 - }, - { - "id": "minecraft:waxed_exposed_cut_copper", - "blockRuntimeId": 5690 - }, - { - "id": "minecraft:waxed_weathered_cut_copper", - "blockRuntimeId": 7978 - }, - { - "id": "minecraft:waxed_oxidized_cut_copper", - "blockRuntimeId": 620 - }, - { - "id": "minecraft:emerald_block", - "blockRuntimeId": 2265 - }, - { - "id": "minecraft:diamond_block", - "blockRuntimeId": 701 - }, - { - "id": "minecraft:lapis_block", - "blockRuntimeId": 6550 - }, - { - "id": "minecraft:raw_iron_block", - "blockRuntimeId": 13110 - }, - { - "id": "minecraft:raw_copper_block", - "blockRuntimeId": 8431 - }, - { - "id": "minecraft:raw_gold_block", - "blockRuntimeId": 1083 - }, - { - "id": "minecraft:quartz_block", - "blockRuntimeId": 5572 - }, - { - "id": "minecraft:quartz_block", - "blockRuntimeId": 5574 - }, - { - "id": "minecraft:quartz_block", - "blockRuntimeId": 5573 - }, - { - "id": "minecraft:quartz_block", - "blockRuntimeId": 5575 - }, - { - "id": "minecraft:prismarine", - "blockRuntimeId": 10467 - }, - { - "id": "minecraft:prismarine", - "blockRuntimeId": 10468 - }, - { - "id": "minecraft:slime", - "blockRuntimeId": 6494 - }, - { - "id": "minecraft:honey_block", - "blockRuntimeId": 1995 - }, - { - "id": "minecraft:honeycomb_block", - "blockRuntimeId": 6782 - }, - { - "id": "minecraft:hay_block", - "blockRuntimeId": 1790 - }, - { - "id": "minecraft:bone_block", - "blockRuntimeId": 6495 - }, - { - "id": "minecraft:nether_brick", - "blockRuntimeId": 12097 - }, - { - "id": "minecraft:red_nether_brick", - "blockRuntimeId": 551 - }, - { - "id": "minecraft:netherite_block", - "blockRuntimeId": 5655 - }, - { - "id": "minecraft:lodestone", - "blockRuntimeId": 13108 - }, - { - "id": "minecraft:white_wool", - "blockRuntimeId": 8562 - }, - { - "id": "minecraft:light_gray_wool", - "blockRuntimeId": 12885 - }, - { - "id": "minecraft:gray_wool", - "blockRuntimeId": 632 - }, - { - "id": "minecraft:black_wool", - "blockRuntimeId": 1084 - }, - { - "id": "minecraft:brown_wool", - "blockRuntimeId": 684 - }, - { - "id": "minecraft:red_wool", - "blockRuntimeId": 119 - }, - { - "id": "minecraft:orange_wool", - "blockRuntimeId": 1771 - }, - { - "id": "minecraft:yellow_wool", - "blockRuntimeId": 542 - }, - { - "id": "minecraft:lime_wool", - "blockRuntimeId": 10361 - }, - { - "id": "minecraft:green_wool", - "blockRuntimeId": 5603 - }, - { - "id": "minecraft:cyan_wool", - "blockRuntimeId": 8506 - }, - { - "id": "minecraft:light_blue_wool", - "blockRuntimeId": 11483 - }, - { - "id": "minecraft:blue_wool", - "blockRuntimeId": 8643 - }, - { - "id": "minecraft:purple_wool", - "blockRuntimeId": 13112 - }, - { - "id": "minecraft:magenta_wool", - "blockRuntimeId": 2070 - }, - { - "id": "minecraft:pink_wool", - "blockRuntimeId": 5656 - }, - { - "id": "minecraft:white_carpet", - "blockRuntimeId": 12095 - }, - { - "id": "minecraft:light_gray_carpet", - "blockRuntimeId": 13111 - }, - { - "id": "minecraft:gray_carpet", - "blockRuntimeId": 633 - }, - { - "id": "minecraft:black_carpet", - "blockRuntimeId": 10399 - }, - { - "id": "minecraft:brown_carpet", - "blockRuntimeId": 2046 - }, - { - "id": "minecraft:red_carpet", - "blockRuntimeId": 12240 - }, - { - "id": "minecraft:orange_carpet", - "blockRuntimeId": 11474 - }, - { - "id": "minecraft:yellow_carpet", - "blockRuntimeId": 9881 - }, - { - "id": "minecraft:lime_carpet", - "blockRuntimeId": 11109 - }, - { - "id": "minecraft:green_carpet", - "blockRuntimeId": 5604 - }, - { - "id": "minecraft:cyan_carpet", - "blockRuntimeId": 5491 - }, - { - "id": "minecraft:light_blue_carpet", - "blockRuntimeId": 7544 - }, - { - "id": "minecraft:blue_carpet", - "blockRuntimeId": 584 - }, - { - "id": "minecraft:purple_carpet", - "blockRuntimeId": 12578 - }, - { - "id": "minecraft:magenta_carpet", - "blockRuntimeId": 667 - }, - { - "id": "minecraft:pink_carpet", - "blockRuntimeId": 12520 - }, - { - "id": "minecraft:concrete_powder", - "blockRuntimeId": 10657 - }, - { - "id": "minecraft:concrete_powder", - "blockRuntimeId": 10665 - }, - { - "id": "minecraft:concrete_powder", - "blockRuntimeId": 10664 - }, - { - "id": "minecraft:concrete_powder", - "blockRuntimeId": 10672 - }, - { - "id": "minecraft:concrete_powder", - "blockRuntimeId": 10669 - }, - { - "id": "minecraft:concrete_powder", - "blockRuntimeId": 10671 - }, - { - "id": "minecraft:concrete_powder", - "blockRuntimeId": 10658 - }, - { - "id": "minecraft:concrete_powder", - "blockRuntimeId": 10661 - }, - { - "id": "minecraft:concrete_powder", - "blockRuntimeId": 10662 - }, - { - "id": "minecraft:concrete_powder", - "blockRuntimeId": 10670 - }, - { - "id": "minecraft:concrete_powder", - "blockRuntimeId": 10666 - }, - { - "id": "minecraft:concrete_powder", - "blockRuntimeId": 10660 - }, - { - "id": "minecraft:concrete_powder", - "blockRuntimeId": 10668 - }, - { - "id": "minecraft:concrete_powder", - "blockRuntimeId": 10667 - }, - { - "id": "minecraft:concrete_powder", - "blockRuntimeId": 10659 - }, - { - "id": "minecraft:concrete_powder", - "blockRuntimeId": 10663 - }, - { - "id": "minecraft:concrete", - "blockRuntimeId": 1750 - }, - { - "id": "minecraft:concrete", - "blockRuntimeId": 1758 - }, - { - "id": "minecraft:concrete", - "blockRuntimeId": 1757 - }, - { - "id": "minecraft:concrete", - "blockRuntimeId": 1765 - }, - { - "id": "minecraft:concrete", - "blockRuntimeId": 1762 - }, - { - "id": "minecraft:concrete", - "blockRuntimeId": 1764 - }, - { - "id": "minecraft:concrete", - "blockRuntimeId": 1751 - }, - { - "id": "minecraft:concrete", - "blockRuntimeId": 1754 - }, - { - "id": "minecraft:concrete", - "blockRuntimeId": 1755 - }, - { - "id": "minecraft:concrete", - "blockRuntimeId": 1763 - }, - { - "id": "minecraft:concrete", - "blockRuntimeId": 1759 - }, - { - "id": "minecraft:concrete", - "blockRuntimeId": 1753 - }, - { - "id": "minecraft:concrete", - "blockRuntimeId": 1761 - }, - { - "id": "minecraft:concrete", - "blockRuntimeId": 1760 - }, - { - "id": "minecraft:concrete", - "blockRuntimeId": 1752 - }, - { - "id": "minecraft:concrete", - "blockRuntimeId": 1756 - }, - { - "id": "minecraft:clay", - "blockRuntimeId": 11533 - }, - { - "id": "minecraft:hardened_clay", - "blockRuntimeId": 1346 - }, - { - "id": "minecraft:stained_hardened_clay", - "blockRuntimeId": 10558 - }, - { - "id": "minecraft:stained_hardened_clay", - "blockRuntimeId": 10566 - }, - { - "id": "minecraft:stained_hardened_clay", - "blockRuntimeId": 10565 - }, - { - "id": "minecraft:stained_hardened_clay", - "blockRuntimeId": 10573 - }, - { - "id": "minecraft:stained_hardened_clay", - "blockRuntimeId": 10570 - }, - { - "id": "minecraft:stained_hardened_clay", - "blockRuntimeId": 10572 - }, - { - "id": "minecraft:stained_hardened_clay", - "blockRuntimeId": 10559 - }, - { - "id": "minecraft:stained_hardened_clay", - "blockRuntimeId": 10562 - }, - { - "id": "minecraft:stained_hardened_clay", - "blockRuntimeId": 10563 - }, - { - "id": "minecraft:stained_hardened_clay", - "blockRuntimeId": 10571 - }, - { - "id": "minecraft:stained_hardened_clay", - "blockRuntimeId": 10567 - }, - { - "id": "minecraft:stained_hardened_clay", - "blockRuntimeId": 10561 - }, - { - "id": "minecraft:stained_hardened_clay", - "blockRuntimeId": 10569 - }, - { - "id": "minecraft:stained_hardened_clay", - "blockRuntimeId": 10568 - }, - { - "id": "minecraft:stained_hardened_clay", - "blockRuntimeId": 10560 - }, - { - "id": "minecraft:stained_hardened_clay", - "blockRuntimeId": 10564 - }, - { - "id": "minecraft:white_glazed_terracotta", - "blockRuntimeId": 8738 - }, - { - "id": "minecraft:silver_glazed_terracotta", - "blockRuntimeId": 5018 - }, - { - "id": "minecraft:gray_glazed_terracotta", - "blockRuntimeId": 13102 - }, - { - "id": "minecraft:black_glazed_terracotta", - "blockRuntimeId": 9389 - }, - { - "id": "minecraft:brown_glazed_terracotta", - "blockRuntimeId": 5418 - }, - { - "id": "minecraft:red_glazed_terracotta", - "blockRuntimeId": 6426 - }, - { - "id": "minecraft:orange_glazed_terracotta", - "blockRuntimeId": 2257 - }, - { - "id": "minecraft:yellow_glazed_terracotta", - "blockRuntimeId": 2032 - }, - { - "id": "minecraft:lime_glazed_terracotta", - "blockRuntimeId": 634 - }, - { - "id": "minecraft:green_glazed_terracotta", - "blockRuntimeId": 11008 - }, - { - "id": "minecraft:cyan_glazed_terracotta", - "blockRuntimeId": 8521 - }, - { - "id": "minecraft:light_blue_glazed_terracotta", - "blockRuntimeId": 8635 - }, - { - "id": "minecraft:blue_glazed_terracotta", - "blockRuntimeId": 8629 - }, - { - "id": "minecraft:purple_glazed_terracotta", - "blockRuntimeId": 11411 - }, - { - "id": "minecraft:magenta_glazed_terracotta", - "blockRuntimeId": 2071 - }, - { - "id": "minecraft:pink_glazed_terracotta", - "blockRuntimeId": 10937 - }, - { - "id": "minecraft:purpur_block", - "blockRuntimeId": 12535 - }, - { - "id": "minecraft:purpur_block", - "blockRuntimeId": 12537 - }, - { - "id": "minecraft:packed_mud", - "blockRuntimeId": 715 - }, - { - "id": "minecraft:mud_bricks", - "blockRuntimeId": 11280 - }, - { - "id": "minecraft:nether_wart_block", - "blockRuntimeId": 6560 - }, - { - "id": "minecraft:warped_wart_block", - "blockRuntimeId": 9872 - }, - { - "id": "minecraft:shroomlight", - "blockRuntimeId": 8191 - }, - { - "id": "minecraft:crimson_nylium", - "blockRuntimeId": 6450 - }, - { - "id": "minecraft:warped_nylium", - "blockRuntimeId": 10743 - }, - { - "id": "minecraft:netherrack", - "blockRuntimeId": 11437 - }, - { - "id": "minecraft:basalt", - "blockRuntimeId": 6651 - }, - { - "id": "minecraft:polished_basalt", - "blockRuntimeId": 24 - }, - { - "id": "minecraft:smooth_basalt", - "blockRuntimeId": 2263 - }, - { - "id": "minecraft:soul_soil", - "blockRuntimeId": 8997 - }, - { - "id": "minecraft:dirt", - "blockRuntimeId": 8918 - }, - { - "id": "minecraft:dirt", - "blockRuntimeId": 8919 - }, - { - "id": "minecraft:farmland", - "blockRuntimeId": 6171 - }, - { - "id": "minecraft:grass", - "blockRuntimeId": 11372 - }, - { - "id": "minecraft:grass_path", - "blockRuntimeId": 12914 - }, - { - "id": "minecraft:podzol", - "blockRuntimeId": 7384 - }, - { - "id": "minecraft:mycelium", - "blockRuntimeId": 5559 - }, - { - "id": "minecraft:mud", - "blockRuntimeId": 11070 - }, - { - "id": "minecraft:stone", - "blockRuntimeId": 1743 - }, - { - "id": "minecraft:iron_ore", - "blockRuntimeId": 7424 - }, - { - "id": "minecraft:gold_ore", - "blockRuntimeId": 2031 - }, - { - "id": "minecraft:diamond_ore", - "blockRuntimeId": 6663 - }, - { - "id": "minecraft:lapis_ore", - "blockRuntimeId": 12519 - }, - { - "id": "minecraft:redstone_ore", - "blockRuntimeId": 6553 - }, - { - "id": "minecraft:coal_ore", - "blockRuntimeId": 6551 - }, - { - "id": "minecraft:copper_ore", - "blockRuntimeId": 5425 - }, - { - "id": "minecraft:emerald_ore", - "blockRuntimeId": 12172 - }, - { - "id": "minecraft:quartz_ore", - "blockRuntimeId": 6807 - }, - { - "id": "minecraft:nether_gold_ore", - "blockRuntimeId": 27 - }, - { - "id": "minecraft:ancient_debris", - "blockRuntimeId": 10489 - }, - { - "id": "minecraft:deepslate_iron_ore", - "blockRuntimeId": 12098 - }, - { - "id": "minecraft:deepslate_gold_ore", - "blockRuntimeId": 10488 - }, - { - "id": "minecraft:deepslate_diamond_ore", - "blockRuntimeId": 12868 - }, - { - "id": "minecraft:deepslate_lapis_ore", - "blockRuntimeId": 12080 - }, - { - "id": "minecraft:deepslate_redstone_ore", - "blockRuntimeId": 11014 - }, - { - "id": "minecraft:deepslate_emerald_ore", - "blockRuntimeId": 10744 - }, - { - "id": "minecraft:deepslate_coal_ore", - "blockRuntimeId": 11998 - }, - { - "id": "minecraft:deepslate_copper_ore", - "blockRuntimeId": 108 - }, - { - "id": "minecraft:gravel", - "blockRuntimeId": 13139 - }, - { - "id": "minecraft:stone", - "blockRuntimeId": 1744 - }, - { - "id": "minecraft:stone", - "blockRuntimeId": 1746 - }, - { - "id": "minecraft:stone", - "blockRuntimeId": 1748 - }, - { - "id": "minecraft:blackstone", - "blockRuntimeId": 12405 - }, - { - "id": "minecraft:deepslate", - "blockRuntimeId": 664 - }, - { - "id": "minecraft:stone", - "blockRuntimeId": 1745 - }, - { - "id": "minecraft:stone", - "blockRuntimeId": 1747 - }, - { - "id": "minecraft:stone", - "blockRuntimeId": 1749 - }, - { - "id": "minecraft:polished_blackstone", - "blockRuntimeId": 5558 - }, - { - "id": "minecraft:polished_deepslate", - "blockRuntimeId": 12583 - }, - { - "id": "minecraft:sand", - "blockRuntimeId": 6456 - }, - { - "id": "minecraft:sand", - "blockRuntimeId": 6457 - }, - { - "id": "minecraft:cactus", - "blockRuntimeId": 11383 - }, - { - "id": "minecraft:oak_log", - "blockRuntimeId": 710 - }, - { - "id": "minecraft:stripped_oak_log", - "blockRuntimeId": 12363 - }, - { - "id": "minecraft:spruce_log", - "blockRuntimeId": 6531 - }, - { - "id": "minecraft:stripped_spruce_log", - "blockRuntimeId": 10682 - }, - { - "id": "minecraft:birch_log", - "blockRuntimeId": 1766 - }, - { - "id": "minecraft:stripped_birch_log", - "blockRuntimeId": 9941 - }, - { - "id": "minecraft:jungle_log", - "blockRuntimeId": 625 - }, - { - "id": "minecraft:stripped_jungle_log", - "blockRuntimeId": 1731 - }, - { - "id": "minecraft:acacia_log", - "blockRuntimeId": 6632 - }, - { - "id": "minecraft:stripped_acacia_log", - "blockRuntimeId": 9415 - }, - { - "id": "minecraft:dark_oak_log", - "blockRuntimeId": 4574 - }, - { - "id": "minecraft:stripped_dark_oak_log", - "blockRuntimeId": 622 - }, - { - "id": "minecraft:mangrove_log", - "blockRuntimeId": 1070 - }, - { - "id": "minecraft:stripped_mangrove_log", - "blockRuntimeId": 13136 - }, - { - "id": "minecraft:cherry_log", - "blockRuntimeId": 12084 - }, - { - "id": "minecraft:stripped_cherry_log", - "blockRuntimeId": 6735 - }, - { - "id": "minecraft:crimson_stem", - "blockRuntimeId": 9864 - }, - { - "id": "minecraft:stripped_crimson_stem", - "blockRuntimeId": 11345 - }, - { - "id": "minecraft:warped_stem", - "blockRuntimeId": 10892 - }, - { - "id": "minecraft:stripped_warped_stem", - "blockRuntimeId": 12219 - }, - { - "id": "minecraft:wood", - "blockRuntimeId": 4577 - }, - { - "id": "minecraft:wood", - "blockRuntimeId": 4583 - }, - { - "id": "minecraft:wood", - "blockRuntimeId": 4578 - }, - { - "id": "minecraft:wood", - "blockRuntimeId": 4584 - }, - { - "id": "minecraft:wood", - "blockRuntimeId": 4579 - }, - { - "id": "minecraft:wood", - "blockRuntimeId": 4585 - }, - { - "id": "minecraft:wood", - "blockRuntimeId": 4580 - }, - { - "id": "minecraft:wood", - "blockRuntimeId": 4586 - }, - { - "id": "minecraft:wood", - "blockRuntimeId": 4581 - }, - { - "id": "minecraft:wood", - "blockRuntimeId": 4587 - }, - { - "id": "minecraft:wood", - "blockRuntimeId": 4582 - }, - { - "id": "minecraft:wood", - "blockRuntimeId": 4588 - }, - { - "id": "minecraft:mangrove_wood", - "blockRuntimeId": 6420 - }, - { - "id": "minecraft:stripped_mangrove_wood", - "blockRuntimeId": 6490 - }, - { - "id": "minecraft:cherry_wood", - "blockRuntimeId": 11524 - }, - { - "id": "minecraft:stripped_cherry_wood", - "blockRuntimeId": 8002 - }, - { - "id": "minecraft:crimson_hyphae", - "blockRuntimeId": 6593 - }, - { - "id": "minecraft:stripped_crimson_hyphae", - "blockRuntimeId": 10895 - }, - { - "id": "minecraft:warped_hyphae", - "blockRuntimeId": 9869 - }, - { - "id": "minecraft:stripped_warped_hyphae", - "blockRuntimeId": 8744 - }, - { - "id": "minecraft:bamboo_block", - "blockRuntimeId": 60 - }, - { - "id": "minecraft:stripped_bamboo_block", - "blockRuntimeId": 5468 - }, - { - "id": "minecraft:leaves", - "blockRuntimeId": 10472 - }, - { - "id": "minecraft:leaves", - "blockRuntimeId": 10473 - }, - { - "id": "minecraft:leaves", - "blockRuntimeId": 10474 - }, - { - "id": "minecraft:leaves", - "blockRuntimeId": 10475 - }, - { - "id": "minecraft:leaves2", - "blockRuntimeId": 6655 - }, - { - "id": "minecraft:leaves2", - "blockRuntimeId": 6656 - }, - { - "id": "minecraft:mangrove_leaves", - "blockRuntimeId": 11064 - }, - { - "id": "minecraft:cherry_leaves", - "blockRuntimeId": 9385 - }, - { - "id": "minecraft:azalea_leaves", - "blockRuntimeId": 12531 - }, - { - "id": "minecraft:azalea_leaves_flowered", - "blockRuntimeId": 10733 - }, - { - "id": "minecraft:sapling", - "blockRuntimeId": 1807 - }, - { - "id": "minecraft:sapling", - "blockRuntimeId": 1808 - }, - { - "id": "minecraft:sapling", - "blockRuntimeId": 1809 - }, - { - "id": "minecraft:sapling", - "blockRuntimeId": 1810 - }, - { - "id": "minecraft:sapling", - "blockRuntimeId": 1811 - }, - { - "id": "minecraft:sapling", - "blockRuntimeId": 1812 - }, - { - "id": "minecraft:mangrove_propagule", - "blockRuntimeId": 11373 - }, - { - "id": "minecraft:cherry_sapling", - "blockRuntimeId": 12082 - }, - { - "id": "minecraft:bee_nest", - "blockRuntimeId": 8921 - }, - { - "id": "minecraft:wheat_seeds", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:pumpkin_seeds", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:melon_seeds", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:beetroot_seeds", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:torchflower_seeds", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:pitcher_pod", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:wheat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:beetroot", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potato", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:poisonous_potato", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:carrot", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:golden_carrot", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:apple", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:golden_apple", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:enchanted_golden_apple", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:melon_block", - "blockRuntimeId": 1117 - }, - { - "id": "minecraft:melon_slice", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:glistering_melon_slice", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:sweet_berries", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:glow_berries", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:pumpkin", - "blockRuntimeId": 6883 - }, - { - "id": "minecraft:carved_pumpkin", - "blockRuntimeId": 12197 - }, - { - "id": "minecraft:lit_pumpkin", - "blockRuntimeId": 11071 - }, - { - "id": "minecraft:honeycomb", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:tallgrass", - "blockRuntimeId": 2049 - }, - { - "id": "minecraft:double_plant", - "blockRuntimeId": 8619 - }, - { - "id": "minecraft:tallgrass", - "blockRuntimeId": 2048 - }, - { - "id": "minecraft:double_plant", - "blockRuntimeId": 8618 - }, - { - "id": "minecraft:nether_sprouts", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:fire_coral", - "blockRuntimeId": 1742 - }, - { - "id": "minecraft:brain_coral", - "blockRuntimeId": 1770 - }, - { - "id": "minecraft:bubble_coral", - "blockRuntimeId": 10616 - }, - { - "id": "minecraft:tube_coral", - "blockRuntimeId": 12592 - }, - { - "id": "minecraft:horn_coral", - "blockRuntimeId": 5490 - }, - { - "id": "minecraft:dead_fire_coral", - "blockRuntimeId": 10673 - }, - { - "id": "minecraft:dead_brain_coral", - "blockRuntimeId": 11997 - }, - { - "id": "minecraft:dead_bubble_coral", - "blockRuntimeId": 12081 - }, - { - "id": "minecraft:dead_tube_coral", - "blockRuntimeId": 6559 - }, - { - "id": "minecraft:dead_horn_coral", - "blockRuntimeId": 9882 - }, - { - "id": "minecraft:coral_fan", - "blockRuntimeId": 6922 - }, - { - "id": "minecraft:coral_fan", - "blockRuntimeId": 6920 - }, - { - "id": "minecraft:coral_fan", - "blockRuntimeId": 6921 - }, - { - "id": "minecraft:coral_fan", - "blockRuntimeId": 6919 - }, - { - "id": "minecraft:coral_fan", - "blockRuntimeId": 6923 - }, - { - "id": "minecraft:coral_fan_dead", - "blockRuntimeId": 72 - }, - { - "id": "minecraft:coral_fan_dead", - "blockRuntimeId": 70 - }, - { - "id": "minecraft:coral_fan_dead", - "blockRuntimeId": 71 - }, - { - "id": "minecraft:coral_fan_dead", - "blockRuntimeId": 69 - }, - { - "id": "minecraft:coral_fan_dead", - "blockRuntimeId": 73 - }, - { - "id": "minecraft:crimson_roots", - "blockRuntimeId": 12393 - }, - { - "id": "minecraft:warped_roots", - "blockRuntimeId": 6664 - }, - { - "id": "minecraft:yellow_flower", - "blockRuntimeId": 1022 - }, - { - "id": "minecraft:red_flower", - "blockRuntimeId": 5492 - }, - { - "id": "minecraft:red_flower", - "blockRuntimeId": 5493 - }, - { - "id": "minecraft:red_flower", - "blockRuntimeId": 5494 - }, - { - "id": "minecraft:red_flower", - "blockRuntimeId": 5495 - }, - { - "id": "minecraft:red_flower", - "blockRuntimeId": 5496 - }, - { - "id": "minecraft:red_flower", - "blockRuntimeId": 5497 - }, - { - "id": "minecraft:red_flower", - "blockRuntimeId": 5498 - }, - { - "id": "minecraft:red_flower", - "blockRuntimeId": 5499 - }, - { - "id": "minecraft:red_flower", - "blockRuntimeId": 5500 - }, - { - "id": "minecraft:red_flower", - "blockRuntimeId": 5501 - }, - { - "id": "minecraft:red_flower", - "blockRuntimeId": 5502 - }, - { - "id": "minecraft:double_plant", - "blockRuntimeId": 8616 - }, - { - "id": "minecraft:double_plant", - "blockRuntimeId": 8617 - }, - { - "id": "minecraft:double_plant", - "blockRuntimeId": 8620 - }, - { - "id": "minecraft:double_plant", - "blockRuntimeId": 8621 - }, - { - "id": "minecraft:pitcher_plant", - "blockRuntimeId": 5637 - }, - { - "id": "minecraft:pink_petals", - "blockRuntimeId": 6959 - }, - { - "id": "minecraft:wither_rose", - "blockRuntimeId": 10547 - }, - { - "id": "minecraft:torchflower", - "blockRuntimeId": 10436 - }, - { - "id": "minecraft:white_dye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:light_gray_dye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:gray_dye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:black_dye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:brown_dye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:red_dye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:orange_dye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:yellow_dye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lime_dye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:green_dye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cyan_dye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:light_blue_dye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:blue_dye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:purple_dye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:magenta_dye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:pink_dye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:ink_sac", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:glow_ink_sac", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cocoa_beans", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lapis_lazuli", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bone_meal", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:vine", - "blockRuntimeId": 1997 - }, - { - "id": "minecraft:weeping_vines", - "blockRuntimeId": 8644 - }, - { - "id": "minecraft:twisting_vines", - "blockRuntimeId": 8857 - }, - { - "id": "minecraft:waterlily", - "blockRuntimeId": 2264 - }, - { - "id": "minecraft:seagrass", - "blockRuntimeId": 657 - }, - { - "id": "minecraft:kelp", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:deadbush", - "blockRuntimeId": 7411 - }, - { - "id": "minecraft:bamboo", - "blockRuntimeId": 5560 - }, - { - "id": "minecraft:snow", - "blockRuntimeId": 6455 - }, - { - "id": "minecraft:ice", - "blockRuntimeId": 11075 - }, - { - "id": "minecraft:packed_ice", - "blockRuntimeId": 714 - }, - { - "id": "minecraft:blue_ice", - "blockRuntimeId": 11427 - }, - { - "id": "minecraft:snow_layer", - "blockRuntimeId": 560 - }, - { - "id": "minecraft:pointed_dripstone", - "blockRuntimeId": 12235 - }, - { - "id": "minecraft:dripstone_block", - "blockRuntimeId": 1996 - }, - { - "id": "minecraft:moss_carpet", - "blockRuntimeId": 718 - }, - { - "id": "minecraft:moss_block", - "blockRuntimeId": 10936 - }, - { - "id": "minecraft:dirt_with_roots", - "blockRuntimeId": 8560 - }, - { - "id": "minecraft:hanging_roots", - "blockRuntimeId": 611 - }, - { - "id": "minecraft:mangrove_roots", - "blockRuntimeId": 10557 - }, - { - "id": "minecraft:muddy_mangrove_roots", - "blockRuntimeId": 1065 - }, - { - "id": "minecraft:big_dripleaf", - "blockRuntimeId": 9949 - }, - { - "id": "minecraft:small_dripleaf_block", - "blockRuntimeId": 6619 - }, - { - "id": "minecraft:spore_blossom", - "blockRuntimeId": 12137 - }, - { - "id": "minecraft:azalea", - "blockRuntimeId": 11279 - }, - { - "id": "minecraft:flowering_azalea", - "blockRuntimeId": 8641 - }, - { - "id": "minecraft:glow_lichen", - "blockRuntimeId": 8850 - }, - { - "id": "minecraft:amethyst_block", - "blockRuntimeId": 754 - }, - { - "id": "minecraft:budding_amethyst", - "blockRuntimeId": 11399 - }, - { - "id": "minecraft:amethyst_cluster", - "blockRuntimeId": 12640 - }, - { - "id": "minecraft:large_amethyst_bud", - "blockRuntimeId": 7462 - }, - { - "id": "minecraft:medium_amethyst_bud", - "blockRuntimeId": 6678 - }, - { - "id": "minecraft:small_amethyst_bud", - "blockRuntimeId": 1024 - }, - { - "id": "minecraft:tuff", - "blockRuntimeId": 1069 - }, - { - "id": "minecraft:calcite", - "blockRuntimeId": 621 - }, - { - "id": "minecraft:chicken", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:porkchop", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:beef", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:mutton", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:rabbit", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cod", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:salmon", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:tropical_fish", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:pufferfish", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:brown_mushroom", - "blockRuntimeId": 5417 - }, - { - "id": "minecraft:red_mushroom", - "blockRuntimeId": 6891 - }, - { - "id": "minecraft:crimson_fungus", - "blockRuntimeId": 12581 - }, - { - "id": "minecraft:warped_fungus", - "blockRuntimeId": 719 - }, - { - "id": "minecraft:brown_mushroom_block", - "blockRuntimeId": 12187 - }, - { - "id": "minecraft:red_mushroom_block", - "blockRuntimeId": 5485 - }, - { - "id": "minecraft:brown_mushroom_block", - "blockRuntimeId": 12188 - }, - { - "id": "minecraft:brown_mushroom_block", - "blockRuntimeId": 12173 - }, - { - "id": "minecraft:egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:sugar_cane", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:sugar", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:rotten_flesh", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bone", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:web", - "blockRuntimeId": 11099 - }, - { - "id": "minecraft:spider_eye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:mob_spawner", - "blockRuntimeId": 1126 - }, - { - "id": "minecraft:monster_egg", - "blockRuntimeId": 6403 - }, - { - "id": "minecraft:monster_egg", - "blockRuntimeId": 6404 - }, - { - "id": "minecraft:monster_egg", - "blockRuntimeId": 6405 - }, - { - "id": "minecraft:monster_egg", - "blockRuntimeId": 6406 - }, - { - "id": "minecraft:monster_egg", - "blockRuntimeId": 6407 - }, - { - "id": "minecraft:monster_egg", - "blockRuntimeId": 6408 - }, - { - "id": "minecraft:infested_deepslate", - "blockRuntimeId": 7375 - }, - { - "id": "minecraft:dragon_egg", - "blockRuntimeId": 12096 - }, - { - "id": "minecraft:turtle_egg", - "blockRuntimeId": 12827 - }, - { - "id": "minecraft:sniffer_egg", - "blockRuntimeId": 11400 - }, - { - "id": "minecraft:frog_spawn", - "blockRuntimeId": 6702 - }, - { - "id": "minecraft:pearlescent_froglight", - "blockRuntimeId": 10829 - }, - { - "id": "minecraft:verdant_froglight", - "blockRuntimeId": 10887 - }, - { - "id": "minecraft:ochre_froglight", - "blockRuntimeId": 4997 - }, - { - "id": "minecraft:chicken_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bee_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cow_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:pig_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:sheep_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:wolf_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:polar_bear_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:ocelot_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cat_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:mooshroom_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bat_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:parrot_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:rabbit_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:llama_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:horse_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:donkey_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:mule_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:skeleton_horse_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:zombie_horse_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:tropical_fish_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cod_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:pufferfish_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:salmon_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:dolphin_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:turtle_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:panda_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:fox_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:creeper_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:enderman_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:silverfish_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:skeleton_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:wither_skeleton_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:stray_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:slime_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:spider_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:zombie_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:zombie_pigman_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:husk_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:drowned_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:squid_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:glow_squid_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cave_spider_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:witch_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:guardian_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:elder_guardian_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:endermite_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:magma_cube_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:strider_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:hoglin_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:piglin_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:zoglin_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:piglin_brute_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:goat_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:axolotl_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:warden_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:allay_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:frog_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:tadpole_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:trader_llama_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:camel_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:ghast_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:blaze_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:shulker_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:vindicator_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:evoker_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:vex_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:villager_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:wandering_trader_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:zombie_villager_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:phantom_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:pillager_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:ravager_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:iron_golem_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:snow_golem_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:sniffer_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:obsidian", - "blockRuntimeId": 1153 - }, - { - "id": "minecraft:crying_obsidian", - "blockRuntimeId": 11108 - }, - { - "id": "minecraft:bedrock", - "blockRuntimeId": 11417 - }, - { - "id": "minecraft:soul_sand", - "blockRuntimeId": 8998 - }, - { - "id": "minecraft:magma", - "blockRuntimeId": 12839 - }, - { - "id": "minecraft:nether_wart", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:end_stone", - "blockRuntimeId": 6095 - }, - { - "id": "minecraft:chorus_flower", - "blockRuntimeId": 6836 - }, - { - "id": "minecraft:chorus_plant", - "blockRuntimeId": 8670 - }, - { - "id": "minecraft:chorus_fruit", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:popped_chorus_fruit", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:sponge", - "blockRuntimeId": 1333 - }, - { - "id": "minecraft:sponge", - "blockRuntimeId": 1334 - }, - { - "id": "minecraft:coral_block", - "blockRuntimeId": 8383 - }, - { - "id": "minecraft:coral_block", - "blockRuntimeId": 8384 - }, - { - "id": "minecraft:coral_block", - "blockRuntimeId": 8385 - }, - { - "id": "minecraft:coral_block", - "blockRuntimeId": 8386 - }, - { - "id": "minecraft:coral_block", - "blockRuntimeId": 8387 - }, - { - "id": "minecraft:coral_block", - "blockRuntimeId": 8388 - }, - { - "id": "minecraft:coral_block", - "blockRuntimeId": 8389 - }, - { - "id": "minecraft:coral_block", - "blockRuntimeId": 8390 - }, - { - "id": "minecraft:coral_block", - "blockRuntimeId": 8391 - }, - { - "id": "minecraft:coral_block", - "blockRuntimeId": 8392 - }, - { - "id": "minecraft:sculk", - "blockRuntimeId": 11436 - }, - { - "id": "minecraft:sculk_vein", - "blockRuntimeId": 11933 - }, - { - "id": "minecraft:sculk_catalyst", - "blockRuntimeId": 5487 - }, - { - "id": "minecraft:sculk_shrieker", - "blockRuntimeId": 628 - }, - { - "id": "minecraft:sculk_sensor", - "blockRuntimeId": 6691 - }, - { - "id": "minecraft:calibrated_sculk_sensor", - "blockRuntimeId": 9403 - }, - { - "id": "minecraft:reinforced_deepslate", - "blockRuntimeId": 9383 - }, - { - "id": "minecraft:leather_helmet", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:chainmail_helmet", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:iron_helmet", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:golden_helmet", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:diamond_helmet", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:netherite_helmet", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:leather_chestplate", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:chainmail_chestplate", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:iron_chestplate", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:golden_chestplate", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:diamond_chestplate", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:netherite_chestplate", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:leather_leggings", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:chainmail_leggings", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:iron_leggings", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:golden_leggings", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:diamond_leggings", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:netherite_leggings", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:leather_boots", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:chainmail_boots", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:iron_boots", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:golden_boots", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:diamond_boots", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:netherite_boots", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:wooden_sword", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:stone_sword", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:iron_sword", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:golden_sword", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:diamond_sword", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:netherite_sword", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:wooden_axe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:stone_axe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:iron_axe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:golden_axe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:diamond_axe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:netherite_axe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:wooden_pickaxe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:stone_pickaxe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:iron_pickaxe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:golden_pickaxe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:diamond_pickaxe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:netherite_pickaxe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:wooden_shovel", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:stone_shovel", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:iron_shovel", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:golden_shovel", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:diamond_shovel", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:netherite_shovel", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:wooden_hoe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:stone_hoe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:iron_hoe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:golden_hoe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:diamond_hoe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:netherite_hoe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bow", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:crossbow", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 6, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 7, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 8, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 9, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 10, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 11, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 12, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 13, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 14, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 15, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 16, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 17, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 18, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 19, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 20, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 21, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 22, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 23, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 24, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 25, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 26, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 27, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 28, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 29, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 30, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 31, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 32, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 33, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 34, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 35, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 36, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 37, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 38, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 39, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 40, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 41, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 42, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 43, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:shield", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cooked_chicken", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cooked_porkchop", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cooked_beef", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cooked_mutton", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cooked_rabbit", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cooked_cod", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cooked_salmon", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bread", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:mushroom_stew", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:beetroot_soup", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:rabbit_stew", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:baked_potato", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cookie", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:pumpkin_pie", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cake", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:dried_kelp", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:fishing_rod", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:carrot_on_a_stick", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:warped_fungus_on_a_stick", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:snowball", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:shears", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:flint_and_steel", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lead", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:clock", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:compass", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:recovery_compass", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:goat_horn", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:goat_horn", - "damage": 1, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:goat_horn", - "damage": 2, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:goat_horn", - "damage": 3, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:goat_horn", - "damage": 4, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:goat_horn", - "damage": 5, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:goat_horn", - "damage": 6, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:goat_horn", - "damage": 7, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:empty_map", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:empty_map", - "damage": 2, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:saddle", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:leather_horse_armor", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:iron_horse_armor", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:golden_horse_armor", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:diamond_horse_armor", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:trident", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:turtle_helmet", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:elytra", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:totem_of_undying", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:glass_bottle", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:experience_bottle", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 1, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 2, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 3, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 4, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 5, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 6, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 7, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 8, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 9, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 10, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 11, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 12, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 13, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 14, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 15, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 16, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 17, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 18, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 19, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 20, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 21, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 22, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 23, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 24, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 25, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 26, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 27, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 28, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 29, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 30, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 31, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 32, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 33, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 34, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 35, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 36, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 37, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 38, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 39, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 40, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 41, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 42, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 1, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 2, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 3, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 4, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 5, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 6, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 7, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 8, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 9, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 10, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 11, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 12, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 13, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 14, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 15, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 16, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 17, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 18, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 19, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 20, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 21, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 22, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 23, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 24, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 25, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 26, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 27, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 28, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 29, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 30, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 31, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 32, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 33, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 34, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 35, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 36, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 37, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 38, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 39, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 40, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 41, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 42, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 1, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 2, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 3, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 4, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 5, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 6, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 7, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 8, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 9, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 10, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 11, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 12, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 13, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 14, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 15, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 16, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 17, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 18, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 19, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 20, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 21, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 22, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 23, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 24, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 25, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 26, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 27, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 28, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 29, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 30, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 31, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 32, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 33, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 34, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 35, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 36, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 37, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 38, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 39, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 40, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 41, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 42, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:spyglass", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:brush", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:stick", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bed", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bed", - "damage": 8, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bed", - "damage": 7, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bed", - "damage": 15, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bed", - "damage": 12, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bed", - "damage": 14, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bed", - "damage": 1, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bed", - "damage": 4, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bed", - "damage": 5, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bed", - "damage": 13, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bed", - "damage": 9, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bed", - "damage": 3, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bed", - "damage": 11, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bed", - "damage": 10, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bed", - "damage": 2, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bed", - "damage": 6, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:torch", - "blockRuntimeId": 1827 - }, - { - "id": "minecraft:soul_torch", - "blockRuntimeId": 7378 - }, - { - "id": "minecraft:sea_pickle", - "blockRuntimeId": 9422 - }, - { - "id": "minecraft:lantern", - "blockRuntimeId": 11475 - }, - { - "id": "minecraft:soul_lantern", - "blockRuntimeId": 8916 - }, - { - "id": "minecraft:candle", - "blockRuntimeId": 12222 - }, - { - "id": "minecraft:white_candle", - "blockRuntimeId": 8462 - }, - { - "id": "minecraft:orange_candle", - "blockRuntimeId": 1085 - }, - { - "id": "minecraft:magenta_candle", - "blockRuntimeId": 1143 - }, - { - "id": "minecraft:light_blue_candle", - "blockRuntimeId": 6875 - }, - { - "id": "minecraft:yellow_candle", - "blockRuntimeId": 10574 - }, - { - "id": "minecraft:lime_candle", - "blockRuntimeId": 10762 - }, - { - "id": "minecraft:pink_candle", - "blockRuntimeId": 12189 - }, - { - "id": "minecraft:gray_candle", - "blockRuntimeId": 2059 - }, - { - "id": "minecraft:light_gray_candle", - "blockRuntimeId": 10617 - }, - { - "id": "minecraft:cyan_candle", - "blockRuntimeId": 12553 - }, - { - "id": "minecraft:purple_candle", - "blockRuntimeId": 11438 - }, - { - "id": "minecraft:blue_candle", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:brown_candle", - "blockRuntimeId": 9842 - }, - { - "id": "minecraft:green_candle", - "blockRuntimeId": 1781 - }, - { - "id": "minecraft:red_candle", - "blockRuntimeId": 7415 - }, - { - "id": "minecraft:black_candle", - "blockRuntimeId": 576 - }, - { - "id": "minecraft:crafting_table", - "blockRuntimeId": 9421 - }, - { - "id": "minecraft:cartography_table", - "blockRuntimeId": 13140 - }, - { - "id": "minecraft:fletching_table", - "blockRuntimeId": 9384 - }, - { - "id": "minecraft:smithing_table", - "blockRuntimeId": 5602 - }, - { - "id": "minecraft:beehive", - "blockRuntimeId": 10490 - }, - { - "id": "minecraft:suspicious_sand", - "blockRuntimeId": 2267 - }, - { - "id": "minecraft:suspicious_gravel", - "blockRuntimeId": 7468 - }, - { - "id": "minecraft:campfire", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:soul_campfire", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:furnace", - "blockRuntimeId": 12632 - }, - { - "id": "minecraft:blast_furnace", - "blockRuntimeId": 12387 - }, - { - "id": "minecraft:smoker", - "blockRuntimeId": 1736 - }, - { - "id": "minecraft:respawn_anchor", - "blockRuntimeId": 1776 - }, - { - "id": "minecraft:brewing_stand", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:anvil", - "blockRuntimeId": 11032 - }, - { - "id": "minecraft:anvil", - "blockRuntimeId": 11036 - }, - { - "id": "minecraft:anvil", - "blockRuntimeId": 11040 - }, - { - "id": "minecraft:grindstone", - "blockRuntimeId": 12869 - }, - { - "id": "minecraft:enchanting_table", - "blockRuntimeId": 11114 - }, - { - "id": "minecraft:bookshelf", - "blockRuntimeId": 11069 - }, - { - "id": "minecraft:chiseled_bookshelf", - "blockRuntimeId": 758 - }, - { - "id": "minecraft:lectern", - "blockRuntimeId": 11337 - }, - { - "id": "minecraft:cauldron", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:composter", - "blockRuntimeId": 8579 - }, - { - "id": "minecraft:chest", - "blockRuntimeId": 11518 - }, - { - "id": "minecraft:trapped_chest", - "blockRuntimeId": 8748 - }, - { - "id": "minecraft:ender_chest", - "blockRuntimeId": 6671 - }, - { - "id": "minecraft:barrel", - "blockRuntimeId": 6824 - }, - { - "id": "minecraft:undyed_shulker_box", - "blockRuntimeId": 5557 - }, - { - "id": "minecraft:shulker_box", - "blockRuntimeId": 8478 - }, - { - "id": "minecraft:shulker_box", - "blockRuntimeId": 8486 - }, - { - "id": "minecraft:shulker_box", - "blockRuntimeId": 8485 - }, - { - "id": "minecraft:shulker_box", - "blockRuntimeId": 8493 - }, - { - "id": "minecraft:shulker_box", - "blockRuntimeId": 8490 - }, - { - "id": "minecraft:shulker_box", - "blockRuntimeId": 8492 - }, - { - "id": "minecraft:shulker_box", - "blockRuntimeId": 8479 - }, - { - "id": "minecraft:shulker_box", - "blockRuntimeId": 8482 - }, - { - "id": "minecraft:shulker_box", - "blockRuntimeId": 8483 - }, - { - "id": "minecraft:shulker_box", - "blockRuntimeId": 8491 - }, - { - "id": "minecraft:shulker_box", - "blockRuntimeId": 8487 - }, - { - "id": "minecraft:shulker_box", - "blockRuntimeId": 8481 - }, - { - "id": "minecraft:shulker_box", - "blockRuntimeId": 8489 - }, - { - "id": "minecraft:shulker_box", - "blockRuntimeId": 8488 - }, - { - "id": "minecraft:shulker_box", - "blockRuntimeId": 8480 - }, - { - "id": "minecraft:shulker_box", - "blockRuntimeId": 8484 - }, - { - "id": "minecraft:armor_stand", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:noteblock", - "blockRuntimeId": 1068 - }, - { - "id": "minecraft:jukebox", - "blockRuntimeId": 8001 - }, - { - "id": "minecraft:music_disc_13", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:music_disc_cat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:music_disc_blocks", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:music_disc_chirp", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:music_disc_far", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:music_disc_mall", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:music_disc_mellohi", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:music_disc_stal", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:music_disc_strad", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:music_disc_ward", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:music_disc_11", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:music_disc_wait", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:music_disc_otherside", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:music_disc_5", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:music_disc_pigstep", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:music_disc_relic", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:disc_fragment_5", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:glowstone_dust", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:glowstone", - "blockRuntimeId": 6144 - }, - { - "id": "minecraft:redstone_lamp", - "blockRuntimeId": 662 - }, - { - "id": "minecraft:sea_lantern", - "blockRuntimeId": 12366 - }, - { - "id": "minecraft:oak_sign", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:spruce_sign", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:birch_sign", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:jungle_sign", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:acacia_sign", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:dark_oak_sign", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:mangrove_sign", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cherry_sign", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bamboo_sign", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:crimson_sign", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:warped_sign", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:oak_hanging_sign", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:spruce_hanging_sign", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:birch_hanging_sign", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:jungle_hanging_sign", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:acacia_hanging_sign", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:dark_oak_hanging_sign", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:mangrove_hanging_sign", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cherry_hanging_sign", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bamboo_hanging_sign", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:crimson_hanging_sign", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:warped_hanging_sign", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:painting", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:frame", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:glow_frame", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:honey_bottle", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:flower_pot", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bowl", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bucket", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:milk_bucket", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:water_bucket", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lava_bucket", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cod_bucket", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:salmon_bucket", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:tropical_fish_bucket", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:pufferfish_bucket", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:powder_snow_bucket", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:axolotl_bucket", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:tadpole_bucket", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:skull", - "damage": 3, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:skull", - "damage": 2, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:skull", - "damage": 4, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:skull", - "damage": 5, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:skull", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:skull", - "damage": 1, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:skull", - "damage": 6, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:beacon", - "blockRuntimeId": 550 - }, - { - "id": "minecraft:bell", - "blockRuntimeId": 11305 - }, - { - "id": "minecraft:conduit", - "blockRuntimeId": 6493 - }, - { - "id": "minecraft:stonecutter_block", - "blockRuntimeId": 12394 - }, - { - "id": "minecraft:end_portal_frame", - "blockRuntimeId": 10443 - }, - { - "id": "minecraft:coal", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:charcoal", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:diamond", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:iron_nugget", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:raw_iron", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:raw_gold", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:raw_copper", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:copper_ingot", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:iron_ingot", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:netherite_scrap", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:netherite_ingot", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:gold_nugget", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:gold_ingot", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:emerald", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:quartz", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:clay_ball", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:brick", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:netherbrick", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:prismarine_shard", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:amethyst_shard", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:prismarine_crystals", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:nautilus_shell", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:heart_of_the_sea", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:scute", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:phantom_membrane", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:string", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:feather", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:flint", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:gunpowder", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:leather", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:rabbit_hide", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:rabbit_foot", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:fire_charge", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:blaze_rod", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:blaze_powder", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:magma_cream", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:fermented_spider_eye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:echo_shard", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:dragon_breath", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:shulker_shell", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:ghast_tear", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:slime_ball", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:ender_pearl", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:ender_eye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:nether_star", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:end_rod", - "blockRuntimeId": 9858 - }, - { - "id": "minecraft:lightning_rod", - "blockRuntimeId": 2290 - }, - { - "id": "minecraft:end_crystal", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:paper", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:book", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:writable_book", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQFAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQFAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQFAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQGAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQGAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQGAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQHAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQHAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQHAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQIAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAUAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAUAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAUAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQMAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQMAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQNAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQNAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQOAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQOAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQOAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAUAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQQAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQRAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQRAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQRAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQSAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQSAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQSAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAUAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQUAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQUAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQVAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQWAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQXAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQXAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQXAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQYAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQYAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQYAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQZAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQZAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQaAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQbAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQcAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAUAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQeAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQeAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQeAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQfAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQfAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQfAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQgAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQhAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQjAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQjAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQjAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQkAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQkAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQkAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQlAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQlAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQlAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:oak_boat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:spruce_boat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:birch_boat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:jungle_boat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:acacia_boat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:dark_oak_boat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:mangrove_boat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cherry_boat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bamboo_raft", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:oak_chest_boat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:spruce_chest_boat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:birch_chest_boat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:jungle_chest_boat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:acacia_chest_boat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:dark_oak_chest_boat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:mangrove_chest_boat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cherry_chest_boat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bamboo_chest_raft", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:rail", - "blockRuntimeId": 6179 - }, - { - "id": "minecraft:golden_rail", - "blockRuntimeId": 8494 - }, - { - "id": "minecraft:detector_rail", - "blockRuntimeId": 6391 - }, - { - "id": "minecraft:activator_rail", - "blockRuntimeId": 1029 - }, - { - "id": "minecraft:minecart", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:chest_minecart", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:hopper_minecart", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:tnt_minecart", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:redstone", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:redstone_block", - "blockRuntimeId": 5657 - }, - { - "id": "minecraft:redstone_torch", - "blockRuntimeId": 5012 - }, - { - "id": "minecraft:lever", - "blockRuntimeId": 10910 - }, - { - "id": "minecraft:wooden_button", - "blockRuntimeId": 10785 - }, - { - "id": "minecraft:spruce_button", - "blockRuntimeId": 6620 - }, - { - "id": "minecraft:birch_button", - "blockRuntimeId": 12596 - }, - { - "id": "minecraft:jungle_button", - "blockRuntimeId": 120 - }, - { - "id": "minecraft:acacia_button", - "blockRuntimeId": 12049 - }, - { - "id": "minecraft:dark_oak_button", - "blockRuntimeId": 96 - }, - { - "id": "minecraft:mangrove_button", - "blockRuntimeId": 11462 - }, - { - "id": "minecraft:cherry_button", - "blockRuntimeId": 6929 - }, - { - "id": "minecraft:bamboo_button", - "blockRuntimeId": 10874 - }, - { - "id": "minecraft:stone_button", - "blockRuntimeId": 1321 - }, - { - "id": "minecraft:crimson_button", - "blockRuntimeId": 6738 - }, - { - "id": "minecraft:warped_button", - "blockRuntimeId": 12068 - }, - { - "id": "minecraft:polished_blackstone_button", - "blockRuntimeId": 12620 - }, - { - "id": "minecraft:tripwire_hook", - "blockRuntimeId": 9883 - }, - { - "id": "minecraft:wooden_pressure_plate", - "blockRuntimeId": 12894 - }, - { - "id": "minecraft:spruce_pressure_plate", - "blockRuntimeId": 5639 - }, - { - "id": "minecraft:birch_pressure_plate", - "blockRuntimeId": 5426 - }, - { - "id": "minecraft:jungle_pressure_plate", - "blockRuntimeId": 5511 - }, - { - "id": "minecraft:acacia_pressure_plate", - "blockRuntimeId": 8393 - }, - { - "id": "minecraft:dark_oak_pressure_plate", - "blockRuntimeId": 9925 - }, - { - "id": "minecraft:mangrove_pressure_plate", - "blockRuntimeId": 6128 - }, - { - "id": "minecraft:cherry_pressure_plate", - "blockRuntimeId": 142 - }, - { - "id": "minecraft:bamboo_pressure_plate", - "blockRuntimeId": 10451 - }, - { - "id": "minecraft:crimson_pressure_plate", - "blockRuntimeId": 13120 - }, - { - "id": "minecraft:warped_pressure_plate", - "blockRuntimeId": 685 - }, - { - "id": "minecraft:stone_pressure_plate", - "blockRuntimeId": 6145 - }, - { - "id": "minecraft:light_weighted_pressure_plate", - "blockRuntimeId": 5541 - }, - { - "id": "minecraft:heavy_weighted_pressure_plate", - "blockRuntimeId": 2274 - }, - { - "id": "minecraft:polished_blackstone_pressure_plate", - "blockRuntimeId": 10625 - }, - { - "id": "minecraft:observer", - "blockRuntimeId": 5000 - }, - { - "id": "minecraft:daylight_detector", - "blockRuntimeId": 6458 - }, - { - "id": "minecraft:repeater", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:comparator", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:hopper", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:dropper", - "blockRuntimeId": 12204 - }, - { - "id": "minecraft:dispenser", - "blockRuntimeId": 12843 - }, - { - "id": "minecraft:piston", - "blockRuntimeId": 2041 - }, - { - "id": "minecraft:sticky_piston", - "blockRuntimeId": 6666 - }, - { - "id": "minecraft:tnt", - "blockRuntimeId": 11093 - }, - { - "id": "minecraft:name_tag", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:loom", - "blockRuntimeId": 6091 - }, - { - "id": "minecraft:banner", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:banner", - "damage": 8, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:banner", - "damage": 7, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:banner", - "damage": 15, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:banner", - "damage": 12, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:banner", - "damage": 14, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:banner", - "damage": 1, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:banner", - "damage": 4, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:banner", - "damage": 5, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:banner", - "damage": 13, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:banner", - "damage": 9, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:banner", - "damage": 3, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:banner", - "damage": 11, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:banner", - "damage": 10, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:banner", - "damage": 2, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:banner", - "damage": 6, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:banner", - "damage": 15, - "blockRuntimeId": 0, - "nbt_b64": "CgAAAwQAVHlwZQEAAAAA" - }, - { - "id": "minecraft:creeper_banner_pattern", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:skull_banner_pattern", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:flower_banner_pattern", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:mojang_banner_pattern", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:field_masoned_banner_pattern", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bordure_indented_banner_pattern", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:piglin_banner_pattern", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:globe_banner_pattern", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:angler_pottery_sherd", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:archer_pottery_sherd", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arms_up_pottery_sherd", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:blade_pottery_sherd", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:brewer_pottery_sherd", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:burn_pottery_sherd", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:danger_pottery_sherd", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:explorer_pottery_sherd", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:friend_pottery_sherd", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:heart_pottery_sherd", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:heartbreak_pottery_sherd", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:howl_pottery_sherd", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:miner_pottery_sherd", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:mourner_pottery_sherd", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:plenty_pottery_sherd", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:prize_pottery_sherd", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:sheaf_pottery_sherd", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:shelter_pottery_sherd", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:skull_pottery_sherd", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:snort_pottery_sherd", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:netherite_upgrade_smithing_template", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:sentry_armor_trim_smithing_template", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:vex_armor_trim_smithing_template", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:wild_armor_trim_smithing_template", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:coast_armor_trim_smithing_template", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:dune_armor_trim_smithing_template", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:wayfinder_armor_trim_smithing_template", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:shaper_armor_trim_smithing_template", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:raiser_armor_trim_smithing_template", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:host_armor_trim_smithing_template", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:ward_armor_trim_smithing_template", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:silence_armor_trim_smithing_template", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:tide_armor_trim_smithing_template", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:snout_armor_trim_smithing_template", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:rib_armor_trim_smithing_template", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:eye_armor_trim_smithing_template", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:spire_armor_trim_smithing_template", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwAAAAAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAABwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAIBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAHBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAPBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAMBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAOBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAABBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAEBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAFBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAANBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAJBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAADBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAALBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAKBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAACBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAGBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_star", - "blockRuntimeId": 0, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yIR0d/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 8, - "blockRuntimeId": 0, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yUk9H/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 7, - "blockRuntimeId": 0, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yl52d/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 15, - "blockRuntimeId": 0, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9y8PDw/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 12, - "blockRuntimeId": 0, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9y2rM6/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 14, - "blockRuntimeId": 0, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yHYD5/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 1, - "blockRuntimeId": 0, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yJi6w/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 4, - "blockRuntimeId": 0, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yqkQ8/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 5, - "blockRuntimeId": 0, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yuDKJ/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 13, - "blockRuntimeId": 0, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yvU7H/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 9, - "blockRuntimeId": 0, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yqovz/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 3, - "blockRuntimeId": 0, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yMlSD/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 11, - "blockRuntimeId": 0, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yPdj+/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 10, - "blockRuntimeId": 0, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yH8eA/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 2, - "blockRuntimeId": 0, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yFnxe/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 6, - "blockRuntimeId": 0, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9ynJwW/wA=" - }, - { - "id": "minecraft:chain", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:target", - "blockRuntimeId": 10784 - }, - { - "id": "minecraft:decorated_pot", - "blockRuntimeId": 11110 - }, - { - "id": "minecraft:lodestone_compass", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:wither_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:ender_dragon_spawn_egg", - "blockRuntimeId": 0 - } - ] -} \ No newline at end of file diff --git a/core/src/main/resources/bedrock/creative_items.1_20_10.json b/core/src/main/resources/bedrock/creative_items.1_20_10.json deleted file mode 100644 index c531bf28e..000000000 --- a/core/src/main/resources/bedrock/creative_items.1_20_10.json +++ /dev/null @@ -1,5793 +0,0 @@ -{ - "items": [ - { - "id": "minecraft:planks", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBsYW5rcwQJAG5hbWVfaGFzaA+7EGxL5oikAwoAbmV0d29ya19pZLUoAAAKBgBzdGF0ZXMICQB3b29kX3R5cGUDAG9hawADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:planks", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBsYW5rcwQJAG5hbWVfaGFzaA+7EGxL5oikAwoAbmV0d29ya19pZLYoAAAKBgBzdGF0ZXMICQB3b29kX3R5cGUGAHNwcnVjZQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:planks", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBsYW5rcwQJAG5hbWVfaGFzaA+7EGxL5oikAwoAbmV0d29ya19pZLcoAAAKBgBzdGF0ZXMICQB3b29kX3R5cGUFAGJpcmNoAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:planks", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBsYW5rcwQJAG5hbWVfaGFzaA+7EGxL5oikAwoAbmV0d29ya19pZLgoAAAKBgBzdGF0ZXMICQB3b29kX3R5cGUGAGp1bmdsZQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:planks", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBsYW5rcwQJAG5hbWVfaGFzaA+7EGxL5oikAwoAbmV0d29ya19pZLkoAAAKBgBzdGF0ZXMICQB3b29kX3R5cGUGAGFjYWNpYQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:planks", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBsYW5rcwQJAG5hbWVfaGFzaA+7EGxL5oikAwoAbmV0d29ya19pZLooAAAKBgBzdGF0ZXMICQB3b29kX3R5cGUIAGRhcmtfb2FrAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:mangrove_planks", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX3BsYW5rcwQJAG5hbWVfaGFzaPvLtcEA0F8xAwoAbmV0d29ya19pZAkIAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:cherry_planks", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9wbGFua3MECQBuYW1lX2hhc2hNIvVh/lVW7gMKAG5ldHdvcmtfaWQlMQAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:bamboo_planks", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19wbGFua3MECQBuYW1lX2hhc2gYnjNz7SCCjgMKAG5ldHdvcmtfaWQ/IgAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:bamboo_mosaic", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19tb3NhaWMECQBuYW1lX2hhc2izSEgiMKOp/AMKAG5ldHdvcmtfaWQ1MwAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:crimson_planks", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fcGxhbmtzBAkAbmFtZV9oYXNoJc5IKqNXJnwDCgBuZXR3b3JrX2lkJR8AAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:warped_planks", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9wbGFua3MECQBuYW1lX2hhc2g3yGXEWhe6LgMKAG5ldHdvcmtfaWTsBwAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWTtCAAACgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCwBjb2JibGVzdG9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWTuCAAACgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEQBtb3NzeV9jb2JibGVzdG9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWTvCAAACgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBwBncmFuaXRlCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWTwCAAACgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBwBkaW9yaXRlCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWTxCAAACgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCABhbmRlc2l0ZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWTyCAAACgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCQBzYW5kc3RvbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWT5CAAACgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlDQByZWRfc2FuZHN0b25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWT0CAAACgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCwBzdG9uZV9icmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWT1CAAACgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEQBtb3NzeV9zdG9uZV9icmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWTzCAAACgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBQBicmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWT2CAAACgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlDABuZXRoZXJfYnJpY2sIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWT6CAAACgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEAByZWRfbmV0aGVyX2JyaWNrCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWT3CAAACgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCQBlbmRfYnJpY2sIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWT4CAAACgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCgBwcmlzbWFyaW5lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:blackstone_wall", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmJsYWNrc3RvbmVfd2FsbAQJAG5hbWVfaGFzaMP8XppUSU1RAwoAbmV0d29ya19pZCQYAAAKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:polished_blackstone_wall", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfd2FsbAQJAG5hbWVfaGFzaP6SwV08YwzAAwoAbmV0d29ya19pZGErAAAKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:polished_blackstone_brick_wall", - "block_state_b64": "CgAACAQAbmFtZSgAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfd2FsbAQJAG5hbWVfaGFzaBBIDZbHxiEzAwoAbmV0d29ya19pZBIIAAAKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:cobbled_deepslate_wall", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3dhbGwECQBuYW1lX2hhc2iECY5oKxeT+gMKAG5ldHdvcmtfaWRzMgAACgYAc3RhdGVzCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:deepslate_tile_wall", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3dhbGwECQBuYW1lX2hhc2jz7N+PeuEXgQMKAG5ldHdvcmtfaWQVIAAACgYAc3RhdGVzCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:polished_deepslate_wall", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV93YWxsBAkAbmFtZV9oYXNoHxjTdj9pevMDCgBuZXR3b3JrX2lkZjEAAAoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:deepslate_brick_wall", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja193YWxsBAkAbmFtZV9oYXNoEs3EQrjroyEDCgBuZXR3b3JrX2lkhgQAAAoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:mud_brick_wall", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0Om11ZF9icmlja193YWxsBAkAbmFtZV9oYXNov9b98ATpUSwDCgBuZXR3b3JrX2lkHgcAAAoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:oak_fence", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0Om9ha19mZW5jZQQJAG5hbWVfaGFzaGEmid7AaCWRAwoAbmV0d29ya19pZMAiAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:spruce_fence", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnNwcnVjZV9mZW5jZQQJAG5hbWVfaGFzaPQCm+aX1ZQeAwoAbmV0d29ya19pZGAEAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:birch_fence", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmJpcmNoX2ZlbmNlBAkAbmFtZV9oYXNo6CJ2ATpANfgDCgBuZXR3b3JrX2lkbTIAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:jungle_fence", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0Omp1bmdsZV9mZW5jZQQJAG5hbWVfaGFzaOX4cD9uAmsdAwoAbmV0d29ya19pZFkEAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:acacia_fence", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmFjYWNpYV9mZW5jZQQJAG5hbWVfaGFzaGjn+RlKVDH6AwoAbmV0d29ya19pZHEyAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:dark_oak_fence", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmRhcmtfb2FrX2ZlbmNlBAkAbmFtZV9oYXNoGPj0gCgM0c0DCgBuZXR3b3JrX2lk1iwAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:mangrove_fence", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hbmdyb3ZlX2ZlbmNlBAkAbmFtZV9oYXNowwAd7tPu9bsDCgBuZXR3b3JrX2lkCysAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:cherry_fence", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmNoZXJyeV9mZW5jZQQJAG5hbWVfaGFzaFmtUfHfTxcxAwoAbmV0d29ya19pZAgIAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:bamboo_fence", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJhbWJvb19mZW5jZQQJAG5hbWVfaGFzaCKRbxfXsfkiAwoAbmV0d29ya19pZD0FAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:nether_brick_fence", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0Om5ldGhlcl9icmlja19mZW5jZQQJAG5hbWVfaGFzaA6030ngawxcAwoAbmV0d29ya19pZJQZAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:crimson_fence", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNyaW1zb25fZmVuY2UECQBuYW1lX2hhc2jhUhKv1HGj9AMKAG5ldHdvcmtfaWQZMgAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:warped_fence", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OndhcnBlZF9mZW5jZQQJAG5hbWVfaGFzaJfb3/YuKmOWAwoAbmV0d29ya19pZLkkAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:fence_gate", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmZlbmNlX2dhdGUECQBuYW1lX2hhc2hTxpjEDmRzAwMKAG5ldHdvcmtfaWRPAAAACgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:spruce_fence_gate", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnNwcnVjZV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoanTVB84HRbkDCgBuZXR3b3JrX2lk2ioAAAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:birch_fence_gate", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmJpcmNoX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2jmfPklI8azSwMKAG5ldHdvcmtfaWQRFgAACgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:jungle_fence_gate", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0Omp1bmdsZV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNobYVQkfBomIcDCgBuZXR3b3JrX2lkPSEAAAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:acacia_fence_gate", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmFjYWNpYV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoZnrLUx/XSekDCgBuZXR3b3JrX2lkdDAAAAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:dark_oak_fence_gate", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmRhcmtfb2FrX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2j2PTvdJJHcVQMKAG5ldHdvcmtfaWQXGQAACgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:mangrove_fence_gate", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0Om1hbmdyb3ZlX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2i/kOhBKiI/dAMKAG5ldHdvcmtfaWQbGwAACgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:cherry_fence_gate", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmNoZXJyeV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoKWLgCk0z+PsDCgBuZXR3b3JrX2lkHjMAAAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:bamboo_fence_gate", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmJhbWJvb19mZW5jZV9nYXRlBAkAbmFtZV9oYXNopH1JrUgwdIADCgBuZXR3b3JrX2lk/B8AAAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:crimson_fence_gate", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmNyaW1zb25fZmVuY2VfZ2F0ZQQJAG5hbWVfaGFzaHE3Gfd0Z2d2AwoAbmV0d29ya19pZN8cAAAKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQsAaW5fd2FsbF9iaXQAAQgAb3Blbl9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:warped_fence_gate", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OndhcnBlZF9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoy0oIBjDIG4kDCgBuZXR3b3JrX2lkYCEAAAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:normal_stone_stairs", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0Om5vcm1hbF9zdG9uZV9zdGFpcnMECQBuYW1lX2hhc2hAEktZZOkGIwMKAG5ldHdvcmtfaWQ+BQAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stone_stairs", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnN0b25lX3N0YWlycwQJAG5hbWVfaGFzaNRjqVC5GRVDAwoAbmV0d29ya19pZMcVAAAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:mossy_cobblestone_stairs", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0Om1vc3N5X2NvYmJsZXN0b25lX3N0YWlycwQJAG5hbWVfaGFzaMVSTq5z9n1RAwoAbmV0d29ya19pZMYYAAAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:oak_stairs", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Om9ha19zdGFpcnMECQBuYW1lX2hhc2jk/HFzdXy0FQMKAG5ldHdvcmtfaWS/AgAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:spruce_stairs", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9zdGFpcnMECQBuYW1lX2hhc2iznygw7uBPBQMKAG5ldHdvcmtfaWSFAAAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:birch_stairs", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX3N0YWlycwQJAG5hbWVfaGFzaPfhbL619a3GAwoAbmV0d29ya19pZIMsAAAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:jungle_stairs", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9zdGFpcnMECQBuYW1lX2hhc2jodJsHUbOVxQMKAG5ldHdvcmtfaWRcLAAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:acacia_stairs", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9zdGFpcnMECQBuYW1lX2hhc2h3x1NmD43IqQMKAG5ldHdvcmtfaWRGKQAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:dark_oak_stairs", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX3N0YWlycwQJAG5hbWVfaGFzaMfwkbYPbNmAAwoAbmV0d29ya19pZA0gAAAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:mangrove_stairs", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX3N0YWlycwQJAG5hbWVfaGFzaNpUDY+uGMpyAwoAbmV0d29ya19pZPEaAAAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:cherry_stairs", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9zdGFpcnMECQBuYW1lX2hhc2jMtr0v9JY4zwMKAG5ldHdvcmtfaWQHLQAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:bamboo_stairs", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19zdGFpcnMECQBuYW1lX2hhc2jFOzWL8PalKwMKAG5ldHdvcmtfaWQQBwAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:bamboo_mosaic_stairs", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmJhbWJvb19tb3NhaWNfc3RhaXJzBAkAbmFtZV9oYXNoNLPiveSHPaoDCgBuZXR3b3JrX2lkTikAAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stone_brick_stairs", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnN0b25lX2JyaWNrX3N0YWlycwQJAG5hbWVfaGFzaN6tQViRo5cwAwoAbmV0d29ya19pZPgHAAAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:mossy_stone_brick_stairs", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0Om1vc3N5X3N0b25lX2JyaWNrX3N0YWlycwQJAG5hbWVfaGFzaIB/Zv5YBPuYAwoAbmV0d29ya19pZGcmAAAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:sandstone_stairs", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnNhbmRzdG9uZV9zdGFpcnMECQBuYW1lX2hhc2hOyA0BoYUOPQMKAG5ldHdvcmtfaWRIFQAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:smooth_sandstone_stairs", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnNtb290aF9zYW5kc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNoB+CuCd8Ruz8DCgBuZXR3b3JrX2lkdhUAAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:red_sandstone_stairs", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNoPs0LpHPL24YDCgBuZXR3b3JrX2lkLiEAAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:smooth_red_sandstone_stairs", - "block_state_b64": "CgAACAQAbmFtZSUAbWluZWNyYWZ0OnNtb290aF9yZWRfc2FuZHN0b25lX3N0YWlycwQJAG5hbWVfaGFzaBvjtQv5pf+MAwoAbmV0d29ya19pZPQhAAAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:granite_stairs", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmdyYW5pdGVfc3RhaXJzBAkAbmFtZV9oYXNoGzpvtoqKQjgDCgBuZXR3b3JrX2lklRMAAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:polished_granite_stairs", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2dyYW5pdGVfc3RhaXJzBAkAbmFtZV9oYXNo3PvbSfEQklIDCgBuZXR3b3JrX2lkABkAAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:diorite_stairs", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmRpb3JpdGVfc3RhaXJzBAkAbmFtZV9oYXNoi73T8VQuZmcDCgBuZXR3b3JrX2lkIBoAAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:polished_diorite_stairs", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2Rpb3JpdGVfc3RhaXJzBAkAbmFtZV9oYXNoFKRJd5Wk5L0DCgBuZXR3b3JrX2lkUSsAAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:andesite_stairs", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmFuZGVzaXRlX3N0YWlycwQJAG5hbWVfaGFzaO5w2FKBw76EAwoAbmV0d29ya19pZBIhAAAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:polished_andesite_stairs", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2FuZGVzaXRlX3N0YWlycwQJAG5hbWVfaGFzaNcZZ/zmLInIAwoAbmV0d29ya19pZJ0sAAAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:brick_stairs", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJyaWNrX3N0YWlycwQJAG5hbWVfaGFzaMyt+cRDk5O2AwoAbmV0d29ya19pZKQqAAAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:nether_brick_stairs", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0Om5ldGhlcl9icmlja19zdGFpcnMECQBuYW1lX2hhc2jRqIoOXgifBAMKAG5ldHdvcmtfaWRtAAAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:red_nether_brick_stairs", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnJlZF9uZXRoZXJfYnJpY2tfc3RhaXJzBAkAbmFtZV9oYXNogQvosSbcj7kDCgBuZXR3b3JrX2lk7CoAAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:end_brick_stairs", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmVuZF9icmlja19zdGFpcnMECQBuYW1lX2hhc2hmlAk+QhsUsQMKAG5ldHdvcmtfaWQLKgAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:quartz_stairs", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnF1YXJ0el9zdGFpcnMECQBuYW1lX2hhc2hmvpvOqGi6egMKAG5ldHdvcmtfaWRRHQAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:smooth_quartz_stairs", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnNtb290aF9xdWFydHpfc3RhaXJzBAkAbmFtZV9oYXNoNZZ9rX0qZOsDCgBuZXR3b3JrX2lk6DAAAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:purpur_stairs", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnB1cl9zdGFpcnMECQBuYW1lX2hhc2ifwDxeezXD7gMKAG5ldHdvcmtfaWQnMQAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:prismarine_stairs", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnByaXNtYXJpbmVfc3RhaXJzBAkAbmFtZV9oYXNooTHSZ+IrYtcDCgBuZXR3b3JrX2lkMC8AAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:dark_prismarine_stairs", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmRhcmtfcHJpc21hcmluZV9zdGFpcnMECQBuYW1lX2hhc2hIciLmam4o4AMKAG5ldHdvcmtfaWTXLwAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:prismarine_bricks_stairs", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnByaXNtYXJpbmVfYnJpY2tzX3N0YWlycwQJAG5hbWVfaGFzaNIjq1oBlZMMAwoAbmV0d29ya19pZGUCAAAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:crimson_stairs", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fc3RhaXJzBAkAbmFtZV9oYXNoZJqIzCBpCq4DCgBuZXR3b3JrX2lkpSkAAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:warped_stairs", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9zdGFpcnMECQBuYW1lX2hhc2hOkY27jLD4RQMKAG5ldHdvcmtfaWTRFQAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:blackstone_stairs", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmJsYWNrc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNokdoUb76p9McDCgBuZXR3b3JrX2lkkywAAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:polished_blackstone_stairs", - "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNolCFtFIE8MmADCgBuZXR3b3JrX2lkvBkAAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:polished_blackstone_brick_stairs", - "block_state_b64": "CgAACAQAbmFtZSoAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfc3RhaXJzBAkAbmFtZV9oYXNonks6UlfpOmkDCgBuZXR3b3JrX2lkehoAAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:cut_copper_stairs", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmN1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoHfoAXYq5G3MDCgBuZXR3b3JrX2lk+hoAAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:exposed_cut_copper_stairs", - "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcl9zdGFpcnMECQBuYW1lX2hhc2howneQGtZ9cgMKAG5ldHdvcmtfaWTpGgAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:weathered_cut_copper_stairs", - "block_state_b64": "CgAACAQAbmFtZSUAbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyX3N0YWlycwQJAG5hbWVfaGFzaP+R5loXxrVgAwoAbmV0d29ya19pZMQZAAAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:oxidized_cut_copper_stairs", - "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNo6Jeoq5rsPxsDCgBuZXR3b3JrX2lkNAQAAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:waxed_cut_copper_stairs", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoh07CQj0/SR8DCgBuZXR3b3JrX2lkYgQAAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:waxed_exposed_cut_copper_stairs", - "block_state_b64": "CgAACAQAbmFtZSkAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcl9zdGFpcnMECQBuYW1lX2hhc2guVct1ilmxTwMKAG5ldHdvcmtfaWQIGAAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:waxed_weathered_cut_copper_stairs", - "block_state_b64": "CgAACAQAbmFtZSsAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyX3N0YWlycwQJAG5hbWVfaGFzaPXC8Sz/phCpAwoAbmV0d29ya19pZCUpAAAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:waxed_oxidized_cut_copper_stairs", - "block_state_b64": "CgAACAQAbmFtZSoAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoaqGdkuhxVZUDCgBuZXR3b3JrX2lkoCQAAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:cobbled_deepslate_stairs", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3N0YWlycwQJAG5hbWVfaGFzaPIfa+TpyJcIAwoAbmV0d29ya19pZCkCAAAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:deepslate_tile_stairs", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3N0YWlycwQJAG5hbWVfaGFzaGFRFzB72mN2AwoAbmV0d29ya19pZNccAAAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:polished_deepslate_stairs", - "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV9zdGFpcnMECQBuYW1lX2hhc2iNCYxVik9sGAMKAG5ldHdvcmtfaWT4AwAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:deepslate_brick_stairs", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja19zdGFpcnMECQBuYW1lX2hhc2hIasOahEf83wMKAG5ldHdvcmtfaWTPLwAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:mud_brick_stairs", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0Om11ZF9icmlja19zdGFpcnMECQBuYW1lX2hhc2gt3qxK1NWajAMKAG5ldHdvcmtfaWTcIQAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:wooden_door" - }, - { - "id": "minecraft:spruce_door" - }, - { - "id": "minecraft:birch_door" - }, - { - "id": "minecraft:jungle_door" - }, - { - "id": "minecraft:acacia_door" - }, - { - "id": "minecraft:dark_oak_door" - }, - { - "id": "minecraft:mangrove_door" - }, - { - "id": "minecraft:cherry_door" - }, - { - "id": "minecraft:bamboo_door" - }, - { - "id": "minecraft:iron_door" - }, - { - "id": "minecraft:crimson_door" - }, - { - "id": "minecraft:warped_door" - }, - { - "id": "minecraft:trapdoor", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OnRyYXBkb29yBAkAbmFtZV9oYXNotYiAJGtN0xADCgBuZXR3b3JrX2lkgQIAAAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:spruce_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnNwcnVjZV90cmFwZG9vcgQJAG5hbWVfaGFzaOwlfbgBkUW4AwoAbmV0d29ya19pZLoqAAAKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:birch_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmJpcmNoX3RyYXBkb29yBAkAbmFtZV9oYXNoSLtLweOLJ7wDCgBuZXR3b3JrX2lkHCsAAAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:jungle_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Omp1bmdsZV90cmFwZG9vcgQJAG5hbWVfaGFzaDP/TnM9wyCIAwoAbmV0d29ya19pZE0hAAAKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:acacia_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmFjYWNpYV90cmFwZG9vcgQJAG5hbWVfaGFzaMj8xi3vmEKOAwoAbmV0d29ya19pZB8iAAAKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:dark_oak_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmRhcmtfb2FrX3RyYXBkb29yBAkAbmFtZV9oYXNomB2GGJQ2aOMDCgBuZXR3b3JrX2lkIDAAAAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:mangrove_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0Om1hbmdyb3ZlX3RyYXBkb29yBAkAbmFtZV9oYXNooV3kQsQUUmkDCgBuZXR3b3JrX2lkghoAAAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:cherry_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmNoZXJyeV90cmFwZG9vcgQJAG5hbWVfaGFzaH/PefpfdHgtAwoAbmV0d29ya19pZNIHAAAKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:bamboo_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmJhbWJvb190cmFwZG9vcgQJAG5hbWVfaGFzaJrEOpsTwtKCAwoAbmV0d29ya19pZNUgAAAKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:iron_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Omlyb25fdHJhcGRvb3IECQBuYW1lX2hhc2gwA+IumsEiGQMKAG5ldHdvcmtfaWQUBAAACgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAEPAHVwc2lkZV9kb3duX2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:crimson_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNyaW1zb25fdHJhcGRvb3IECQBuYW1lX2hhc2jHXufTnwUkYgMKAG5ldHdvcmtfaWTjGQAACgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAEPAHVwc2lkZV9kb3duX2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:warped_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OndhcnBlZF90cmFwZG9vcgQJAG5hbWVfaGFzaA20wG/+vkd6AwoAbmV0d29ya19pZC8dAAAKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:iron_bars", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0Omlyb25fYmFycwQJAG5hbWVfaGFzaPuefWSNAe56AwoAbmV0d29ya19pZHMdAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:glass", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmdsYXNzBAkAbmFtZV9oYXNowGJByfWff6gDCgBuZXR3b3JrX2lkIikAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stained_glass", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnN0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2gZNhYJXm9IMwMKAG5ldHdvcmtfaWS0CAAACgYAc3RhdGVzCAUAY29sb3IFAHdoaXRlAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stained_glass", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnN0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2gZNhYJXm9IMwMKAG5ldHdvcmtfaWS8CAAACgYAc3RhdGVzCAUAY29sb3IGAHNpbHZlcgADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stained_glass", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnN0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2gZNhYJXm9IMwMKAG5ldHdvcmtfaWS7CAAACgYAc3RhdGVzCAUAY29sb3IEAGdyYXkAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stained_glass", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnN0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2gZNhYJXm9IMwMKAG5ldHdvcmtfaWTDCAAACgYAc3RhdGVzCAUAY29sb3IFAGJsYWNrAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stained_glass", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnN0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2gZNhYJXm9IMwMKAG5ldHdvcmtfaWTACAAACgYAc3RhdGVzCAUAY29sb3IFAGJyb3duAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stained_glass", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnN0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2gZNhYJXm9IMwMKAG5ldHdvcmtfaWTCCAAACgYAc3RhdGVzCAUAY29sb3IDAHJlZAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stained_glass", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnN0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2gZNhYJXm9IMwMKAG5ldHdvcmtfaWS1CAAACgYAc3RhdGVzCAUAY29sb3IGAG9yYW5nZQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stained_glass", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnN0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2gZNhYJXm9IMwMKAG5ldHdvcmtfaWS4CAAACgYAc3RhdGVzCAUAY29sb3IGAHllbGxvdwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stained_glass", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnN0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2gZNhYJXm9IMwMKAG5ldHdvcmtfaWS5CAAACgYAc3RhdGVzCAUAY29sb3IEAGxpbWUAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stained_glass", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnN0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2gZNhYJXm9IMwMKAG5ldHdvcmtfaWTBCAAACgYAc3RhdGVzCAUAY29sb3IFAGdyZWVuAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stained_glass", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnN0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2gZNhYJXm9IMwMKAG5ldHdvcmtfaWS9CAAACgYAc3RhdGVzCAUAY29sb3IEAGN5YW4AAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stained_glass", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnN0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2gZNhYJXm9IMwMKAG5ldHdvcmtfaWS3CAAACgYAc3RhdGVzCAUAY29sb3IKAGxpZ2h0X2JsdWUAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stained_glass", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnN0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2gZNhYJXm9IMwMKAG5ldHdvcmtfaWS/CAAACgYAc3RhdGVzCAUAY29sb3IEAGJsdWUAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stained_glass", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnN0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2gZNhYJXm9IMwMKAG5ldHdvcmtfaWS+CAAACgYAc3RhdGVzCAUAY29sb3IGAHB1cnBsZQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stained_glass", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnN0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2gZNhYJXm9IMwMKAG5ldHdvcmtfaWS2CAAACgYAc3RhdGVzCAUAY29sb3IHAG1hZ2VudGEAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stained_glass", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnN0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2gZNhYJXm9IMwMKAG5ldHdvcmtfaWS6CAAACgYAc3RhdGVzCAUAY29sb3IEAHBpbmsAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:tinted_glass", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnRpbnRlZF9nbGFzcwQJAG5hbWVfaGFzaAFZWSamk6KdAwoAbmV0d29ya19pZMcmAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:glass_pane", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmdsYXNzX3BhbmUECQBuYW1lX2hhc2gRSBHwNMQ4gQMKAG5ldHdvcmtfaWS3IAAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnN0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaLb5lzurQ119AwoAbmV0d29ya19pZCcfAAAKBgBzdGF0ZXMIBQBjb2xvcgUAd2hpdGUAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnN0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaLb5lzurQ119AwoAbmV0d29ya19pZC8fAAAKBgBzdGF0ZXMIBQBjb2xvcgYAc2lsdmVyAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnN0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaLb5lzurQ119AwoAbmV0d29ya19pZC4fAAAKBgBzdGF0ZXMIBQBjb2xvcgQAZ3JheQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnN0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaLb5lzurQ119AwoAbmV0d29ya19pZDYfAAAKBgBzdGF0ZXMIBQBjb2xvcgUAYmxhY2sAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnN0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaLb5lzurQ119AwoAbmV0d29ya19pZDMfAAAKBgBzdGF0ZXMIBQBjb2xvcgUAYnJvd24AAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnN0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaLb5lzurQ119AwoAbmV0d29ya19pZDUfAAAKBgBzdGF0ZXMIBQBjb2xvcgMAcmVkAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnN0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaLb5lzurQ119AwoAbmV0d29ya19pZCgfAAAKBgBzdGF0ZXMIBQBjb2xvcgYAb3JhbmdlAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnN0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaLb5lzurQ119AwoAbmV0d29ya19pZCsfAAAKBgBzdGF0ZXMIBQBjb2xvcgYAeWVsbG93AAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnN0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaLb5lzurQ119AwoAbmV0d29ya19pZCwfAAAKBgBzdGF0ZXMIBQBjb2xvcgQAbGltZQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnN0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaLb5lzurQ119AwoAbmV0d29ya19pZDQfAAAKBgBzdGF0ZXMIBQBjb2xvcgUAZ3JlZW4AAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnN0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaLb5lzurQ119AwoAbmV0d29ya19pZDAfAAAKBgBzdGF0ZXMIBQBjb2xvcgQAY3lhbgADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnN0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaLb5lzurQ119AwoAbmV0d29ya19pZCofAAAKBgBzdGF0ZXMIBQBjb2xvcgoAbGlnaHRfYmx1ZQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnN0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaLb5lzurQ119AwoAbmV0d29ya19pZDIfAAAKBgBzdGF0ZXMIBQBjb2xvcgQAYmx1ZQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnN0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaLb5lzurQ119AwoAbmV0d29ya19pZDEfAAAKBgBzdGF0ZXMIBQBjb2xvcgYAcHVycGxlAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnN0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaLb5lzurQ119AwoAbmV0d29ya19pZCkfAAAKBgBzdGF0ZXMIBQBjb2xvcgcAbWFnZW50YQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnN0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaLb5lzurQ119AwoAbmV0d29ya19pZC0fAAAKBgBzdGF0ZXMIBQBjb2xvcgQAcGluawADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:ladder", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmxhZGRlcgQJAG5hbWVfaGFzaKBhqheJVOz+AwoAbmV0d29ya19pZDozAAAKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:scaffolding", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnNjYWZmb2xkaW5nBAkAbmFtZV9oYXNoYrkevrqcljwDCgBuZXR3b3JrX2lkOBUAAAoGAHN0YXRlcwMJAHN0YWJpbGl0eQAAAAABDwBzdGFiaWxpdHlfY2hlY2sAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stone_block_slab", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWR+GQAACgYAc3RhdGVzCA8Ac3RvbmVfc2xhYl90eXBlDABzbW9vdGhfc3RvbmUBDAB0b3Bfc2xvdF9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stone_block_slab4", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkCiMAAAoGAHN0YXRlcwgRAHN0b25lX3NsYWJfdHlwZV80BQBzdG9uZQEMAHRvcF9zbG90X2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stone_block_slab", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWSBGQAACgYAc3RhdGVzCA8Ac3RvbmVfc2xhYl90eXBlCwBjb2JibGVzdG9uZQEMAHRvcF9zbG90X2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stone_block_slab2", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lk7SIAAAoGAHN0YXRlcwgRAHN0b25lX3NsYWJfdHlwZV8yEQBtb3NzeV9jb2JibGVzdG9uZQEMAHRvcF9zbG90X2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:wooden_slab", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lk7CAAAAoGAHN0YXRlcwEMAHRvcF9zbG90X2JpdAAICQB3b29kX3R5cGUDAG9hawADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:wooden_slab", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lk7SAAAAoGAHN0YXRlcwEMAHRvcF9zbG90X2JpdAAICQB3b29kX3R5cGUGAHNwcnVjZQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:wooden_slab", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lk7iAAAAoGAHN0YXRlcwEMAHRvcF9zbG90X2JpdAAICQB3b29kX3R5cGUFAGJpcmNoAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:wooden_slab", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lk7yAAAAoGAHN0YXRlcwEMAHRvcF9zbG90X2JpdAAICQB3b29kX3R5cGUGAGp1bmdsZQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:wooden_slab", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lk8CAAAAoGAHN0YXRlcwEMAHRvcF9zbG90X2JpdAAICQB3b29kX3R5cGUGAGFjYWNpYQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:wooden_slab", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lk8SAAAAoGAHN0YXRlcwEMAHRvcF9zbG90X2JpdAAICQB3b29kX3R5cGUIAGRhcmtfb2FrAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:mangrove_slab", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Om1hbmdyb3ZlX3NsYWIECQBuYW1lX2hhc2jYCcmhJPeNMwMKAG5ldHdvcmtfaWTECAAACgYAc3RhdGVzAQwAdG9wX3Nsb3RfYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:cherry_slab", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNoZXJyeV9zbGFiBAkAbmFtZV9oYXNoTt0MmVn/mqoDCgBuZXR3b3JrX2lkZykAAAoGAHN0YXRlcwEMAHRvcF9zbG90X2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:bamboo_slab", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmJhbWJvb19zbGFiBAkAbmFtZV9oYXNoo1xuFqINeLYDCgBuZXR3b3JrX2lkoioAAAoGAHN0YXRlcwEMAHRvcF9zbG90X2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:bamboo_mosaic_slab", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmJhbWJvb19tb3NhaWNfc2xhYgQJAG5hbWVfaGFzaNbVRBZ/ChI3AwoAbmV0d29ya19pZNERAAAKBgBzdGF0ZXMBDAB0b3Bfc2xvdF9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stone_block_slab", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWSDGQAACgYAc3RhdGVzCA8Ac3RvbmVfc2xhYl90eXBlCwBzdG9uZV9icmljawEMAHRvcF9zbG90X2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stone_block_slab4", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkCCMAAAoGAHN0YXRlcwgRAHN0b25lX3NsYWJfdHlwZV80EQBtb3NzeV9zdG9uZV9icmljawEMAHRvcF9zbG90X2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stone_block_slab", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWR/GQAACgYAc3RhdGVzCA8Ac3RvbmVfc2xhYl90eXBlCQBzYW5kc3RvbmUBDAB0b3Bfc2xvdF9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stone_block_slab4", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkCyMAAAoGAHN0YXRlcwgRAHN0b25lX3NsYWJfdHlwZV80DQBjdXRfc2FuZHN0b25lAQwAdG9wX3Nsb3RfYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stone_block_slab2", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lk7iIAAAoGAHN0YXRlcwgRAHN0b25lX3NsYWJfdHlwZV8yEABzbW9vdGhfc2FuZHN0b25lAQwAdG9wX3Nsb3RfYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stone_block_slab2", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lk6CIAAAoGAHN0YXRlcwgRAHN0b25lX3NsYWJfdHlwZV8yDQByZWRfc2FuZHN0b25lAQwAdG9wX3Nsb3RfYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stone_block_slab4", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkDCMAAAoGAHN0YXRlcwgRAHN0b25lX3NsYWJfdHlwZV80EQBjdXRfcmVkX3NhbmRzdG9uZQEMAHRvcF9zbG90X2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stone_block_slab3", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lk+SIAAAoGAHN0YXRlcwgRAHN0b25lX3NsYWJfdHlwZV8zFABzbW9vdGhfcmVkX3NhbmRzdG9uZQEMAHRvcF9zbG90X2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stone_block_slab3", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lk/iIAAAoGAHN0YXRlcwgRAHN0b25lX3NsYWJfdHlwZV8zBwBncmFuaXRlAQwAdG9wX3Nsb3RfYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stone_block_slab3", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lk/yIAAAoGAHN0YXRlcwgRAHN0b25lX3NsYWJfdHlwZV8zEABwb2xpc2hlZF9ncmFuaXRlAQwAdG9wX3Nsb3RfYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stone_block_slab3", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lk/CIAAAoGAHN0YXRlcwgRAHN0b25lX3NsYWJfdHlwZV8zBwBkaW9yaXRlAQwAdG9wX3Nsb3RfYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stone_block_slab3", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lk/SIAAAoGAHN0YXRlcwgRAHN0b25lX3NsYWJfdHlwZV8zEABwb2xpc2hlZF9kaW9yaXRlAQwAdG9wX3Nsb3RfYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stone_block_slab3", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lk+yIAAAoGAHN0YXRlcwgRAHN0b25lX3NsYWJfdHlwZV8zCABhbmRlc2l0ZQEMAHRvcF9zbG90X2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stone_block_slab3", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lk+iIAAAoGAHN0YXRlcwgRAHN0b25lX3NsYWJfdHlwZV8zEQBwb2xpc2hlZF9hbmRlc2l0ZQEMAHRvcF9zbG90X2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stone_block_slab", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWSCGQAACgYAc3RhdGVzCA8Ac3RvbmVfc2xhYl90eXBlBQBicmljawEMAHRvcF9zbG90X2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stone_block_slab", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWSFGQAACgYAc3RhdGVzCA8Ac3RvbmVfc2xhYl90eXBlDABuZXRoZXJfYnJpY2sBDAB0b3Bfc2xvdF9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stone_block_slab2", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lk7yIAAAoGAHN0YXRlcwgRAHN0b25lX3NsYWJfdHlwZV8yEAByZWRfbmV0aGVyX2JyaWNrAQwAdG9wX3Nsb3RfYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stone_block_slab3", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lk+CIAAAoGAHN0YXRlcwgRAHN0b25lX3NsYWJfdHlwZV8zDwBlbmRfc3RvbmVfYnJpY2sBDAB0b3Bfc2xvdF9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stone_block_slab", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWSEGQAACgYAc3RhdGVzCA8Ac3RvbmVfc2xhYl90eXBlBgBxdWFydHoBDAB0b3Bfc2xvdF9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stone_block_slab4", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkCSMAAAoGAHN0YXRlcwgRAHN0b25lX3NsYWJfdHlwZV80DQBzbW9vdGhfcXVhcnR6AQwAdG9wX3Nsb3RfYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stone_block_slab2", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lk6SIAAAoGAHN0YXRlcwgRAHN0b25lX3NsYWJfdHlwZV8yBgBwdXJwdXIBDAB0b3Bfc2xvdF9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stone_block_slab2", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lk6iIAAAoGAHN0YXRlcwgRAHN0b25lX3NsYWJfdHlwZV8yEABwcmlzbWFyaW5lX3JvdWdoAQwAdG9wX3Nsb3RfYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stone_block_slab2", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lk6yIAAAoGAHN0YXRlcwgRAHN0b25lX3NsYWJfdHlwZV8yDwBwcmlzbWFyaW5lX2RhcmsBDAB0b3Bfc2xvdF9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stone_block_slab2", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lk7CIAAAoGAHN0YXRlcwgRAHN0b25lX3NsYWJfdHlwZV8yEABwcmlzbWFyaW5lX2JyaWNrAQwAdG9wX3Nsb3RfYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:crimson_slab", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmNyaW1zb25fc2xhYgQJAG5hbWVfaGFzaKZ+EfP0ZYOZAwoAbmV0d29ya19pZHkmAAAKBgBzdGF0ZXMBDAB0b3Bfc2xvdF9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:warped_slab", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OndhcnBlZF9zbGFiBAkAbmFtZV9oYXNo/AT0e/Z9W7UDCgBuZXR3b3JrX2lkfSoAAAoGAHN0YXRlcwEMAHRvcF9zbG90X2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:blackstone_slab", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmJsYWNrc3RvbmVfc2xhYgQJAG5hbWVfaGFzaF/DD4ZUlNgtAwoAbmV0d29ya19pZOIHAAAKBgBzdGF0ZXMBDAB0b3Bfc2xvdF9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:polished_blackstone_slab", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfc2xhYgQJAG5hbWVfaGFzaDYnuUs86EWfAwoAbmV0d29ya19pZHMoAAAKBgBzdGF0ZXMBDAB0b3Bfc2xvdF9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:polished_blackstone_brick_slab", - "block_state_b64": "CgAACAQAbmFtZSgAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfc2xhYgQJAG5hbWVfaGFzaKySLqvHc4xXAwoAbmV0d29ya19pZC0ZAAAKBgBzdGF0ZXMBDAB0b3Bfc2xvdF9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:cut_copper_slab", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmN1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaDsNpb2qs4iBAwoAbmV0d29ya19pZLkgAAAKBgBzdGF0ZXMBDAB0b3Bfc2xvdF9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:exposed_cut_copper_slab", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcl9zbGFiBAkAbmFtZV9oYXNoahQ5OwIQb7kDCgBuZXR3b3JrX2lk6ioAAAoGAHN0YXRlcwEMAHRvcF9zbG90X2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:weathered_cut_copper_slab", - "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyX3NsYWIECQBuYW1lX2hhc2hBIuGIOVVXogMKAG5ldHdvcmtfaWSiKAAACgYAc3RhdGVzAQwAdG9wX3Nsb3RfYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:oxidized_cut_copper_slab", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaOptj9ycfpaDAwoAbmV0d29ya19pZPggAAAKBgBzdGF0ZXMBDAB0b3Bfc2xvdF9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:waxed_cut_copper_slab", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaAlx6DZOCTHzAwoAbmV0d29ya19pZGQxAAAKBgBzdGF0ZXMBDAB0b3Bfc2xvdF9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:waxed_exposed_cut_copper_slab", - "block_state_b64": "CgAACAQAbmFtZScAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcl9zbGFiBAkAbmFtZV9oYXNo3KqS5OnhtRIDCgBuZXR3b3JrX2lklQIAAAoGAHN0YXRlcwEMAHRvcF9zbG90X2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:waxed_weathered_cut_copper_slab", - "block_state_b64": "CgAACAQAbmFtZSkAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyX3NsYWIECQBuYW1lX2hhc2gzZ1oX0HCFtwMKAG5ldHdvcmtfaWSzKgAACgYAc3RhdGVzAQwAdG9wX3Nsb3RfYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:waxed_oxidized_cut_copper_slab", - "block_state_b64": "CgAACAQAbmFtZSgAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaMjjTnLu1KcqAwoAbmV0d29ya19pZAAHAAAKBgBzdGF0ZXMBDAB0b3Bfc2xvdF9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:cobbled_deepslate_slab", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3NsYWIECQBuYW1lX2hhc2gwJIVWK1TM2QMKAG5ldHdvcmtfaWRiLwAACgYAc3RhdGVzAQwAdG9wX3Nsb3RfYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:polished_deepslate_slab", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV9zbGFiBAkAbmFtZV9oYXNoC/Adiz8k6RYDCgBuZXR3b3JrX2lk0gIAAAoGAHN0YXRlcwEMAHRvcF9zbG90X2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:deepslate_tile_slab", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3NsYWIECQBuYW1lX2hhc2hPydV6emzIXAMKAG5ldHdvcmtfaWSVGQAACgYAc3RhdGVzAQwAdG9wX3Nsb3RfYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:deepslate_brick_slab", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja19zbGFiBAkAbmFtZV9oYXNoSv62V7iw10UDCgBuZXR3b3JrX2lkzxUAAAoGAHN0YXRlcwEMAHRvcF9zbG90X2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:mud_brick_slab", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0Om11ZF9icmlja19zbGFiBAkAbmFtZV9oYXNoq/tGBQWkv08DCgBuZXR3b3JrX2lkEBgAAAoGAHN0YXRlcwEMAHRvcF9zbG90X2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:brick_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmJyaWNrX2Jsb2NrBAkAbmFtZV9oYXNo5Qc2E005S3oDCgBuZXR3b3JrX2lkTx0AAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:chiseled_nether_bricks", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmNoaXNlbGVkX25ldGhlcl9icmlja3MECQBuYW1lX2hhc2g31SBPTcUK1QMKAG5ldHdvcmtfaWQcLwAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:cracked_nether_bricks", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmNyYWNrZWRfbmV0aGVyX2JyaWNrcwQJAG5hbWVfaGFzaAdC6eKzXT5tAwoAbmV0d29ya19pZMUaAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:quartz_bricks", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnF1YXJ0el9icmlja3MECQBuYW1lX2hhc2jSZO590dd8sAMKAG5ldHdvcmtfaWTsKQAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stonebrick", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWS1KgAACgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQcAZGVmYXVsdAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stonebrick", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWS2KgAACgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQUAbW9zc3kAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stonebrick", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWS3KgAACgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQcAY3JhY2tlZAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stonebrick", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWS4KgAACgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQgAY2hpc2VsZWQAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:end_bricks", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmVuZF9icmlja3MECQBuYW1lX2hhc2hIUFfxNLZaFgMKAG5ldHdvcmtfaWTKAgAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:prismarine", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnByaXNtYXJpbmUECQBuYW1lX2hhc2jcnQCHi9CspQMKAG5ldHdvcmtfaWTVKAAACgYAc3RhdGVzCBUAcHJpc21hcmluZV9ibG9ja190eXBlBgBicmlja3MAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:polished_blackstone_bricks", - "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tzBAkAbmFtZV9oYXNoIHgsgIdzKXcDCgBuZXR3b3JrX2lk8hwAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:cracked_polished_blackstone_bricks", - "block_state_b64": "CgAACAQAbmFtZSwAbWluZWNyYWZ0OmNyYWNrZWRfcG9saXNoZWRfYmxhY2tzdG9uZV9icmlja3MECQBuYW1lX2hhc2jQIO1GQDk80AMKAG5ldHdvcmtfaWTpLgAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:gilded_blackstone", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmdpbGRlZF9ibGFja3N0b25lBAkAbmFtZV9oYXNoNoWt1ocG0HEDCgBuZXR3b3JrX2lk6BoAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:chiseled_polished_blackstone", - "block_state_b64": "CgAACAQAbmFtZSYAbWluZWNyYWZ0OmNoaXNlbGVkX3BvbGlzaGVkX2JsYWNrc3RvbmUECQBuYW1lX2hhc2gzFa+kEjCJgAMKAG5ldHdvcmtfaWQMIAAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:deepslate_tiles", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlcwQJAG5hbWVfaGFzaGcLLx3NXAFvAwoAbmV0d29ya19pZOIaAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:cracked_deepslate_tiles", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmNyYWNrZWRfZGVlcHNsYXRlX3RpbGVzBAkAbmFtZV9oYXNo9zWgkFuMM1QDCgBuZXR3b3JrX2lkChkAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:deepslate_bricks", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja3MECQBuYW1lX2hhc2gucvFmPdZxigMKAG5ldHdvcmtfaWShIQAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:cracked_deepslate_bricks", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OmNyYWNrZWRfZGVlcHNsYXRlX2JyaWNrcwQJAG5hbWVfaGFzaN40aqhh9WqHAwoAbmV0d29ya19pZDwhAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:chiseled_deepslate", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmNoaXNlbGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaEU7/uRG8HSBAwoAbmV0d29ya19pZLggAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:cobblestone", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvYmJsZXN0b25lBAkAbmFtZV9oYXNoPoK7mGlSUz4DCgBuZXR3b3JrX2lkZxUAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:mossy_cobblestone", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0Om1vc3N5X2NvYmJsZXN0b25lBAkAbmFtZV9oYXNoGJ67FCbkChMDCgBuZXR3b3JrX2lkmAIAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:cobbled_deepslate", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlBAkAbmFtZV9oYXNoLUz9Y/ywmLwDCgBuZXR3b3JrX2lkMCsAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:smooth_stone", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnNtb290aF9zdG9uZQQJAG5hbWVfaGFzaMwf87/JaTNvAwoAbmV0d29ya19pZOMaAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:sandstone", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZJAVAAAKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGUHAGRlZmF1bHQAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:sandstone", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZJEVAAAKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGULAGhlaXJvZ2x5cGhzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:sandstone", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZJIVAAAKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGUDAGN1dAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:sandstone", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZJMVAAAKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGUGAHNtb290aAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:red_sandstone", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWTWKgAACgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlBwBkZWZhdWx0AAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:red_sandstone", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWTXKgAACgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlCwBoZWlyb2dseXBocwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:red_sandstone", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWTYKgAACgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlAwBjdXQAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:red_sandstone", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWTZKgAACgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlBgBzbW9vdGgAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:coal_block", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmNvYWxfYmxvY2sECQBuYW1lX2hhc2jH8QQP3t5PiAMKAG5ldHdvcmtfaWReIQAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:dried_kelp_block", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmRyaWVkX2tlbHBfYmxvY2sECQBuYW1lX2hhc2iRoucexkrl8wMKAG5ldHdvcmtfaWQIMgAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:gold_block", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmdvbGRfYmxvY2sECQBuYW1lX2hhc2iYLshvjtXzFwMKAG5ldHdvcmtfaWT1AgAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:iron_block", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Omlyb25fYmxvY2sECQBuYW1lX2hhc2jYINmJQbvV/gMKAG5ldHdvcmtfaWQ5MwAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:copper_block", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmNvcHBlcl9ibG9jawQJAG5hbWVfaGFzaDVxnehsGaZ1AwoAbmV0d29ya19pZNUcAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:exposed_copper", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmV4cG9zZWRfY29wcGVyBAkAbmFtZV9oYXNoQH3Fukmu3CEDCgBuZXR3b3JrX2lkKgUAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:weathered_copper", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OndlYXRoZXJlZF9jb3BwZXIECQBuYW1lX2hhc2hJCQXbvobv+gMKAG5ldHdvcmtfaWQXMwAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:oxidized_copper", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om94aWRpemVkX2NvcHBlcgQJAG5hbWVfaGFzaMDtJqR0G5Y7AwoAbmV0d29ya19pZCYVAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:waxed_copper", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OndheGVkX2NvcHBlcgQJAG5hbWVfaGFzaPF+FG6Eh5fsAwoAbmV0d29ya19pZBAxAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:waxed_exposed_copper", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY29wcGVyBAkAbmFtZV9oYXNoig8IOc+SCikDCgBuZXR3b3JrX2lk8gYAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:waxed_weathered_copper", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jb3BwZXIECQBuYW1lX2hhc2gjtPq8MOdvKgMKAG5ldHdvcmtfaWT/BgAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:waxed_oxidized_copper", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OndheGVkX294aWRpemVkX2NvcHBlcgQJAG5hbWVfaGFzaMaORhsO+LzjAwoAbmV0d29ya19pZEgwAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:cut_copper", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmN1dF9jb3BwZXIECQBuYW1lX2hhc2hAfN3NGax3eAMKAG5ldHdvcmtfaWT7HAAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:exposed_cut_copper", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcgQJAG5hbWVfaGFzaA85G3yv/w6pAwoAbmV0d29ya19pZCQpAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:weathered_cut_copper", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyBAkAbmFtZV9oYXNoVgRV0fBaz88DCgBuZXR3b3JrX2lk2C4AAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:oxidized_cut_copper", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2iP8WmFWOkriwMKAG5ldHdvcmtfaWSvIQAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:waxed_cut_copper", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2jumiwOZIqv2AMKAG5ldHdvcmtfaWRRLwAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:waxed_exposed_cut_copper", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcgQJAG5hbWVfaGFzaPE/OfK6IoVMAwoAbmV0d29ya19pZDEWAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:waxed_weathered_cut_copper", - "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyBAkAbmFtZV9oYXNoCA1xDp11bnwDCgBuZXR3b3JrX2lkJh8AAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:waxed_oxidized_cut_copper", - "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2i1pZAsZYHLDAMKAG5ldHdvcmtfaWRtAgAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:emerald_block", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmVtZXJhbGRfYmxvY2sECQBuYW1lX2hhc2hK6QunqJznNAMKAG5ldHdvcmtfaWTOCAAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:diamond_block", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmRpYW1vbmRfYmxvY2sECQBuYW1lX2hhc2iGKrxuvkytFQMKAG5ldHdvcmtfaWS+AgAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:lapis_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmxhcGlzX2Jsb2NrBAkAbmFtZV9oYXNoDZ44xdb2zVoDCgBuZXR3b3JrX2lkjhkAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:raw_iron_block", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnJhd19pcm9uX2Jsb2NrBAkAbmFtZV9oYXNo9XyzNIQXxvwDCgBuZXR3b3JrX2lkNjMAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:raw_copper_block", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnJhd19jb3BwZXJfYmxvY2sECQBuYW1lX2hhc2hw1KG0TNUGgwMKAG5ldHdvcmtfaWTrIAAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:raw_gold_block", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnJhd19nb2xkX2Jsb2NrBAkAbmFtZV9oYXNo6YuwuLwfOBwDCgBuZXR3b3JrX2lkPgQAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:quartz_block", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZLsVAAAKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQcAZGVmYXVsdAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:quartz_block", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZL0VAAAKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQUAbGluZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:quartz_block", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZLwVAAAKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQgAY2hpc2VsZWQICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:quartz_block", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZL4VAAAKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQYAc21vb3RoCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:prismarine", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnByaXNtYXJpbmUECQBuYW1lX2hhc2jcnQCHi9CspQMKAG5ldHdvcmtfaWTTKAAACgYAc3RhdGVzCBUAcHJpc21hcmluZV9ibG9ja190eXBlBwBkZWZhdWx0AAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:prismarine", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnByaXNtYXJpbmUECQBuYW1lX2hhc2jcnQCHi9CspQMKAG5ldHdvcmtfaWTUKAAACgYAc3RhdGVzCBUAcHJpc21hcmluZV9ibG9ja190eXBlBABkYXJrAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:slime", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnNsaW1lBAkAbmFtZV9oYXNoHJiEEJx+JlkDCgBuZXR3b3JrX2lkVhkAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:honey_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmhvbmV5X2Jsb2NrBAkAbmFtZV9oYXNo9zLYSUlelywDCgBuZXR3b3JrX2lkwAcAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:honeycomb_block", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmhvbmV5Y29tYl9ibG9jawQJAG5hbWVfaGFzaASIPuOCYd1oAwoAbmV0d29ya19pZHkaAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:hay_block", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmhheV9ibG9jawQJAG5hbWVfaGFzaIB2VxKxX8EpAwoAbmV0d29ya19pZPMGAAAKBgBzdGF0ZXMDCgBkZXByZWNhdGVkAAAAAAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:bone_block", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmJvbmVfYmxvY2sECQBuYW1lX2hhc2i4ZX576W9AWgMKAG5ldHdvcmtfaWRXGQAACgYAc3RhdGVzAwoAZGVwcmVjYXRlZAAAAAAICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:nether_brick", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0Om5ldGhlcl9icmljawQJAG5hbWVfaGFzaMxcRiheU+nXAwoAbmV0d29ya19pZDwvAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:red_nether_brick", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnJlZF9uZXRoZXJfYnJpY2sECQBuYW1lX2hhc2j8pRO4LfoECAMKAG5ldHdvcmtfaWQoAgAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:netherite_block", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om5ldGhlcml0ZV9ibG9jawQJAG5hbWVfaGFzaMghh6Zib/ZKAwoAbmV0d29ya19pZA4WAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:lodestone", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmxvZGVzdG9uZQQJAG5hbWVfaGFzaJ2gmHOTlXv8AwoAbmV0d29ya19pZDQzAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:white_wool", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OndoaXRlX3dvb2wECQBuYW1lX2hhc2jRWB7vaIEDiQMKAG5ldHdvcmtfaWRfIQAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:light_gray_wool", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfd29vbAQJAG5hbWVfaGFzaOpdQ1a2v4b3AwoAbmV0d29ya19pZFQyAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:gray_wool", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmdyYXlfd29vbAQJAG5hbWVfaGFzaLsc1Lp1xdIOAwoAbmV0d29ya19pZHkCAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:black_wool", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmJsYWNrX3dvb2wECQBuYW1lX2hhc2hP2HC6o0X4HAMKAG5ldHdvcmtfaWRABAAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:brown_wool", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmJyb3duX3dvb2wECQBuYW1lX2hhc2ig5IW89PrREwMKAG5ldHdvcmtfaWStAgAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:red_wool", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OnJlZF93b29sBAkAbmFtZV9oYXNoY4TBDq+mFgUDCgBuZXR3b3JrX2lkeAAAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:orange_wool", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om9yYW5nZV93b29sBAkAbmFtZV9oYXNoFstfrTZfSCgDCgBuZXR3b3JrX2lk3wYAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:yellow_wool", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnllbGxvd193b29sBAkAbmFtZV9oYXNoTFyus2RHegcDCgBuZXR3b3JrX2lkHwIAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:lime_wool", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmxpbWVfd29vbAQJAG5hbWVfaGFzaNVnnzKiMxmeAwoAbmV0d29ya19pZGgoAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:green_wool", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmdyZWVuX3dvb2wECQBuYW1lX2hhc2i3mElRYHIcSQMKAG5ldHdvcmtfaWTaFQAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:cyan_wool", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmN5YW5fd29vbAQJAG5hbWVfaGFzaBNDfvHn8dqFAwoAbmV0d29ya19pZCYhAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:light_blue_wool", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfd29vbAQJAG5hbWVfaGFzaLWFAUfyxFPNAwoAbmV0d29ya19pZNQsAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:blue_wool", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmJsdWVfd29vbAQJAG5hbWVfaGFzaLjHyxxbTWCLAwoAbmV0d29ya19pZLAhAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:purple_wool", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnB1cnBsZV93b29sBAkAbmFtZV9oYXNojvFtqzjAf/4DCgBuZXR3b3JrX2lkODMAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:magenta_wool", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0Om1hZ2VudGFfd29vbAQJAG5hbWVfaGFzaGuOHvf+Pd4yAwoAbmV0d29ya19pZAsIAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:pink_wool", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnBpbmtfd29vbAQJAG5hbWVfaGFzaPiVA2pFeoFLAwoAbmV0d29ya19pZA8WAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:white_carpet", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OndoaXRlX2NhcnBldAQJAG5hbWVfaGFzaNeMHTI1fWPXAwoAbmV0d29ya19pZDgvAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:light_gray_carpet", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY2FycGV0BAkAbmFtZV9oYXNoHPw6ArBAsP0DCgBuZXR3b3JrX2lkNzMAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:gray_carpet", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmdyYXlfY2FycGV0BAkAbmFtZV9oYXNoZVR0OI+1VRADCgBuZXR3b3JrX2lkegIAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:black_carpet", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJsYWNrX2NhcnBldAQJAG5hbWVfaGFzaOk7LP9NptyhAwoAbmV0d29ya19pZI8oAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:brown_carpet", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJyb3duX2NhcnBldAQJAG5hbWVfaGFzaNaXFyOsAvIvAwoAbmV0d29ya19pZPMHAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:red_carpet", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9jYXJwZXQECQBuYW1lX2hhc2i9eSKBf6SO3wMKAG5ldHdvcmtfaWTNLwAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:orange_carpet", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Om9yYW5nZV9jYXJwZXQECQBuYW1lX2hhc2hIUkO4HlAdygMKAG5ldHdvcmtfaWTLLAAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:yellow_carpet", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19jYXJwZXQECQBuYW1lX2hhc2hSDKX3scCamwMKAG5ldHdvcmtfaWSIJgAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:lime_carpet", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmxpbWVfY2FycGV0BAkAbmFtZV9oYXNo+6KFOpzsib4DCgBuZXR3b3JrX2lkWysAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:green_carpet", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmdyZWVuX2NhcnBldAQJAG5hbWVfaGFzaCHPMP9ltqFJAwoAbmV0d29ya19pZNsVAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:cyan_carpet", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmN5YW5fY2FycGV0BAkAbmFtZV9oYXNobXf62dQBJj8DCgBuZXR3b3JrX2lkahUAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:light_blue_carpet", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY2FycGV0BAkAbmFtZV9oYXNo20l4oktdZ3sDCgBuZXR3b3JrX2lkdB0AAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:blue_carpet", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmJsdWVfY2FycGV0BAkAbmFtZV9oYXNo3p3lsW0eQwsDCgBuZXR3b3JrX2lkSQIAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:purple_carpet", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnBsZV9jYXJwZXQECQBuYW1lX2hhc2jwIA9pW/qp7QMKAG5ldHdvcmtfaWQhMQAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:magenta_carpet", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hZ2VudGFfY2FycGV0BAkAbmFtZV9oYXNoFXT36YNNZhMDCgBuZXR3b3JrX2lknAIAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:pink_carpet", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfY2FycGV0BAkAbmFtZV9oYXNoHll72oqk+OoDCgBuZXR3b3JrX2lk5zAAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:concrete_powder", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmNvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaJNKGQOSGsSsAwoAbmV0d29ya19pZJQpAAAKBgBzdGF0ZXMIBQBjb2xvcgUAd2hpdGUAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:concrete_powder", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmNvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaJNKGQOSGsSsAwoAbmV0d29ya19pZJwpAAAKBgBzdGF0ZXMIBQBjb2xvcgYAc2lsdmVyAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:concrete_powder", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmNvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaJNKGQOSGsSsAwoAbmV0d29ya19pZJspAAAKBgBzdGF0ZXMIBQBjb2xvcgQAZ3JheQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:concrete_powder", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmNvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaJNKGQOSGsSsAwoAbmV0d29ya19pZKMpAAAKBgBzdGF0ZXMIBQBjb2xvcgUAYmxhY2sAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:concrete_powder", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmNvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaJNKGQOSGsSsAwoAbmV0d29ya19pZKApAAAKBgBzdGF0ZXMIBQBjb2xvcgUAYnJvd24AAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:concrete_powder", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmNvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaJNKGQOSGsSsAwoAbmV0d29ya19pZKIpAAAKBgBzdGF0ZXMIBQBjb2xvcgMAcmVkAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:concrete_powder", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmNvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaJNKGQOSGsSsAwoAbmV0d29ya19pZJUpAAAKBgBzdGF0ZXMIBQBjb2xvcgYAb3JhbmdlAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:concrete_powder", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmNvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaJNKGQOSGsSsAwoAbmV0d29ya19pZJgpAAAKBgBzdGF0ZXMIBQBjb2xvcgYAeWVsbG93AAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:concrete_powder", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmNvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaJNKGQOSGsSsAwoAbmV0d29ya19pZJkpAAAKBgBzdGF0ZXMIBQBjb2xvcgQAbGltZQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:concrete_powder", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmNvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaJNKGQOSGsSsAwoAbmV0d29ya19pZKEpAAAKBgBzdGF0ZXMIBQBjb2xvcgUAZ3JlZW4AAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:concrete_powder", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmNvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaJNKGQOSGsSsAwoAbmV0d29ya19pZJ0pAAAKBgBzdGF0ZXMIBQBjb2xvcgQAY3lhbgADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:concrete_powder", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmNvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaJNKGQOSGsSsAwoAbmV0d29ya19pZJcpAAAKBgBzdGF0ZXMIBQBjb2xvcgoAbGlnaHRfYmx1ZQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:concrete_powder", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmNvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaJNKGQOSGsSsAwoAbmV0d29ya19pZJ8pAAAKBgBzdGF0ZXMIBQBjb2xvcgQAYmx1ZQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:concrete_powder", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmNvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaJNKGQOSGsSsAwoAbmV0d29ya19pZJ4pAAAKBgBzdGF0ZXMIBQBjb2xvcgYAcHVycGxlAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:concrete_powder", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmNvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaJNKGQOSGsSsAwoAbmV0d29ya19pZJYpAAAKBgBzdGF0ZXMIBQBjb2xvcgcAbWFnZW50YQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:concrete_powder", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmNvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaJNKGQOSGsSsAwoAbmV0d29ya19pZJopAAAKBgBzdGF0ZXMIBQBjb2xvcgQAcGluawADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:white_concrete", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OndoaXRlX2NvbmNyZXRlBAkAbmFtZV9oYXNo6zAp7lsLlvkDCgBuZXR3b3JrX2lkcDIAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:light_gray_concrete", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY29uY3JldGUECQBuYW1lX2hhc2hEtet5wuDIKAMKAG5ldHdvcmtfaWTpBgAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:gray_concrete", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmdyYXlfY29uY3JldGUECQBuYW1lX2hhc2j92INnb0a83AMKAG5ldHdvcmtfaWSYLwAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:black_concrete", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmJsYWNrX2NvbmNyZXRlBAkAbmFtZV9oYXNo2X7NDIQmZ70DCgBuZXR3b3JrX2lkSSsAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:brown_concrete", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmJyb3duX2NvbmNyZXRlBAkAbmFtZV9oYXNoeka02BwXf6oDCgBuZXR3b3JrX2lkVikAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:red_concrete", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZF9jb25jcmV0ZQQJAG5hbWVfaGFzaPWmNowLGubqAwoAbmV0d29ya19pZOYwAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:orange_concrete", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om9yYW5nZV9jb25jcmV0ZQQJAG5hbWVfaGFzaAgE8XmaAi6+AwoAbmV0d29ya19pZFkrAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:yellow_concrete", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnllbGxvd19jb25jcmV0ZQQJAG5hbWVfaGFzaE6ONfJPBd0+AwoAbmV0d29ya19pZGkVAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:lime_concrete", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmxpbWVfY29uY3JldGUECQBuYW1lX2hhc2gnd8JW6wmJcAMKAG5ldHdvcmtfaWTkGgAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:green_concrete", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmdyZWVuX2NvbmNyZXRlBAkAbmFtZV9oYXNokbFxRKchQZkDCgBuZXR3b3JrX2lkeCYAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:cyan_concrete", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmN5YW5fY29uY3JldGUECQBuYW1lX2hhc2hFRrWJ33qj1wMKAG5ldHdvcmtfaWQ5LwAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:light_blue_concrete", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY29uY3JldGUECQBuYW1lX2hhc2gHAe0kl0SE4AMKAG5ldHdvcmtfaWTfLwAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:blue_concrete", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmJsdWVfY29uY3JldGUECQBuYW1lX2hhc2hiay301nnj1wMKAG5ldHdvcmtfaWQ7LwAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:purple_concrete", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnB1cnBsZV9jb25jcmV0ZQQJAG5hbWVfaGFzaHBHflsPIwdXAwoAbmV0d29ya19pZCwZAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:magenta_concrete", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0Om1hZ2VudGFfY29uY3JldGUECQBuYW1lX2hhc2gN7LuB/OvdZAMKAG5ldHdvcmtfaWQBGgAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:pink_concrete", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnBpbmtfY29uY3JldGUECQBuYW1lX2hhc2ii2G5F0u3SOAMKAG5ldHdvcmtfaWSdEwAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:clay", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OmNsYXkECQBuYW1lX2hhc2j/S6sKXRcpzwMKAG5ldHdvcmtfaWQGLQAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:hardened_clay", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmhhcmRlbmVkX2NsYXkECQBuYW1lX2hhc2jrnRwCJ0krJAMKAG5ldHdvcmtfaWRGBQAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stained_hardened_clay", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0YWluZWRfaGFyZGVuZWRfY2xheQQJAG5hbWVfaGFzaNYbyvfAS3CpAwoAbmV0d29ya19pZC4pAAAKBgBzdGF0ZXMIBQBjb2xvcgUAd2hpdGUAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stained_hardened_clay", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0YWluZWRfaGFyZGVuZWRfY2xheQQJAG5hbWVfaGFzaNYbyvfAS3CpAwoAbmV0d29ya19pZDYpAAAKBgBzdGF0ZXMIBQBjb2xvcgYAc2lsdmVyAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stained_hardened_clay", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0YWluZWRfaGFyZGVuZWRfY2xheQQJAG5hbWVfaGFzaNYbyvfAS3CpAwoAbmV0d29ya19pZDUpAAAKBgBzdGF0ZXMIBQBjb2xvcgQAZ3JheQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stained_hardened_clay", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0YWluZWRfaGFyZGVuZWRfY2xheQQJAG5hbWVfaGFzaNYbyvfAS3CpAwoAbmV0d29ya19pZD0pAAAKBgBzdGF0ZXMIBQBjb2xvcgUAYmxhY2sAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stained_hardened_clay", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0YWluZWRfaGFyZGVuZWRfY2xheQQJAG5hbWVfaGFzaNYbyvfAS3CpAwoAbmV0d29ya19pZDopAAAKBgBzdGF0ZXMIBQBjb2xvcgUAYnJvd24AAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stained_hardened_clay", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0YWluZWRfaGFyZGVuZWRfY2xheQQJAG5hbWVfaGFzaNYbyvfAS3CpAwoAbmV0d29ya19pZDwpAAAKBgBzdGF0ZXMIBQBjb2xvcgMAcmVkAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stained_hardened_clay", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0YWluZWRfaGFyZGVuZWRfY2xheQQJAG5hbWVfaGFzaNYbyvfAS3CpAwoAbmV0d29ya19pZC8pAAAKBgBzdGF0ZXMIBQBjb2xvcgYAb3JhbmdlAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stained_hardened_clay", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0YWluZWRfaGFyZGVuZWRfY2xheQQJAG5hbWVfaGFzaNYbyvfAS3CpAwoAbmV0d29ya19pZDIpAAAKBgBzdGF0ZXMIBQBjb2xvcgYAeWVsbG93AAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stained_hardened_clay", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0YWluZWRfaGFyZGVuZWRfY2xheQQJAG5hbWVfaGFzaNYbyvfAS3CpAwoAbmV0d29ya19pZDMpAAAKBgBzdGF0ZXMIBQBjb2xvcgQAbGltZQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stained_hardened_clay", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0YWluZWRfaGFyZGVuZWRfY2xheQQJAG5hbWVfaGFzaNYbyvfAS3CpAwoAbmV0d29ya19pZDspAAAKBgBzdGF0ZXMIBQBjb2xvcgUAZ3JlZW4AAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stained_hardened_clay", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0YWluZWRfaGFyZGVuZWRfY2xheQQJAG5hbWVfaGFzaNYbyvfAS3CpAwoAbmV0d29ya19pZDcpAAAKBgBzdGF0ZXMIBQBjb2xvcgQAY3lhbgADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stained_hardened_clay", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0YWluZWRfaGFyZGVuZWRfY2xheQQJAG5hbWVfaGFzaNYbyvfAS3CpAwoAbmV0d29ya19pZDEpAAAKBgBzdGF0ZXMIBQBjb2xvcgoAbGlnaHRfYmx1ZQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stained_hardened_clay", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0YWluZWRfaGFyZGVuZWRfY2xheQQJAG5hbWVfaGFzaNYbyvfAS3CpAwoAbmV0d29ya19pZDkpAAAKBgBzdGF0ZXMIBQBjb2xvcgQAYmx1ZQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stained_hardened_clay", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0YWluZWRfaGFyZGVuZWRfY2xheQQJAG5hbWVfaGFzaNYbyvfAS3CpAwoAbmV0d29ya19pZDgpAAAKBgBzdGF0ZXMIBQBjb2xvcgYAcHVycGxlAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stained_hardened_clay", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0YWluZWRfaGFyZGVuZWRfY2xheQQJAG5hbWVfaGFzaNYbyvfAS3CpAwoAbmV0d29ya19pZDApAAAKBgBzdGF0ZXMIBQBjb2xvcgcAbWFnZW50YQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stained_hardened_clay", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0YWluZWRfaGFyZGVuZWRfY2xheQQJAG5hbWVfaGFzaNYbyvfAS3CpAwoAbmV0d29ya19pZDQpAAAKBgBzdGF0ZXMIBQBjb2xvcgQAcGluawADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:white_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OndoaXRlX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoiVzCdoHAJo0DCgBuZXR3b3JrX2lkDyIAAAoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:silver_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnNpbHZlcl9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAVsA0CnhzA4AwoAbmV0d29ya19pZI8TAAAKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:gray_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmdyYXlfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2jvLZt9u/lF/AMKAG5ldHdvcmtfaWQuMwAACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:black_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmJsYWNrX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoe8I4xAXbO5UDCgBuZXR3b3JrX2lkmiQAAAoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:brown_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmJyb3duX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoSiNZOobbpjoDCgBuZXR3b3JrX2lkIBUAAAoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:red_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnJlZF9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaBdWFGLmCLFVAwoAbmV0d29ya19pZBEZAAAKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:orange_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0Om9yYW5nZV9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaMyJMrnPr7szAwoAbmV0d29ya19pZMYIAAAKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:yellow_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnllbGxvd19nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaN6NaIhf6m0uAwoAbmV0d29ya19pZOUHAAAKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:lime_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmxpbWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2iF3E68/rB2EAMKAG5ldHdvcmtfaWR7AgAACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:green_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmdyZWVuX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNow5mo8aQDFboDCgBuZXR3b3JrX2lk9CoAAAoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:cyan_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmN5YW5fZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2gnNB+cCFRJhwMKAG5ldHdvcmtfaWQ2IQAACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:light_blue_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSYAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2gladnCDBKCigMKAG5ldHdvcmtfaWSoIQAACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:blue_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmJsdWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2giOZK+2nB1igMKAG5ldHdvcmtfaWSiIQAACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:purple_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnB1cnBsZV9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaIQU03txeAfHAwoAbmV0d29ya19pZIssAAAKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:magenta_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0Om1hZ2VudGFfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2i/SNqDJbfjMgMKAG5ldHdvcmtfaWQMCAAACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:pink_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OnBpbmtfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2hik8DVt4g+twMKAG5ldHdvcmtfaWStKgAACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:purpur_block", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnB1cnB1cl9ibG9jawQJAG5hbWVfaGFzaAgLwnUZGlzsAwoAbmV0d29ya19pZPYwAAAKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQcAZGVmYXVsdAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:purpur_block", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnB1cnB1cl9ibG9jawQJAG5hbWVfaGFzaAgLwnUZGlzsAwoAbmV0d29ya19pZPgwAAAKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQUAbGluZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:packed_mud", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnBhY2tlZF9tdWQECQBuYW1lX2hhc2gHOMa121h4FgMKAG5ldHdvcmtfaWTNAgAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:mud_bricks", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Om11ZF9icmlja3MECQBuYW1lX2hhc2iDL/SVl/PewQMKAG5ldHdvcmtfaWQHLAAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:nether_wart_block", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0Om5ldGhlcl93YXJ0X2Jsb2NrBAkAbmFtZV9oYXNo9XGS4GNnlV4DCgBuZXR3b3JrX2lkmBkAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:warped_wart_block", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OndhcnBlZF93YXJ0X2Jsb2NrBAkAbmFtZV9oYXNo9IqDS9yUPJoDCgBuZXR3b3JrX2lkfiYAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:shroomlight", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnNocm9vbWxpZ2h0BAkAbmFtZV9oYXNoZHCHcHX/HYADCgBuZXR3b3JrX2lk+x8AAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:crimson_nylium", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fbnlsaXVtBAkAbmFtZV9oYXNoOr6DJYW2bFYDCgBuZXR3b3JrX2lkKRkAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:warped_nylium", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9ueWxpdW0ECQBuYW1lX2hhc2g0Zf89cfr3rwMKAG5ldHdvcmtfaWTqKQAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:netherrack", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Om5ldGhlcnJhY2sECQBuYW1lX2hhc2i/r5ZyRsvPyQMKAG5ldHdvcmtfaWSmLAAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:basalt", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmJhc2FsdAQJAG5hbWVfaGFzaH+UQO2yWodiAwoAbmV0d29ya19pZPMZAAAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:polished_basalt", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnBvbGlzaGVkX2Jhc2FsdAQJAG5hbWVfaGFzaMS+L0gMnRcBAwoAbmV0d29ya19pZBgAAAAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:smooth_basalt", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnNtb290aF9iYXNhbHQECQBuYW1lX2hhc2jKPUdz89kuNAMKAG5ldHdvcmtfaWTMCAAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:soul_soil", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnNvdWxfc29pbAQJAG5hbWVfaGFzaC1/87ccutuTAwoAbmV0d29ya19pZBIjAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:dirt", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OmRpcnQECQBuYW1lX2hhc2hXp6jnXAe+kQMKAG5ldHdvcmtfaWTDIgAACgYAc3RhdGVzCAkAZGlydF90eXBlBgBub3JtYWwAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:dirt", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OmRpcnQECQBuYW1lX2hhc2hXp6jnXAe+kQMKAG5ldHdvcmtfaWTEIgAACgYAc3RhdGVzCAkAZGlydF90eXBlBgBjb2Fyc2UAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:farmland", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OmZhcm1sYW5kBAkAbmFtZV9oYXNoxyQ5ag7LolADCgBuZXR3b3JrX2lkEhgAAAoGAHN0YXRlcwMSAG1vaXN0dXJpemVkX2Ftb3VudAAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:grass", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmdyYXNzBAkAbmFtZV9oYXNosppASPWFlsUDCgBuZXR3b3JrX2lkZCwAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:grass_path", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmdyYXNzX3BhdGgECQBuYW1lX2hhc2i0/KZV8Qsy+gMKAG5ldHdvcmtfaWRyMgAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:podzol", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBvZHpvbAQJAG5hbWVfaGFzaBzqokRjH4Z1AwoAbmV0d29ya19pZNQcAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:mycelium", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0Om15Y2VsaXVtBAkAbmFtZV9oYXNojTN09cKickIDCgBuZXR3b3JrX2lkrhUAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:mud", - "block_state_b64": "CgAACAQAbmFtZQ0AbWluZWNyYWZ0Om11ZAQJAG5hbWVfaGFzaPb/3P+uLy+9AwoAbmV0d29ya19pZDIrAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stone", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lk0wYAAAoGAHN0YXRlcwgKAHN0b25lX3R5cGUFAHN0b25lAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:iron_ore", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0Omlyb25fb3JlBAkAbmFtZV9oYXNoS7BYtLnfx3gDCgBuZXR3b3JrX2lk/BwAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:gold_ore", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OmdvbGRfb3JlBAkAbmFtZV9oYXNoC5Y+DUGXLC4DCgBuZXR3b3JrX2lk5AcAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:diamond_ore", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmRpYW1vbmRfb3JlBAkAbmFtZV9oYXNokUOJ2wZZrGQDCgBuZXR3b3JrX2lk/xkAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:lapis_ore", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmxhcGlzX29yZQQJAG5hbWVfaGFzaMrmrUrSzb7qAwoAbmV0d29ya19pZOUwAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:redstone_ore", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZHN0b25lX29yZQQJAG5hbWVfaGFzaFHVnp8Wc4JbAwoAbmV0d29ya19pZJEZAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:coal_ore", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OmNvYWxfb3JlBAkAbmFtZV9oYXNo1OjA+Iuy51oDCgBuZXR3b3JrX2lkjxkAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:copper_ore", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmNvcHBlcl9vcmUECQBuYW1lX2hhc2iSZduSntOzOwMKAG5ldHdvcmtfaWQnFQAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:emerald_ore", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmVtZXJhbGRfb3JlBAkAbmFtZV9oYXNoJTovr+VgINsDCgBuZXR3b3JrX2lkhy8AAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:quartz_ore", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnF1YXJ0el9vcmUECQBuYW1lX2hhc2g0yNHLMK9TaQMKAG5ldHdvcmtfaWSSGgAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:nether_gold_ore", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om5ldGhlcl9nb2xkX29yZQQJAG5hbWVfaGFzaEJZ7segIBgBAwoAbmV0d29ya19pZBsAAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:ancient_debris", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmFuY2llbnRfZGVicmlzBAkAbmFtZV9oYXNoNrbxMc9AwKcDCgBuZXR3b3JrX2lk6SgAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:deepslate_iron_ore", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9pcm9uX29yZQQJAG5hbWVfaGFzaB/fDL9pgvXXAwoAbmV0d29ya19pZD0vAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:deepslate_gold_ore", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9nb2xkX29yZQQJAG5hbWVfaGFzaF9G7WYhKFinAwoAbmV0d29ya19pZOgoAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:deepslate_diamond_ore", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV9kaWFtb25kX29yZQQJAG5hbWVfaGFzaEUH5USh+iD3AwoAbmV0d29ya19pZEMyAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:deepslate_lapis_ore", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV9sYXBpc19vcmUECQBuYW1lX2hhc2j+yFxU/KZs1gMKAG5ldHdvcmtfaWQpLwAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:deepslate_redstone_ore", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmRlZXBzbGF0ZV9yZWRzdG9uZV9vcmUECQBuYW1lX2hhc2iVgM3wWWD6ugMKAG5ldHdvcmtfaWT6KgAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:deepslate_emerald_ore", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV9lbWVyYWxkX29yZQQJAG5hbWVfaGFzaNlfo5HTwS6wAwoAbmV0d29ya19pZOspAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:deepslate_coal_ore", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9jb2FsX29yZQQJAG5hbWVfaGFzaIjikmcbRrPPAwoAbmV0d29ya19pZNcuAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:deepslate_copper_ore", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9jb3BwZXJfb3JlBAkAbmFtZV9oYXNottjV4Ev5LAQDCgBuZXR3b3JrX2lkbAAAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:gravel", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmdyYXZlbAQJAG5hbWVfaGFzaOFxz8XJd2r/AwoAbmV0d29ya19pZFMzAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stone", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lk1AYAAAoGAHN0YXRlcwgKAHN0b25lX3R5cGUHAGdyYW5pdGUAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stone", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lk1gYAAAoGAHN0YXRlcwgKAHN0b25lX3R5cGUHAGRpb3JpdGUAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stone", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lk2AYAAAoGAHN0YXRlcwgKAHN0b25lX3R5cGUIAGFuZGVzaXRlAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:blackstone", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmJsYWNrc3RvbmUECQBuYW1lX2hhc2iMFYziD80D6QMKAG5ldHdvcmtfaWRzMAAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:deepslate", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmRlZXBzbGF0ZQQJAG5hbWVfaGFzaKX5pAblxz8TAwoAbmV0d29ya19pZJkCAAAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stone", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lk1QYAAAoGAHN0YXRlcwgKAHN0b25lX3R5cGUOAGdyYW5pdGVfc21vb3RoAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stone", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lk1wYAAAoGAHN0YXRlcwgKAHN0b25lX3R5cGUOAGRpb3JpdGVfc21vb3RoAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stone", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lk2QYAAAoGAHN0YXRlcwgKAHN0b25lX3R5cGUPAGFuZGVzaXRlX3Ntb290aAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:polished_blackstone", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmUECQBuYW1lX2hhc2jT9fHCl6vWQQMKAG5ldHdvcmtfaWStFQAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:polished_deepslate", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaHC1edoaWF3uAwoAbmV0d29ya19pZCYxAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:sand", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OnNhbmQECQBuYW1lX2hhc2i6lthXXbAyWAMKAG5ldHdvcmtfaWQwGQAACgYAc3RhdGVzCAkAc2FuZF90eXBlBgBub3JtYWwAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:sand", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OnNhbmQECQBuYW1lX2hhc2i6lthXXbAyWAMKAG5ldHdvcmtfaWQxGQAACgYAc3RhdGVzCAkAc2FuZF90eXBlAwByZWQAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:cactus", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmNhY3R1cwQJAG5hbWVfaGFzaCG9zL0N4wvGAwoAbmV0d29ya19pZG8sAAAKBgBzdGF0ZXMDAwBhZ2UAAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:oak_log", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0Om9ha19sb2cECQBuYW1lX2hhc2ho6TS+K7PZFQMKAG5ldHdvcmtfaWTHAgAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stripped_oak_log", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0cmlwcGVkX29ha19sb2cECQBuYW1lX2hhc2h8dqh+OOHU4wMKAG5ldHdvcmtfaWRJMAAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:spruce_log", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnNwcnVjZV9sb2cECQBuYW1lX2hhc2hZ03qaLoF3WgMKAG5ldHdvcmtfaWR7GQAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stripped_spruce_log", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX3NwcnVjZV9sb2cECQBuYW1lX2hhc2iNrhKjS5IyrgMKAG5ldHdvcmtfaWStKQAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:birch_log", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmJpcmNoX2xvZwQJAG5hbWVfaGFzaBUzT3NxsZAnAwoAbmV0d29ya19pZNoGAAAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stripped_birch_log", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnN0cmlwcGVkX2JpcmNoX2xvZwQJAG5hbWVfaGFzaCFKS4AeuSidAwoAbmV0d29ya19pZMQmAAAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:jungle_log", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Omp1bmdsZV9sb2cECQBuYW1lX2hhc2gkwW0KNulqDgMKAG5ldHdvcmtfaWRyAgAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stripped_jungle_log", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2p1bmdsZV9sb2cECQBuYW1lX2hhc2hAwMsgOk02JAMKAG5ldHdvcmtfaWTHBgAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:acacia_log", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmFjYWNpYV9sb2cECQBuYW1lX2hhc2iV48VpYhjoYQMKAG5ldHdvcmtfaWTgGQAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stripped_acacia_log", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2FjYWNpYV9sb2cECQBuYW1lX2hhc2hJb0lQqnEqlgMKAG5ldHdvcmtfaWS0JAAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:dark_oak_log", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRhcmtfb2FrX2xvZwQJAG5hbWVfaGFzaIWfVRd0XUo3AwoAbmV0d29ya19pZNMRAAAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stripped_dark_oak_log", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2Rhcmtfb2FrX2xvZwQJAG5hbWVfaGFzaPFTdxRdPwkOAwoAbmV0d29ya19pZG8CAAAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:mangrove_log", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0Om1hbmdyb3ZlX2xvZwQJAG5hbWVfaGFzaHZe6DzPZBobAwoAbmV0d29ya19pZDEEAAAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stripped_mangrove_log", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX21hbmdyb3ZlX2xvZwQJAG5hbWVfaGFzaLqIBo4hwA//AwoAbmV0d29ya19pZFAzAAAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:cherry_log", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmNoZXJyeV9sb2cECQBuYW1lX2hhc2hwFlaioppB1wMKAG5ldHdvcmtfaWQtLwAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stripped_cherry_log", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2NoZXJyeV9sb2cECQBuYW1lX2hhc2i85H6G+WhXaAMKAG5ldHdvcmtfaWRKGgAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:crimson_stem", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmNyaW1zb25fc3RlbQQJAG5hbWVfaGFzaM0FzfL0UTKZAwoAbmV0d29ya19pZHUmAAAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stripped_crimson_stem", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2NyaW1zb25fc3RlbQQJAG5hbWVfaGFzaDlA6nood57EAwoAbmV0d29ya19pZEgsAAAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:warped_stem", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OndhcnBlZF9zdGVtBAkAbmFtZV9oYXNon7cKfPZxdrUDCgBuZXR3b3JrX2lkfyoAAAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stripped_warped_stem", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX3dhcnBlZF9zdGVtBAkAbmFtZV9oYXNoEw+y0dDPSd8DCgBuZXR3b3JrX2lkuC8AAAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWTWEQAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlAwBvYWsAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWTcEQAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlAwBvYWsAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWTXEQAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlBgBzcHJ1Y2UAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWTdEQAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlBgBzcHJ1Y2UAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWTYEQAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlBQBiaXJjaAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWTeEQAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlBQBiaXJjaAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWTZEQAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlBgBqdW5nbGUAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWTfEQAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlBgBqdW5nbGUAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWTaEQAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlBgBhY2FjaWEAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWTgEQAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlBgBhY2FjaWEAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWTbEQAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlCABkYXJrX29hawADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWThEQAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlCABkYXJrX29hawADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:mangrove_wood", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Om1hbmdyb3ZlX3dvb2QECQBuYW1lX2hhc2iXVxG0JG2fVAMKAG5ldHdvcmtfaWQLGQAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stripped_mangrove_wood", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OnN0cmlwcGVkX21hbmdyb3ZlX3dvb2QECQBuYW1lX2hhc2h7CkbaBF7/WAMKAG5ldHdvcmtfaWRSGQAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:cherry_wood", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNoZXJyeV93b29kBAkAbmFtZV9oYXNoAW8srlmpBM8DCgBuZXR3b3JrX2lk/SwAAAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AQwAc3RyaXBwZWRfYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stripped_cherry_wood", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX2NoZXJyeV93b29kBAkAbmFtZV9oYXNo/e7KXv+CB38DCgBuZXR3b3JrX2lkPh8AAAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:crimson_hyphae", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25faHlwaGFlBAkAbmFtZV9oYXNouRmKmfSqEWADCgBuZXR3b3JrX2lkuRkAAAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stripped_crimson_hyphae", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnN0cmlwcGVkX2NyaW1zb25faHlwaGFlBAkAbmFtZV9oYXNoFffwmABq4LUDCgBuZXR3b3JrX2lkgyoAAAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:warped_hyphae", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9oeXBoYWUECQBuYW1lX2hhc2hn8plQUr6pmQMKAG5ldHdvcmtfaWR7JgAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:stripped_warped_hyphae", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OnN0cmlwcGVkX3dhcnBlZF9oeXBoYWUECQBuYW1lX2hhc2irKq+HYPSgjQMKAG5ldHdvcmtfaWQVIgAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:bamboo_block", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJhbWJvb19ibG9jawQJAG5hbWVfaGFzaAbDeur6stIBAwoAbmV0d29ya19pZDwAAAAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:stripped_bamboo_block", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2JhbWJvb19ibG9jawQJAG5hbWVfaGFzaJpwytpZOZM9AwoAbmV0d29ya19pZFIVAAAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:leaves", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmxlYXZlcwQJAG5hbWVfaGFzaACPIsusW0mnAwoAbmV0d29ya19pZNgoAAAKBgBzdGF0ZXMIDQBvbGRfbGVhZl90eXBlAwBvYWsBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:leaves", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmxlYXZlcwQJAG5hbWVfaGFzaACPIsusW0mnAwoAbmV0d29ya19pZNkoAAAKBgBzdGF0ZXMIDQBvbGRfbGVhZl90eXBlBgBzcHJ1Y2UBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:leaves", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmxlYXZlcwQJAG5hbWVfaGFzaACPIsusW0mnAwoAbmV0d29ya19pZNooAAAKBgBzdGF0ZXMIDQBvbGRfbGVhZl90eXBlBQBiaXJjaAEOAHBlcnNpc3RlbnRfYml0AAEKAHVwZGF0ZV9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:leaves", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmxlYXZlcwQJAG5hbWVfaGFzaACPIsusW0mnAwoAbmV0d29ya19pZNsoAAAKBgBzdGF0ZXMIDQBvbGRfbGVhZl90eXBlBgBqdW5nbGUBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:leaves2", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmxlYXZlczIECQBuYW1lX2hhc2gy/bgrncY1ZAMKAG5ldHdvcmtfaWT3GQAACgYAc3RhdGVzCA0AbmV3X2xlYWZfdHlwZQYAYWNhY2lhAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:leaves2", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmxlYXZlczIECQBuYW1lX2hhc2gy/bgrncY1ZAMKAG5ldHdvcmtfaWT4GQAACgYAc3RhdGVzCA0AbmV3X2xlYWZfdHlwZQgAZGFya19vYWsBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:mangrove_leaves", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX2xlYXZlcwQJAG5hbWVfaGFzaKyI/dWvhEG8AwoAbmV0d29ya19pZCwrAAAKBgBzdGF0ZXMBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:cherry_leaves", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9sZWF2ZXMECQBuYW1lX2hhc2giTs9ChhYBlQMKAG5ldHdvcmtfaWSWJAAACgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:azalea_leaves", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmF6YWxlYV9sZWF2ZXMECQBuYW1lX2hhc2iXFhD57wFS7AMKAG5ldHdvcmtfaWTyMAAACgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:azalea_leaves_flowered", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmF6YWxlYV9sZWF2ZXNfZmxvd2VyZWQECQBuYW1lX2hhc2gs8jxlS/pMrwMKAG5ldHdvcmtfaWTgKQAACgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:sapling", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWQEBwAACgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUDAG9hawADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:sapling", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWQFBwAACgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUGAHNwcnVjZQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:sapling", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWQGBwAACgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUFAGJpcmNoAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:sapling", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWQHBwAACgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUGAGp1bmdsZQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:sapling", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWQIBwAACgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUGAGFjYWNpYQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:sapling", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWQJBwAACgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUIAGRhcmtfb2FrAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:mangrove_propagule", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0Om1hbmdyb3ZlX3Byb3BhZ3VsZQQJAG5hbWVfaGFzaJGeox6hkfLFAwoAbmV0d29ya19pZGUsAAAKBgBzdGF0ZXMBBwBoYW5naW5nAAMPAHByb3BhZ3VsZV9zdGFnZQAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:cherry_sapling", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNoZXJyeV9zYXBsaW5nBAkAbmFtZV9oYXNoGrPpNMf1LtcDCgBuZXR3b3JrX2lkKy8AAAoGAHN0YXRlcwEHAGFnZV9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:bee_nest", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OmJlZV9uZXN0BAkAbmFtZV9oYXNo2R2WBxUHEZIDCgBuZXR3b3JrX2lkxiIAAAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAADCwBob25leV9sZXZlbAAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:wheat_seeds" - }, - { - "id": "minecraft:pumpkin_seeds" - }, - { - "id": "minecraft:melon_seeds" - }, - { - "id": "minecraft:beetroot_seeds" - }, - { - "id": "minecraft:torchflower_seeds" - }, - { - "id": "minecraft:pitcher_pod" - }, - { - "id": "minecraft:wheat" - }, - { - "id": "minecraft:beetroot" - }, - { - "id": "minecraft:potato" - }, - { - "id": "minecraft:poisonous_potato" - }, - { - "id": "minecraft:carrot" - }, - { - "id": "minecraft:golden_carrot" - }, - { - "id": "minecraft:apple" - }, - { - "id": "minecraft:golden_apple" - }, - { - "id": "minecraft:enchanted_golden_apple" - }, - { - "id": "minecraft:melon_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1lbG9uX2Jsb2NrBAkAbmFtZV9oYXNoXxSm0iYpAx8DCgBuZXR3b3JrX2lkYQQAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:melon_slice" - }, - { - "id": "minecraft:glistering_melon_slice" - }, - { - "id": "minecraft:sweet_berries" - }, - { - "id": "minecraft:glow_berries" - }, - { - "id": "minecraft:pumpkin", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnB1bXBraW4ECQBuYW1lX2hhc2gc8A3jaSzWbgMKAG5ldHdvcmtfaWTeGgAACgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:carved_pumpkin", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNhcnZlZF9wdW1wa2luBAkAbmFtZV9oYXNoPu1T0MJuG90DCgBuZXR3b3JrX2lkoi8AAAoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:lit_pumpkin", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmxpdF9wdW1wa2luBAkAbmFtZV9oYXNo7gWtEm2uPL0DCgBuZXR3b3JrX2lkMysAAAoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:honeycomb" - }, - { - "id": "minecraft:tallgrass", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnRhbGxncmFzcwQJAG5hbWVfaGFzaC3PXpAXXYswAwoAbmV0d29ya19pZPYHAAAKBgBzdGF0ZXMIDwB0YWxsX2dyYXNzX3R5cGUEAGZlcm4AAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:double_plant", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZJghAAAKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQQAZmVybgEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:tallgrass", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnRhbGxncmFzcwQJAG5hbWVfaGFzaC3PXpAXXYswAwoAbmV0d29ya19pZPUHAAAKBgBzdGF0ZXMIDwB0YWxsX2dyYXNzX3R5cGUEAHRhbGwAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:double_plant", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZJchAAAKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQUAZ3Jhc3MBDwB1cHBlcl9ibG9ja19iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:nether_sprouts" - }, - { - "id": "minecraft:fire_coral", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmZpcmVfY29yYWwECQBuYW1lX2hhc2hOHyyECVQVJwMKAG5ldHdvcmtfaWTSBgAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:brain_coral", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmJyYWluX2NvcmFsBAkAbmFtZV9oYXNoRiWlLCwA2ycDCgBuZXR3b3JrX2lk3gYAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:bubble_coral", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJ1YmJsZV9jb3JhbAQJAG5hbWVfaGFzaJz6rWnl+v2qAwoAbmV0d29ya19pZGkpAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:tube_coral", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnR1YmVfY29yYWwECQBuYW1lX2hhc2iYa8oO/tgk7wMKAG5ldHdvcmtfaWQvMQAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:horn_coral", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Omhvcm5fY29yYWwECQBuYW1lX2hhc2iZnRHjZbnLPgMKAG5ldHdvcmtfaWRoFQAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:dead_fire_coral", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfZmlyZV9jb3JhbAQJAG5hbWVfaGFzaEPU6tFy/latAwoAbmV0d29ya19pZKQpAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:dead_brain_coral", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmRlYWRfYnJhaW5fY29yYWwECQBuYW1lX2hhc2j5L6QJCISvzwMKAG5ldHdvcmtfaWTWLgAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:dead_bubble_coral", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmRlYWRfYnViYmxlX2NvcmFsBAkAbmFtZV9oYXNoSTOZ/8wpeNYDCgBuZXR3b3JrX2lkKi8AAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:dead_tube_coral", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfdHViZV9jb3JhbAQJAG5hbWVfaGFzaJGjNWhlaIJeAwoAbmV0d29ya19pZJcZAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:dead_horn_coral", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfaG9ybl9jb3JhbAQJAG5hbWVfaGFzaJBkz3qt+g2cAwoAbmV0d29ya19pZIkmAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:coral_fan", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZAYbAAAKBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgMAcmVkAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:coral_fan", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZAQbAAAKBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgQAcGluawMTAGNvcmFsX2Zhbl9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:coral_fan", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZAUbAAAKBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgYAcHVycGxlAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:coral_fan", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZAMbAAAKBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgQAYmx1ZQMTAGNvcmFsX2Zhbl9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:coral_fan", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZAcbAAAKBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgYAeWVsbG93AxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:coral_fan_dead", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkSAAAAAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yAwByZWQDEwBjb3JhbF9mYW5fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:coral_fan_dead", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkRgAAAAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABwaW5rAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:coral_fan_dead", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkRwAAAAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgBwdXJwbGUDEwBjb3JhbF9mYW5fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:coral_fan_dead", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkRQAAAAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABibHVlAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:coral_fan_dead", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkSQAAAAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgB5ZWxsb3cDEwBjb3JhbF9mYW5fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:crimson_roots", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNyaW1zb25fcm9vdHMECQBuYW1lX2hhc2j1fWgQLViv5QMKAG5ldHdvcmtfaWRnMAAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:warped_roots", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OndhcnBlZF9yb290cwQJAG5hbWVfaGFzaBc3WvbJOLlkAwoAbmV0d29ya19pZAAaAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:yellow_flower", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19mbG93ZXIECQBuYW1lX2hhc2jWbU1pF0OUGAMKAG5ldHdvcmtfaWQABAAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWRrFQAACgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUFAHBvcHB5AAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWRsFQAACgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUGAG9yY2hpZAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWRtFQAACgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUGAGFsbGl1bQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWRuFQAACgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUJAGhvdXN0b25pYQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWRvFQAACgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUJAHR1bGlwX3JlZAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWRwFQAACgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUMAHR1bGlwX29yYW5nZQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWRxFQAACgYAc3RhdGVzCAsAZmxvd2VyX3R5cGULAHR1bGlwX3doaXRlAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWRyFQAACgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUKAHR1bGlwX3BpbmsAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWRzFQAACgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUFAG94ZXllAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWR0FQAACgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUKAGNvcm5mbG93ZXIAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWR1FQAACgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUSAGxpbHlfb2ZfdGhlX3ZhbGxleQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:double_plant", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZJUhAAAKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQkAc3VuZmxvd2VyAQ8AdXBwZXJfYmxvY2tfYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:double_plant", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZJYhAAAKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQcAc3lyaW5nYQEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:double_plant", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZJkhAAAKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQQAcm9zZQEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:double_plant", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZJohAAAKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQcAcGFlb25pYQEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:pitcher_plant", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnBpdGNoZXJfcGxhbnQECQBuYW1lX2hhc2hRJHzsbDH+SQMKAG5ldHdvcmtfaWT8FQAACgYAc3RhdGVzAQ8AdXBwZXJfYmxvY2tfYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:pink_petals", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfcGV0YWxzBAkAbmFtZV9oYXNo6DQwN9SwV3QDCgBuZXR3b3JrX2lkKxsAAAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAADBgBncm93dGgAAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:wither_rose", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OndpdGhlcl9yb3NlBAkAbmFtZV9oYXNoaSKxl3I516gDCgBuZXR3b3JrX2lkIykAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:torchflower", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnRvcmNoZmxvd2VyBAkAbmFtZV9oYXNoL+mHtElwbqQDCgBuZXR3b3JrX2lktCgAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:white_dye" - }, - { - "id": "minecraft:light_gray_dye" - }, - { - "id": "minecraft:gray_dye" - }, - { - "id": "minecraft:black_dye" - }, - { - "id": "minecraft:brown_dye" - }, - { - "id": "minecraft:red_dye" - }, - { - "id": "minecraft:orange_dye" - }, - { - "id": "minecraft:yellow_dye" - }, - { - "id": "minecraft:lime_dye" - }, - { - "id": "minecraft:green_dye" - }, - { - "id": "minecraft:cyan_dye" - }, - { - "id": "minecraft:light_blue_dye" - }, - { - "id": "minecraft:blue_dye" - }, - { - "id": "minecraft:purple_dye" - }, - { - "id": "minecraft:magenta_dye" - }, - { - "id": "minecraft:pink_dye" - }, - { - "id": "minecraft:ink_sac" - }, - { - "id": "minecraft:glow_ink_sac" - }, - { - "id": "minecraft:cocoa_beans" - }, - { - "id": "minecraft:lapis_lazuli" - }, - { - "id": "minecraft:bone_meal" - }, - { - "id": "minecraft:vine", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OnZpbmUECQBuYW1lX2hhc2j0Sj8/XeXOLAMKAG5ldHdvcmtfaWTCBwAACgYAc3RhdGVzAxMAdmluZV9kaXJlY3Rpb25fYml0cwAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:weeping_vines", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndlZXBpbmdfdmluZXMECQBuYW1lX2hhc2jrLgLHkQygiwMKAG5ldHdvcmtfaWSxIQAACgYAc3RhdGVzAxEAd2VlcGluZ192aW5lc19hZ2UAAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:twisting_vines", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnR3aXN0aW5nX3ZpbmVzBAkAbmFtZV9oYXNoDYR5QgVUQJADCgBuZXR3b3JrX2lkhiIAAAoGAHN0YXRlcwMSAHR3aXN0aW5nX3ZpbmVzX2FnZQAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:waterlily", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OndhdGVybGlseQQJAG5hbWVfaGFzaEHgC4c1SXg0AwoAbmV0d29ya19pZM0IAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:seagrass", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OnNlYWdyYXNzBAkAbmFtZV9oYXNoHSBFtoHdWxIDCgBuZXR3b3JrX2lkkgIAAAoGAHN0YXRlcwgOAHNlYV9ncmFzc190eXBlBwBkZWZhdWx0AAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:kelp" - }, - { - "id": "minecraft:deadbush", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OmRlYWRidXNoBAkAbmFtZV9oYXNoPFODe4IScnYDCgBuZXR3b3JrX2lk7xwAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:bamboo", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmJhbWJvbwQJAG5hbWVfaGFzaBgpGmyzhedCAwoAbmV0d29ya19pZK8VAAAKBgBzdGF0ZXMBBwBhZ2VfYml0AAgQAGJhbWJvb19sZWFmX3NpemUJAG5vX2xlYXZlcwgWAGJhbWJvb19zdGFsa190aGlja25lc3MEAHRoaW4AAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:snow", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OnNub3cECQBuYW1lX2hhc2gVHr5XXdETWAMKAG5ldHdvcmtfaWQvGQAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:ice", - "block_state_b64": "CgAACAQAbmFtZQ0AbWluZWNyYWZ0OmljZQQJAG5hbWVfaGFzaNF26f+uUT29AwoAbmV0d29ya19pZDcrAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:packed_ice", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnBhY2tlZF9pY2UECQBuYW1lX2hhc2hk4bu123ZrFgMKAG5ldHdvcmtfaWTMAgAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:blue_ice", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OmJsdWVfaWNlBAkAbmFtZV9oYXNo+EKxYgFhKcgDCgBuZXR3b3JrX2lkmywAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:snow_layer", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnNub3dfbGF5ZXIECQBuYW1lX2hhc2hXka6atMYUCQMKAG5ldHdvcmtfaWQxAgAACgYAc3RhdGVzAQsAY292ZXJlZF9iaXQAAwYAaGVpZ2h0AAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:pointed_dripstone", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnBvaW50ZWRfZHJpcHN0b25lBAkAbmFtZV9oYXNoJMISzmHQgt8DCgBuZXR3b3JrX2lkyC8AAAoGAHN0YXRlcwgTAGRyaXBzdG9uZV90aGlja25lc3MDAHRpcAEHAGhhbmdpbmcBAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:dripstone_block", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRyaXBzdG9uZV9ibG9jawQJAG5hbWVfaGFzaIIXnEqY77YsAwoAbmV0d29ya19pZMEHAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:moss_carpet", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vc3NfY2FycGV0BAkAbmFtZV9oYXNo/NEDxRPTshYDCgBuZXR3b3JrX2lk0AIAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:moss_block", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Om1vc3NfYmxvY2sECQBuYW1lX2hhc2iovcsPUYX2tgMKAG5ldHdvcmtfaWSsKgAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:dirt_with_roots", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRpcnRfd2l0aF9yb290cwQJAG5hbWVfaGFzaLCNDYPviDCIAwoAbmV0d29ya19pZF0hAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:hanging_roots", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Omhhbmdpbmdfcm9vdHMECQBuYW1lX2hhc2jaXn+Y5UZpDAMKAG5ldHdvcmtfaWRkAgAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:mangrove_roots", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hbmdyb3ZlX3Jvb3RzBAkAbmFtZV9oYXNoa786PzQGZ6kDCgBuZXR3b3JrX2lkLSkAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:muddy_mangrove_roots", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0Om11ZGR5X21hbmdyb3ZlX3Jvb3RzBAkAbmFtZV9oYXNo9YApdHpo1RkDCgBuZXR3b3JrX2lkLAQAAAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:big_dripleaf", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJpZ19kcmlwbGVhZgQJAG5hbWVfaGFzaGBEhXjo6qSdAwoAbmV0d29ya19pZMwmAAAKBgBzdGF0ZXMBEQBiaWdfZHJpcGxlYWZfaGVhZAEIEQBiaWdfZHJpcGxlYWZfdGlsdAQAbm9uZQMJAGRpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:small_dripleaf_block", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnNtYWxsX2RyaXBsZWFmX2Jsb2NrBAkAbmFtZV9oYXNojxRAgXP9uWADCgBuZXR3b3JrX2lk0xkAAAoGAHN0YXRlcwMJAGRpcmVjdGlvbgMAAAABDwB1cHBlcl9ibG9ja19iaXQBAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:spore_blossom", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnNwb3JlX2Jsb3Nzb20ECQBuYW1lX2hhc2il3U72Gbco2gMKAG5ldHdvcmtfaWRkLwAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:azalea", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmF6YWxlYQQJAG5hbWVfaGFzaNyUl+BW9JrBAwoAbmV0d29ya19pZAYsAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:flowering_azalea", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmZsb3dlcmluZ19hemFsZWEECQBuYW1lX2hhc2ie9r33wz8kiwMKAG5ldHdvcmtfaWSuIQAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:glow_lichen", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Omdsb3dfbGljaGVuBAkAbmFtZV9oYXNobyPUrIYlo44DCgBuZXR3b3JrX2lkfyIAAAoGAHN0YXRlcwMZAG11bHRpX2ZhY2VfZGlyZWN0aW9uX2JpdHM/AAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:amethyst_block", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmFtZXRoeXN0X2Jsb2NrBAkAbmFtZV9oYXNob+JK1iiAthcDCgBuZXR3b3JrX2lk9AIAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:budding_amethyst", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmJ1ZGRpbmdfYW1ldGh5c3QECQBuYW1lX2hhc2gJvAwfI14fxgMKAG5ldHdvcmtfaWR/LAAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:amethyst_cluster", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmFtZXRoeXN0X2NsdXN0ZXIECQBuYW1lX2hhc2jK82S88Jgm8wMKAG5ldHdvcmtfaWRfMQAACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgEAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:large_amethyst_bud", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmxhcmdlX2FtZXRoeXN0X2J1ZAQJAG5hbWVfaGFzaAHhdpWD+sd5AwoAbmV0d29ya19pZCIdAAAKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAQAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:medium_amethyst_bud", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0Om1lZGl1bV9hbWV0aHlzdF9idWQECQBuYW1lX2hhc2g5lBGtC0DzZQMKAG5ldHdvcmtfaWQPGgAACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgEAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:small_amethyst_bud", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnNtYWxsX2FtZXRoeXN0X2J1ZAQJAG5hbWVfaGFzaEnb4+q9PO4YAwoAbmV0d29ya19pZAMEAAAKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAQAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:tuff", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OnR1ZmYECQBuYW1lX2hhc2h1Rwc1XYsBGwMKAG5ldHdvcmtfaWQwBAAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:calcite", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmNhbGNpdGUECQBuYW1lX2hhc2ixKLu8ZIdzDQMKAG5ldHdvcmtfaWRuAgAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:chicken" - }, - { - "id": "minecraft:porkchop" - }, - { - "id": "minecraft:beef" - }, - { - "id": "minecraft:mutton" - }, - { - "id": "minecraft:rabbit" - }, - { - "id": "minecraft:cod" - }, - { - "id": "minecraft:salmon" - }, - { - "id": "minecraft:tropical_fish" - }, - { - "id": "minecraft:pufferfish" - }, - { - "id": "minecraft:brown_mushroom", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmJyb3duX211c2hyb29tBAkAbmFtZV9oYXNonYw/FO78WDoDCgBuZXR3b3JrX2lkHxUAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:red_mushroom", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZF9tdXNocm9vbQQJAG5hbWVfaGFzaPpzJua7669xAwoAbmV0d29ya19pZOcaAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:crimson_fungus", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fZnVuZ3VzBAkAbmFtZV9oYXNolIcCUuFM2u0DCgBuZXR3b3JrX2lkJDEAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:warped_fungus", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9mdW5ndXMECQBuYW1lX2hhc2gq8bSnRVTAFgMKAG5ldHdvcmtfaWTRAgAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:brown_mushroom_block", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkli8AAAoGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cw4AAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:red_mushroom_block", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnJlZF9tdXNocm9vbV9ibG9jawQJAG5hbWVfaGFzaJTTyJbth9M9AwoAbmV0d29ya19pZGMVAAAKBgBzdGF0ZXMDEgBodWdlX211c2hyb29tX2JpdHMOAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:brown_mushroom_block", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkly8AAAoGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cw8AAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:brown_mushroom_block", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkiC8AAAoGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cwAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:egg" - }, - { - "id": "minecraft:sugar_cane" - }, - { - "id": "minecraft:sugar" - }, - { - "id": "minecraft:rotten_flesh" - }, - { - "id": "minecraft:bone" - }, - { - "id": "minecraft:web", - "block_state_b64": "CgAACAQAbmFtZQ0AbWluZWNyYWZ0OndlYgQJAG5hbWVfaGFzaA4GKQCvG4i9AwoAbmV0d29ya19pZFArAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:spider_eye" - }, - { - "id": "minecraft:mob_spawner", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vYl9zcGF3bmVyBAkAbmFtZV9oYXNoNwGrCV/Fkh8DCgBuZXR3b3JrX2lkagQAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:monster_egg", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lk+hgAAAoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGUFAHN0b25lAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:monster_egg", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lk+xgAAAoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGULAGNvYmJsZXN0b25lAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:monster_egg", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lk/BgAAAoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGULAHN0b25lX2JyaWNrAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:monster_egg", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lk/RgAAAoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGURAG1vc3N5X3N0b25lX2JyaWNrAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:monster_egg", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lk/hgAAAoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGUTAGNyYWNrZWRfc3RvbmVfYnJpY2sAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:monster_egg", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lk/xgAAAoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGUUAGNoaXNlbGVkX3N0b25lX2JyaWNrAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:infested_deepslate", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmluZmVzdGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaICF2VYccxF1AwoAbmV0d29ya19pZMscAAAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:dragon_egg", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmRyYWdvbl9lZ2cECQBuYW1lX2hhc2inMzXrV+/e1wMKAG5ldHdvcmtfaWQ6LwAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:turtle_egg", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnR1cnRsZV9lZ2cECQBuYW1lX2hhc2iwSRcxOJIJ9gMKAG5ldHdvcmtfaWQaMgAACgYAc3RhdGVzCA0AY3JhY2tlZF9zdGF0ZQkAbm9fY3JhY2tzCBAAdHVydGxlX2VnZ19jb3VudAcAb25lX2VnZwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:sniffer_egg", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnNuaWZmZXJfZWdnBAkAbmFtZV9oYXNoY1lozc8lPcYDCgBuZXR3b3JrX2lkgCwAAAoGAHN0YXRlcwgNAGNyYWNrZWRfc3RhdGUJAG5vX2NyYWNrcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:frog_spawn", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmZyb2dfc3Bhd24ECQBuYW1lX2hhc2iWmd7idp3ZZwMKAG5ldHdvcmtfaWQoGgAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:pearlescent_froglight", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnBlYXJsZXNjZW50X2Zyb2dsaWdodAQJAG5hbWVfaGFzaKkcFRyycYGyAwoAbmV0d29ya19pZEAqAAAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:verdant_froglight", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnZlcmRhbnRfZnJvZ2xpZ2h0BAkAbmFtZV9oYXNoA+eXuTBohrQDCgBuZXR3b3JrX2lkeioAAAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:ochre_froglight", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om9jaHJlX2Zyb2dsaWdodAQJAG5hbWVfaGFzaMY59kjPe+c3AwoAbmV0d29ya19pZHoTAAAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:chicken_spawn_egg" - }, - { - "id": "minecraft:bee_spawn_egg" - }, - { - "id": "minecraft:cow_spawn_egg" - }, - { - "id": "minecraft:pig_spawn_egg" - }, - { - "id": "minecraft:sheep_spawn_egg" - }, - { - "id": "minecraft:wolf_spawn_egg" - }, - { - "id": "minecraft:polar_bear_spawn_egg" - }, - { - "id": "minecraft:ocelot_spawn_egg" - }, - { - "id": "minecraft:cat_spawn_egg" - }, - { - "id": "minecraft:mooshroom_spawn_egg" - }, - { - "id": "minecraft:bat_spawn_egg" - }, - { - "id": "minecraft:parrot_spawn_egg" - }, - { - "id": "minecraft:rabbit_spawn_egg" - }, - { - "id": "minecraft:llama_spawn_egg" - }, - { - "id": "minecraft:horse_spawn_egg" - }, - { - "id": "minecraft:donkey_spawn_egg" - }, - { - "id": "minecraft:mule_spawn_egg" - }, - { - "id": "minecraft:skeleton_horse_spawn_egg" - }, - { - "id": "minecraft:zombie_horse_spawn_egg" - }, - { - "id": "minecraft:tropical_fish_spawn_egg" - }, - { - "id": "minecraft:cod_spawn_egg" - }, - { - "id": "minecraft:pufferfish_spawn_egg" - }, - { - "id": "minecraft:salmon_spawn_egg" - }, - { - "id": "minecraft:dolphin_spawn_egg" - }, - { - "id": "minecraft:turtle_spawn_egg" - }, - { - "id": "minecraft:panda_spawn_egg" - }, - { - "id": "minecraft:fox_spawn_egg" - }, - { - "id": "minecraft:creeper_spawn_egg" - }, - { - "id": "minecraft:enderman_spawn_egg" - }, - { - "id": "minecraft:silverfish_spawn_egg" - }, - { - "id": "minecraft:skeleton_spawn_egg" - }, - { - "id": "minecraft:wither_skeleton_spawn_egg" - }, - { - "id": "minecraft:stray_spawn_egg" - }, - { - "id": "minecraft:slime_spawn_egg" - }, - { - "id": "minecraft:spider_spawn_egg" - }, - { - "id": "minecraft:zombie_spawn_egg" - }, - { - "id": "minecraft:zombie_pigman_spawn_egg" - }, - { - "id": "minecraft:husk_spawn_egg" - }, - { - "id": "minecraft:drowned_spawn_egg" - }, - { - "id": "minecraft:squid_spawn_egg" - }, - { - "id": "minecraft:glow_squid_spawn_egg" - }, - { - "id": "minecraft:cave_spider_spawn_egg" - }, - { - "id": "minecraft:witch_spawn_egg" - }, - { - "id": "minecraft:guardian_spawn_egg" - }, - { - "id": "minecraft:elder_guardian_spawn_egg" - }, - { - "id": "minecraft:endermite_spawn_egg" - }, - { - "id": "minecraft:magma_cube_spawn_egg" - }, - { - "id": "minecraft:strider_spawn_egg" - }, - { - "id": "minecraft:hoglin_spawn_egg" - }, - { - "id": "minecraft:piglin_spawn_egg" - }, - { - "id": "minecraft:zoglin_spawn_egg" - }, - { - "id": "minecraft:piglin_brute_spawn_egg" - }, - { - "id": "minecraft:goat_spawn_egg" - }, - { - "id": "minecraft:axolotl_spawn_egg" - }, - { - "id": "minecraft:warden_spawn_egg" - }, - { - "id": "minecraft:allay_spawn_egg" - }, - { - "id": "minecraft:frog_spawn_egg" - }, - { - "id": "minecraft:tadpole_spawn_egg" - }, - { - "id": "minecraft:trader_llama_spawn_egg" - }, - { - "id": "minecraft:camel_spawn_egg" - }, - { - "id": "minecraft:ghast_spawn_egg" - }, - { - "id": "minecraft:blaze_spawn_egg" - }, - { - "id": "minecraft:shulker_spawn_egg" - }, - { - "id": "minecraft:vindicator_spawn_egg" - }, - { - "id": "minecraft:evoker_spawn_egg" - }, - { - "id": "minecraft:vex_spawn_egg" - }, - { - "id": "minecraft:villager_spawn_egg" - }, - { - "id": "minecraft:wandering_trader_spawn_egg" - }, - { - "id": "minecraft:zombie_villager_spawn_egg" - }, - { - "id": "minecraft:phantom_spawn_egg" - }, - { - "id": "minecraft:pillager_spawn_egg" - }, - { - "id": "minecraft:ravager_spawn_egg" - }, - { - "id": "minecraft:iron_golem_spawn_egg" - }, - { - "id": "minecraft:snow_golem_spawn_egg" - }, - { - "id": "minecraft:sniffer_spawn_egg" - }, - { - "id": "minecraft:obsidian", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0Om9ic2lkaWFuBAkAbmFtZV9oYXNoiz4qrb8QjyEDCgBuZXR3b3JrX2lkhQQAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:crying_obsidian", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmNyeWluZ19vYnNpZGlhbgQJAG5hbWVfaGFzaKT0JlA7Z1K+AwoAbmV0d29ya19pZForAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:bedrock", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmJlZHJvY2sECQBuYW1lX2hhc2hWfFrh4LVtxwMKAG5ldHdvcmtfaWSRLAAACgYAc3RhdGVzAQ4AaW5maW5pYnVybl9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:soul_sand", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnNvdWxfc2FuZAQJAG5hbWVfaGFzaMaf+bccu+KTAwoAbmV0d29ya19pZBMjAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:magma", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0Om1hZ21hBAkAbmFtZV9oYXNoqyTjKaIsWfYDCgBuZXR3b3JrX2lkJjIAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:nether_wart" - }, - { - "id": "minecraft:end_stone", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmVuZF9zdG9uZQQJAG5hbWVfaGFzaH1J9jA39GJNAwoAbmV0d29ya19pZMYXAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:chorus_flower", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNob3J1c19mbG93ZXIECQBuYW1lX2hhc2iMpSodli5uawMKAG5ldHdvcmtfaWSvGgAACgYAc3RhdGVzAwMAYWdlAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:chorus_plant", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmNob3J1c19wbGFudAQJAG5hbWVfaGFzaJhSrmNGKwaMAwoAbmV0d29ya19pZMshAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:chorus_fruit" - }, - { - "id": "minecraft:popped_chorus_fruit" - }, - { - "id": "minecraft:sponge", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnNwb25nZQQJAG5hbWVfaGFzaLrd2ScYRDMiAwoAbmV0d29ya19pZDkFAAAKBgBzdGF0ZXMICwBzcG9uZ2VfdHlwZQMAZHJ5AAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:sponge", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnNwb25nZQQJAG5hbWVfaGFzaLrd2ScYRDMiAwoAbmV0d29ya19pZDoFAAAKBgBzdGF0ZXMICwBzcG9uZ2VfdHlwZQMAd2V0AAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:coral_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkuyAAAAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABibHVlAQgAZGVhZF9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:coral_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkvCAAAAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABwaW5rAQgAZGVhZF9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:coral_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkvSAAAAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgBwdXJwbGUBCABkZWFkX2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:coral_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkviAAAAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yAwByZWQBCABkZWFkX2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:coral_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkvyAAAAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgB5ZWxsb3cBCABkZWFkX2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:coral_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkwCAAAAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABibHVlAQgAZGVhZF9iaXQBAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:coral_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkwSAAAAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABwaW5rAQgAZGVhZF9iaXQBAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:coral_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkwiAAAAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgBwdXJwbGUBCABkZWFkX2JpdAEAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:coral_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkwyAAAAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yAwByZWQBCABkZWFkX2JpdAEAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:coral_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkxCAAAAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgB5ZWxsb3cBCABkZWFkX2JpdAEAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:sculk", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnNjdWxrBAkAbmFtZV9oYXNo2Lq7T5yQF8kDCgBuZXR3b3JrX2lkpSwAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:sculk_vein", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnNjdWxrX3ZlaW4ECQBuYW1lX2hhc2gJUdhVooV4zwMKAG5ldHdvcmtfaWSWLgAACgYAc3RhdGVzAxkAbXVsdGlfZmFjZV9kaXJlY3Rpb25fYml0cwAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:sculk_catalyst", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnNjdWxrX2NhdGFseXN0BAkAbmFtZV9oYXNo+gCpbrCHST4DCgBuZXR3b3JrX2lkZRUAAAoGAHN0YXRlcwEFAGJsb29tAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:sculk_shrieker", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnNjdWxrX3Nocmlla2VyBAkAbmFtZV9oYXNo5OXtyObniQ4DCgBuZXR3b3JrX2lkdQIAAAoGAHN0YXRlcwEGAGFjdGl2ZQABCgBjYW5fc3VtbW9uAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:sculk_sensor", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnNjdWxrX3NlbnNvcgQJAG5hbWVfaGFzaCkmHreeTgNnAwoAbmV0d29ya19pZB0aAAAKBgBzdGF0ZXMDEgBzY3Vsa19zZW5zb3JfcGhhc2UAAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:calibrated_sculk_sensor", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmNhbGlicmF0ZWRfc2N1bGtfc2Vuc29yBAkAbmFtZV9oYXNoffAcXXN/iJUDCgBuZXR3b3JrX2lkqCQAAAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAADEgBzY3Vsa19zZW5zb3JfcGhhc2UAAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:reinforced_deepslate", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnJlaW5mb3JjZWRfZGVlcHNsYXRlBAkAbmFtZV9oYXNoldDmj91EapQDCgBuZXR3b3JrX2lklCQAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:leather_helmet" - }, - { - "id": "minecraft:chainmail_helmet" - }, - { - "id": "minecraft:iron_helmet" - }, - { - "id": "minecraft:golden_helmet" - }, - { - "id": "minecraft:diamond_helmet" - }, - { - "id": "minecraft:netherite_helmet" - }, - { - "id": "minecraft:leather_chestplate" - }, - { - "id": "minecraft:chainmail_chestplate" - }, - { - "id": "minecraft:iron_chestplate" - }, - { - "id": "minecraft:golden_chestplate" - }, - { - "id": "minecraft:diamond_chestplate" - }, - { - "id": "minecraft:netherite_chestplate" - }, - { - "id": "minecraft:leather_leggings" - }, - { - "id": "minecraft:chainmail_leggings" - }, - { - "id": "minecraft:iron_leggings" - }, - { - "id": "minecraft:golden_leggings" - }, - { - "id": "minecraft:diamond_leggings" - }, - { - "id": "minecraft:netherite_leggings" - }, - { - "id": "minecraft:leather_boots" - }, - { - "id": "minecraft:chainmail_boots" - }, - { - "id": "minecraft:iron_boots" - }, - { - "id": "minecraft:golden_boots" - }, - { - "id": "minecraft:diamond_boots" - }, - { - "id": "minecraft:netherite_boots" - }, - { - "id": "minecraft:wooden_sword" - }, - { - "id": "minecraft:stone_sword" - }, - { - "id": "minecraft:iron_sword" - }, - { - "id": "minecraft:golden_sword" - }, - { - "id": "minecraft:diamond_sword" - }, - { - "id": "minecraft:netherite_sword" - }, - { - "id": "minecraft:wooden_axe" - }, - { - "id": "minecraft:stone_axe" - }, - { - "id": "minecraft:iron_axe" - }, - { - "id": "minecraft:golden_axe" - }, - { - "id": "minecraft:diamond_axe" - }, - { - "id": "minecraft:netherite_axe" - }, - { - "id": "minecraft:wooden_pickaxe" - }, - { - "id": "minecraft:stone_pickaxe" - }, - { - "id": "minecraft:iron_pickaxe" - }, - { - "id": "minecraft:golden_pickaxe" - }, - { - "id": "minecraft:diamond_pickaxe" - }, - { - "id": "minecraft:netherite_pickaxe" - }, - { - "id": "minecraft:wooden_shovel" - }, - { - "id": "minecraft:stone_shovel" - }, - { - "id": "minecraft:iron_shovel" - }, - { - "id": "minecraft:golden_shovel" - }, - { - "id": "minecraft:diamond_shovel" - }, - { - "id": "minecraft:netherite_shovel" - }, - { - "id": "minecraft:wooden_hoe" - }, - { - "id": "minecraft:stone_hoe" - }, - { - "id": "minecraft:iron_hoe" - }, - { - "id": "minecraft:golden_hoe" - }, - { - "id": "minecraft:diamond_hoe" - }, - { - "id": "minecraft:netherite_hoe" - }, - { - "id": "minecraft:bow" - }, - { - "id": "minecraft:crossbow" - }, - { - "id": "minecraft:arrow" - }, - { - "id": "minecraft:arrow", - "damage": 6 - }, - { - "id": "minecraft:arrow", - "damage": 7 - }, - { - "id": "minecraft:arrow", - "damage": 8 - }, - { - "id": "minecraft:arrow", - "damage": 9 - }, - { - "id": "minecraft:arrow", - "damage": 10 - }, - { - "id": "minecraft:arrow", - "damage": 11 - }, - { - "id": "minecraft:arrow", - "damage": 12 - }, - { - "id": "minecraft:arrow", - "damage": 13 - }, - { - "id": "minecraft:arrow", - "damage": 14 - }, - { - "id": "minecraft:arrow", - "damage": 15 - }, - { - "id": "minecraft:arrow", - "damage": 16 - }, - { - "id": "minecraft:arrow", - "damage": 17 - }, - { - "id": "minecraft:arrow", - "damage": 18 - }, - { - "id": "minecraft:arrow", - "damage": 19 - }, - { - "id": "minecraft:arrow", - "damage": 20 - }, - { - "id": "minecraft:arrow", - "damage": 21 - }, - { - "id": "minecraft:arrow", - "damage": 22 - }, - { - "id": "minecraft:arrow", - "damage": 23 - }, - { - "id": "minecraft:arrow", - "damage": 24 - }, - { - "id": "minecraft:arrow", - "damage": 25 - }, - { - "id": "minecraft:arrow", - "damage": 26 - }, - { - "id": "minecraft:arrow", - "damage": 27 - }, - { - "id": "minecraft:arrow", - "damage": 28 - }, - { - "id": "minecraft:arrow", - "damage": 29 - }, - { - "id": "minecraft:arrow", - "damage": 30 - }, - { - "id": "minecraft:arrow", - "damage": 31 - }, - { - "id": "minecraft:arrow", - "damage": 32 - }, - { - "id": "minecraft:arrow", - "damage": 33 - }, - { - "id": "minecraft:arrow", - "damage": 34 - }, - { - "id": "minecraft:arrow", - "damage": 35 - }, - { - "id": "minecraft:arrow", - "damage": 36 - }, - { - "id": "minecraft:arrow", - "damage": 37 - }, - { - "id": "minecraft:arrow", - "damage": 38 - }, - { - "id": "minecraft:arrow", - "damage": 39 - }, - { - "id": "minecraft:arrow", - "damage": 40 - }, - { - "id": "minecraft:arrow", - "damage": 41 - }, - { - "id": "minecraft:arrow", - "damage": 42 - }, - { - "id": "minecraft:arrow", - "damage": 43 - }, - { - "id": "minecraft:shield" - }, - { - "id": "minecraft:cooked_chicken" - }, - { - "id": "minecraft:cooked_porkchop" - }, - { - "id": "minecraft:cooked_beef" - }, - { - "id": "minecraft:cooked_mutton" - }, - { - "id": "minecraft:cooked_rabbit" - }, - { - "id": "minecraft:cooked_cod" - }, - { - "id": "minecraft:cooked_salmon" - }, - { - "id": "minecraft:bread" - }, - { - "id": "minecraft:mushroom_stew" - }, - { - "id": "minecraft:beetroot_soup" - }, - { - "id": "minecraft:rabbit_stew" - }, - { - "id": "minecraft:baked_potato" - }, - { - "id": "minecraft:cookie" - }, - { - "id": "minecraft:pumpkin_pie" - }, - { - "id": "minecraft:cake" - }, - { - "id": "minecraft:dried_kelp" - }, - { - "id": "minecraft:fishing_rod" - }, - { - "id": "minecraft:carrot_on_a_stick" - }, - { - "id": "minecraft:warped_fungus_on_a_stick" - }, - { - "id": "minecraft:snowball" - }, - { - "id": "minecraft:shears" - }, - { - "id": "minecraft:flint_and_steel" - }, - { - "id": "minecraft:lead" - }, - { - "id": "minecraft:clock" - }, - { - "id": "minecraft:compass" - }, - { - "id": "minecraft:recovery_compass" - }, - { - "id": "minecraft:goat_horn" - }, - { - "id": "minecraft:goat_horn", - "damage": 1 - }, - { - "id": "minecraft:goat_horn", - "damage": 2 - }, - { - "id": "minecraft:goat_horn", - "damage": 3 - }, - { - "id": "minecraft:goat_horn", - "damage": 4 - }, - { - "id": "minecraft:goat_horn", - "damage": 5 - }, - { - "id": "minecraft:goat_horn", - "damage": 6 - }, - { - "id": "minecraft:goat_horn", - "damage": 7 - }, - { - "id": "minecraft:empty_map" - }, - { - "id": "minecraft:empty_map", - "damage": 2 - }, - { - "id": "minecraft:saddle" - }, - { - "id": "minecraft:leather_horse_armor" - }, - { - "id": "minecraft:iron_horse_armor" - }, - { - "id": "minecraft:golden_horse_armor" - }, - { - "id": "minecraft:diamond_horse_armor" - }, - { - "id": "minecraft:trident" - }, - { - "id": "minecraft:turtle_helmet" - }, - { - "id": "minecraft:elytra" - }, - { - "id": "minecraft:totem_of_undying" - }, - { - "id": "minecraft:glass_bottle" - }, - { - "id": "minecraft:experience_bottle" - }, - { - "id": "minecraft:potion" - }, - { - "id": "minecraft:potion", - "damage": 1 - }, - { - "id": "minecraft:potion", - "damage": 2 - }, - { - "id": "minecraft:potion", - "damage": 3 - }, - { - "id": "minecraft:potion", - "damage": 4 - }, - { - "id": "minecraft:potion", - "damage": 5 - }, - { - "id": "minecraft:potion", - "damage": 6 - }, - { - "id": "minecraft:potion", - "damage": 7 - }, - { - "id": "minecraft:potion", - "damage": 8 - }, - { - "id": "minecraft:potion", - "damage": 9 - }, - { - "id": "minecraft:potion", - "damage": 10 - }, - { - "id": "minecraft:potion", - "damage": 11 - }, - { - "id": "minecraft:potion", - "damage": 12 - }, - { - "id": "minecraft:potion", - "damage": 13 - }, - { - "id": "minecraft:potion", - "damage": 14 - }, - { - "id": "minecraft:potion", - "damage": 15 - }, - { - "id": "minecraft:potion", - "damage": 16 - }, - { - "id": "minecraft:potion", - "damage": 17 - }, - { - "id": "minecraft:potion", - "damage": 18 - }, - { - "id": "minecraft:potion", - "damage": 19 - }, - { - "id": "minecraft:potion", - "damage": 20 - }, - { - "id": "minecraft:potion", - "damage": 21 - }, - { - "id": "minecraft:potion", - "damage": 22 - }, - { - "id": "minecraft:potion", - "damage": 23 - }, - { - "id": "minecraft:potion", - "damage": 24 - }, - { - "id": "minecraft:potion", - "damage": 25 - }, - { - "id": "minecraft:potion", - "damage": 26 - }, - { - "id": "minecraft:potion", - "damage": 27 - }, - { - "id": "minecraft:potion", - "damage": 28 - }, - { - "id": "minecraft:potion", - "damage": 29 - }, - { - "id": "minecraft:potion", - "damage": 30 - }, - { - "id": "minecraft:potion", - "damage": 31 - }, - { - "id": "minecraft:potion", - "damage": 32 - }, - { - "id": "minecraft:potion", - "damage": 33 - }, - { - "id": "minecraft:potion", - "damage": 34 - }, - { - "id": "minecraft:potion", - "damage": 35 - }, - { - "id": "minecraft:potion", - "damage": 36 - }, - { - "id": "minecraft:potion", - "damage": 37 - }, - { - "id": "minecraft:potion", - "damage": 38 - }, - { - "id": "minecraft:potion", - "damage": 39 - }, - { - "id": "minecraft:potion", - "damage": 40 - }, - { - "id": "minecraft:potion", - "damage": 41 - }, - { - "id": "minecraft:potion", - "damage": 42 - }, - { - "id": "minecraft:splash_potion" - }, - { - "id": "minecraft:splash_potion", - "damage": 1 - }, - { - "id": "minecraft:splash_potion", - "damage": 2 - }, - { - "id": "minecraft:splash_potion", - "damage": 3 - }, - { - "id": "minecraft:splash_potion", - "damage": 4 - }, - { - "id": "minecraft:splash_potion", - "damage": 5 - }, - { - "id": "minecraft:splash_potion", - "damage": 6 - }, - { - "id": "minecraft:splash_potion", - "damage": 7 - }, - { - "id": "minecraft:splash_potion", - "damage": 8 - }, - { - "id": "minecraft:splash_potion", - "damage": 9 - }, - { - "id": "minecraft:splash_potion", - "damage": 10 - }, - { - "id": "minecraft:splash_potion", - "damage": 11 - }, - { - "id": "minecraft:splash_potion", - "damage": 12 - }, - { - "id": "minecraft:splash_potion", - "damage": 13 - }, - { - "id": "minecraft:splash_potion", - "damage": 14 - }, - { - "id": "minecraft:splash_potion", - "damage": 15 - }, - { - "id": "minecraft:splash_potion", - "damage": 16 - }, - { - "id": "minecraft:splash_potion", - "damage": 17 - }, - { - "id": "minecraft:splash_potion", - "damage": 18 - }, - { - "id": "minecraft:splash_potion", - "damage": 19 - }, - { - "id": "minecraft:splash_potion", - "damage": 20 - }, - { - "id": "minecraft:splash_potion", - "damage": 21 - }, - { - "id": "minecraft:splash_potion", - "damage": 22 - }, - { - "id": "minecraft:splash_potion", - "damage": 23 - }, - { - "id": "minecraft:splash_potion", - "damage": 24 - }, - { - "id": "minecraft:splash_potion", - "damage": 25 - }, - { - "id": "minecraft:splash_potion", - "damage": 26 - }, - { - "id": "minecraft:splash_potion", - "damage": 27 - }, - { - "id": "minecraft:splash_potion", - "damage": 28 - }, - { - "id": "minecraft:splash_potion", - "damage": 29 - }, - { - "id": "minecraft:splash_potion", - "damage": 30 - }, - { - "id": "minecraft:splash_potion", - "damage": 31 - }, - { - "id": "minecraft:splash_potion", - "damage": 32 - }, - { - "id": "minecraft:splash_potion", - "damage": 33 - }, - { - "id": "minecraft:splash_potion", - "damage": 34 - }, - { - "id": "minecraft:splash_potion", - "damage": 35 - }, - { - "id": "minecraft:splash_potion", - "damage": 36 - }, - { - "id": "minecraft:splash_potion", - "damage": 37 - }, - { - "id": "minecraft:splash_potion", - "damage": 38 - }, - { - "id": "minecraft:splash_potion", - "damage": 39 - }, - { - "id": "minecraft:splash_potion", - "damage": 40 - }, - { - "id": "minecraft:splash_potion", - "damage": 41 - }, - { - "id": "minecraft:splash_potion", - "damage": 42 - }, - { - "id": "minecraft:lingering_potion" - }, - { - "id": "minecraft:lingering_potion", - "damage": 1 - }, - { - "id": "minecraft:lingering_potion", - "damage": 2 - }, - { - "id": "minecraft:lingering_potion", - "damage": 3 - }, - { - "id": "minecraft:lingering_potion", - "damage": 4 - }, - { - "id": "minecraft:lingering_potion", - "damage": 5 - }, - { - "id": "minecraft:lingering_potion", - "damage": 6 - }, - { - "id": "minecraft:lingering_potion", - "damage": 7 - }, - { - "id": "minecraft:lingering_potion", - "damage": 8 - }, - { - "id": "minecraft:lingering_potion", - "damage": 9 - }, - { - "id": "minecraft:lingering_potion", - "damage": 10 - }, - { - "id": "minecraft:lingering_potion", - "damage": 11 - }, - { - "id": "minecraft:lingering_potion", - "damage": 12 - }, - { - "id": "minecraft:lingering_potion", - "damage": 13 - }, - { - "id": "minecraft:lingering_potion", - "damage": 14 - }, - { - "id": "minecraft:lingering_potion", - "damage": 15 - }, - { - "id": "minecraft:lingering_potion", - "damage": 16 - }, - { - "id": "minecraft:lingering_potion", - "damage": 17 - }, - { - "id": "minecraft:lingering_potion", - "damage": 18 - }, - { - "id": "minecraft:lingering_potion", - "damage": 19 - }, - { - "id": "minecraft:lingering_potion", - "damage": 20 - }, - { - "id": "minecraft:lingering_potion", - "damage": 21 - }, - { - "id": "minecraft:lingering_potion", - "damage": 22 - }, - { - "id": "minecraft:lingering_potion", - "damage": 23 - }, - { - "id": "minecraft:lingering_potion", - "damage": 24 - }, - { - "id": "minecraft:lingering_potion", - "damage": 25 - }, - { - "id": "minecraft:lingering_potion", - "damage": 26 - }, - { - "id": "minecraft:lingering_potion", - "damage": 27 - }, - { - "id": "minecraft:lingering_potion", - "damage": 28 - }, - { - "id": "minecraft:lingering_potion", - "damage": 29 - }, - { - "id": "minecraft:lingering_potion", - "damage": 30 - }, - { - "id": "minecraft:lingering_potion", - "damage": 31 - }, - { - "id": "minecraft:lingering_potion", - "damage": 32 - }, - { - "id": "minecraft:lingering_potion", - "damage": 33 - }, - { - "id": "minecraft:lingering_potion", - "damage": 34 - }, - { - "id": "minecraft:lingering_potion", - "damage": 35 - }, - { - "id": "minecraft:lingering_potion", - "damage": 36 - }, - { - "id": "minecraft:lingering_potion", - "damage": 37 - }, - { - "id": "minecraft:lingering_potion", - "damage": 38 - }, - { - "id": "minecraft:lingering_potion", - "damage": 39 - }, - { - "id": "minecraft:lingering_potion", - "damage": 40 - }, - { - "id": "minecraft:lingering_potion", - "damage": 41 - }, - { - "id": "minecraft:lingering_potion", - "damage": 42 - }, - { - "id": "minecraft:spyglass" - }, - { - "id": "minecraft:brush" - }, - { - "id": "minecraft:stick" - }, - { - "id": "minecraft:bed" - }, - { - "id": "minecraft:bed", - "damage": 8 - }, - { - "id": "minecraft:bed", - "damage": 7 - }, - { - "id": "minecraft:bed", - "damage": 15 - }, - { - "id": "minecraft:bed", - "damage": 12 - }, - { - "id": "minecraft:bed", - "damage": 14 - }, - { - "id": "minecraft:bed", - "damage": 1 - }, - { - "id": "minecraft:bed", - "damage": 4 - }, - { - "id": "minecraft:bed", - "damage": 5 - }, - { - "id": "minecraft:bed", - "damage": 13 - }, - { - "id": "minecraft:bed", - "damage": 9 - }, - { - "id": "minecraft:bed", - "damage": 3 - }, - { - "id": "minecraft:bed", - "damage": 11 - }, - { - "id": "minecraft:bed", - "damage": 10 - }, - { - "id": "minecraft:bed", - "damage": 2 - }, - { - "id": "minecraft:bed", - "damage": 6 - }, - { - "id": "minecraft:torch", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnRvcmNoBAkAbmFtZV9oYXNoagn7rmDBzisDCgBuZXR3b3JrX2lkGAcAAAoGAHN0YXRlcwgWAHRvcmNoX2ZhY2luZ19kaXJlY3Rpb24HAHVua25vd24AAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:soul_torch", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnNvdWxfdG9yY2gECQBuYW1lX2hhc2huixOT04BRdQMKAG5ldHdvcmtfaWTOHAAACgYAc3RhdGVzCBYAdG9yY2hfZmFjaW5nX2RpcmVjdGlvbgcAdW5rbm93bgADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:sea_pickle", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnNlYV9waWNrbGUECQBuYW1lX2hhc2iONEfZJB+glgMKAG5ldHdvcmtfaWS7JAAACgYAc3RhdGVzAw0AY2x1c3Rlcl9jb3VudAAAAAABCABkZWFkX2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:lantern", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmxhbnRlcm4ECQBuYW1lX2hhc2hMw44VI2HWygMKAG5ldHdvcmtfaWTMLAAACgYAc3RhdGVzAQcAaGFuZ2luZwAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:soul_lantern", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnNvdWxfbGFudGVybgQJAG5hbWVfaGFzaGjIpjxk9z+RAwoAbmV0d29ya19pZMEiAAAKBgBzdGF0ZXMBBwBoYW5naW5nAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:candle", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmNhbmRsZQQJAG5hbWVfaGFzaHPd+MsNdWTfAwoAbmV0d29ya19pZLsvAAAKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:white_candle", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OndoaXRlX2NhbmRsZQQJAG5hbWVfaGFzaN1EG5Q1mHiEAwoAbmV0d29ya19pZAohAAAKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:orange_candle", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Om9yYW5nZV9jYW5kbGUECQBuYW1lX2hhc2jySEVWHgUIHQMKAG5ldHdvcmtfaWRBBAAACgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:magenta_candle", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hZ2VudGFfY2FuZGxlBAkAbmFtZV9oYXNoG0u6YIOoBSEDCgBuZXR3b3JrX2lkewQAAAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:light_blue_candle", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY2FuZGxlBAkAbmFtZV9oYXNocXGeK0zgrG0DCgBuZXR3b3JrX2lk1hoAAAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:yellow_candle", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19jYW5kbGUECQBuYW1lX2hhc2i00dtusU3CqQMKAG5ldHdvcmtfaWQ+KQAACgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:lime_candle", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmxpbWVfY2FuZGxlBAkAbmFtZV9oYXNokcmrw5xvz7ADCgBuZXR3b3JrX2lk/SkAAAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:pink_candle", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfY2FuZGxlBAkAbmFtZV9oYXNoQJdEY4sZ0dwDCgBuZXR3b3JrX2lkmS8AAAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:gray_candle", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmdyYXlfY2FuZGxlBAkAbmFtZV9oYXNoS5poSo9wBDEDCgBuZXR3b3JrX2lkAAgAAAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:light_gray_candle", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY2FuZGxlBAkAbmFtZV9oYXNo9ruTZLBNMasDCgBuZXR3b3JrX2lkaykAAAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:cyan_candle", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmN5YW5fY2FuZGxlBAkAbmFtZV9oYXNoc/M8PNVcjOwDCgBuZXR3b3JrX2lkCDEAAAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:purple_candle", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnBsZV9jYW5kbGUECQBuYW1lX2hhc2jaI3xUW0/myQMKAG5ldHdvcmtfaWSnLAAACgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:blue_candle", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmJsdWVfY2FuZGxlBAkAbmFtZV9oYXNoAASSPW6TgQADCgBuZXR3b3JrX2lkAAAAAAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:brown_candle", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJyb3duX2NhbmRsZQQJAG5hbWVfaGFzaDia0l6s1+WYAwoAbmV0d29ya19pZF8mAAAKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:green_candle", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmdyZWVuX2NhbmRsZQQJAG5hbWVfaGFzaLeFPO1l+fIoAwoAbmV0d29ya19pZOoGAAAKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:red_candle", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9jYW5kbGUECQBuYW1lX2hhc2jjAQpGf59ZdwMKAG5ldHdvcmtfaWTzHAAACgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:black_candle", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJsYWNrX2NhbmRsZQQJAG5hbWVfaGFzaB+wRDpOqREKAwoAbmV0d29ya19pZEECAAAKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:crafting_table", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyYWZ0aW5nX3RhYmxlBAkAbmFtZV9oYXNoe76VAmjvbpYDCgBuZXR3b3JrX2lkuiQAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:cartography_table", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmNhcnRvZ3JhcGh5X3RhYmxlBAkAbmFtZV9oYXNomaWiiD/znP8DCgBuZXR3b3JrX2lkVDMAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:fletching_table", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmZsZXRjaGluZ190YWJsZQQJAG5hbWVfaGFzaPFibh8unKyUAwoAbmV0d29ya19pZJUkAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:smithing_table", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnNtaXRoaW5nX3RhYmxlBAkAbmFtZV9oYXNo4tFES2xOXEYDCgBuZXR3b3JrX2lk2RUAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:beehive", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmJlZWhpdmUECQBuYW1lX2hhc2hCcqn12UbNpwMKAG5ldHdvcmtfaWTqKAAACgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAMLAGhvbmV5X2xldmVsAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:suspicious_sand", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnN1c3BpY2lvdXNfc2FuZAQJAG5hbWVfaGFzaL67QsuvLP00AwoAbmV0d29ya19pZNAIAAAKBgBzdGF0ZXMDEABicnVzaGVkX3Byb2dyZXNzAAAAAAEHAGhhbmdpbmcBAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:suspicious_gravel", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN1c3BpY2lvdXNfZ3JhdmVsBAkAbmFtZV9oYXNoJSVbGNk7C3oDCgBuZXR3b3JrX2lkKB0AAAoGAHN0YXRlcwMQAGJydXNoZWRfcHJvZ3Jlc3MAAAAAAQcAaGFuZ2luZwEAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:campfire" - }, - { - "id": "minecraft:soul_campfire" - }, - { - "id": "minecraft:furnace", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmZ1cm5hY2UECQBuYW1lX2hhc2ioOQrludYY8wMKAG5ldHdvcmtfaWRXMQAACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:blast_furnace", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmJsYXN0X2Z1cm5hY2UECQBuYW1lX2hhc2ivDbnjkpGm5QMKAG5ldHdvcmtfaWRhMAAACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:smoker", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnNtb2tlcgQJAG5hbWVfaGFzaJd1rDMkRWomAwoAbmV0d29ya19pZMwGAAAKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:respawn_anchor", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnJlc3Bhd25fYW5jaG9yBAkAbmFtZV9oYXNoZOdcjW05qigDCgBuZXR3b3JrX2lk5AYAAAoGAHN0YXRlcwMVAHJlc3Bhd25fYW5jaG9yX2NoYXJnZQAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:brewing_stand" - }, - { - "id": "minecraft:anvil", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmFudmlsBAkAbmFtZV9oYXNoNqB3fgcUCbwDCgBuZXR3b3JrX2lkDCsAAAoGAHN0YXRlcwgGAGRhbWFnZQkAdW5kYW1hZ2VkAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:anvil", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmFudmlsBAkAbmFtZV9oYXNoNqB3fgcUCbwDCgBuZXR3b3JrX2lkECsAAAoGAHN0YXRlcwgGAGRhbWFnZRAAc2xpZ2h0bHlfZGFtYWdlZAMJAGRpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:anvil", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmFudmlsBAkAbmFtZV9oYXNoNqB3fgcUCbwDCgBuZXR3b3JrX2lkFCsAAAoGAHN0YXRlcwgGAGRhbWFnZQwAdmVyeV9kYW1hZ2VkAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:grindstone", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmdyaW5kc3RvbmUECQBuYW1lX2hhc2id56zc0nk99wMKAG5ldHdvcmtfaWREMgAACgYAc3RhdGVzCAoAYXR0YWNobWVudAgAc3RhbmRpbmcDCQBkaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:enchanting_table", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmVuY2hhbnRpbmdfdGFibGUECQBuYW1lX2hhc2jgIx24VLvMvwMKAG5ldHdvcmtfaWRgKwAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:bookshelf", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmJvb2tzaGVsZgQJAG5hbWVfaGFzaDU04DrgJCS9AwoAbmV0d29ya19pZDErAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:chiseled_bookshelf", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmNoaXNlbGVkX2Jvb2tzaGVsZgQJAG5hbWVfaGFzaNXDBnsIsywYAwoAbmV0d29ya19pZPgCAAAKBgBzdGF0ZXMDDABib29rc19zdG9yZWQAAAAAAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:lectern", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmxlY3Rlcm4ECQBuYW1lX2hhc2j5Z4Mmi/1QxAMKAG5ldHdvcmtfaWRALAAACgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAHBvd2VyZWRfYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:cauldron" - }, - { - "id": "minecraft:composter", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmNvbXBvc3RlcgQJAG5hbWVfaGFzaPAADHptzeWJAwoAbmV0d29ya19pZHAhAAAKBgBzdGF0ZXMDFABjb21wb3N0ZXJfZmlsbF9sZXZlbAAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:chest", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmNoZXN0BAkAbmFtZV9oYXNog9ozMxlcA88DCgBuZXR3b3JrX2lk9ywAAAoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:trapped_chest", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnRyYXBwZWRfY2hlc3QECQBuYW1lX2hhc2g2qpF9stsEjgMKAG5ldHdvcmtfaWQZIgAACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:ender_chest", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmVuZGVyX2NoZXN0BAkAbmFtZV9oYXNohEZzOFdg0WUDCgBuZXR3b3JrX2lkCBoAAAoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:barrel", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmJhcnJlbAQJAG5hbWVfaGFzaHDkRPGymiRqAwoAbmV0d29ya19pZKMaAAAKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:undyed_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnVuZHllZF9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaOC9mypm/MlBAwoAbmV0d29ya19pZKwVAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:white_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OndoaXRlX3NodWxrZXJfYm94BAkAbmFtZV9oYXNosK79m1rPUBwDCgBuZXR3b3JrX2lkPwQAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:light_gray_shulker_box", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2iBe5zq7PxHmgMKAG5ldHdvcmtfaWR/JgAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:gray_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmdyYXlfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2ga2s8ctjHUhgMKAG5ldHdvcmtfaWQtIQAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:black_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmJsYWNrX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoPm03OZphrp8DCgBuZXR3b3JrX2lkhSgAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:brown_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmJyb3duX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoT3DD6qAL9cADCgBuZXR3b3JrX2lkBSwAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:red_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnJlZF9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaMIlKSCzqSZoAwoAbmV0d29ya19pZEkaAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:orange_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0Om9yYW5nZV9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaG2MAXU67wGrAwoAbmV0d29ya19pZGopAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:yellow_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnllbGxvd19zaHVsa2VyX2JveAQJAG5hbWVfaGFzaIsLwQHYjcIEAwoAbmV0d29ya19pZHUAAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:lime_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmxpbWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2hUwBkg+faUGAMKAG5ldHdvcmtfaWQBBAAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:green_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmdyZWVuX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoZgUeT3LupLUDCgBuZXR3b3JrX2lkgioAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:cyan_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmN5YW5fc2h1bGtlcl9ib3gECQBuYW1lX2hhc2gSfbjteXg5yAMKAG5ldHdvcmtfaWScLAAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:light_blue_shulker_box", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2h0VFCX0qsRxQMKAG5ldHdvcmtfaWRbLAAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:blue_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmJsdWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2hn9gS0XIe6rAMKAG5ldHdvcmtfaWSTKQAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:purple_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnB1cnBsZV9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaEV/lkNPxRDdAwoAbmV0d29ya19pZKEvAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:magenta_shulker_box", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0Om1hZ2VudGFfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2iqWM7IJHxcFgMKAG5ldHdvcmtfaWTLAgAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:pink_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnBpbmtfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2in1tkJ1GNcZgMKAG5ldHdvcmtfaWQUGgAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:armor_stand" - }, - { - "id": "minecraft:noteblock", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0Om5vdGVibG9jawQJAG5hbWVfaGFzaHPA8dBBH0UaAwoAbmV0d29ya19pZC8EAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:jukebox", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0Omp1a2Vib3gECQBuYW1lX2hhc2ieAIPExf/ZfgMKAG5ldHdvcmtfaWQ9HwAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:music_disc_13" - }, - { - "id": "minecraft:music_disc_cat" - }, - { - "id": "minecraft:music_disc_blocks" - }, - { - "id": "minecraft:music_disc_chirp" - }, - { - "id": "minecraft:music_disc_far" - }, - { - "id": "minecraft:music_disc_mall" - }, - { - "id": "minecraft:music_disc_mellohi" - }, - { - "id": "minecraft:music_disc_stal" - }, - { - "id": "minecraft:music_disc_strad" - }, - { - "id": "minecraft:music_disc_ward" - }, - { - "id": "minecraft:music_disc_11" - }, - { - "id": "minecraft:music_disc_wait" - }, - { - "id": "minecraft:music_disc_otherside" - }, - { - "id": "minecraft:music_disc_5" - }, - { - "id": "minecraft:music_disc_pigstep" - }, - { - "id": "minecraft:music_disc_relic" - }, - { - "id": "minecraft:disc_fragment_5" - }, - { - "id": "minecraft:glowstone_dust" - }, - { - "id": "minecraft:glowstone", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0Omdsb3dzdG9uZQQJAG5hbWVfaGFzaFYqXNkefIlPAwoAbmV0d29ya19pZPcXAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:redstone_lamp", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZHN0b25lX2xhbXAECQBuYW1lX2hhc2hJ9V80caPvEgMKAG5ldHdvcmtfaWSXAgAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:sea_lantern", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnNlYV9sYW50ZXJuBAkAbmFtZV9oYXNoLPsv1TX9M+QDCgBuZXR3b3JrX2lkTDAAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:oak_sign" - }, - { - "id": "minecraft:spruce_sign" - }, - { - "id": "minecraft:birch_sign" - }, - { - "id": "minecraft:jungle_sign" - }, - { - "id": "minecraft:acacia_sign" - }, - { - "id": "minecraft:dark_oak_sign" - }, - { - "id": "minecraft:mangrove_sign" - }, - { - "id": "minecraft:cherry_sign" - }, - { - "id": "minecraft:bamboo_sign" - }, - { - "id": "minecraft:crimson_sign" - }, - { - "id": "minecraft:warped_sign" - }, - { - "id": "minecraft:oak_hanging_sign" - }, - { - "id": "minecraft:spruce_hanging_sign" - }, - { - "id": "minecraft:birch_hanging_sign" - }, - { - "id": "minecraft:jungle_hanging_sign" - }, - { - "id": "minecraft:acacia_hanging_sign" - }, - { - "id": "minecraft:dark_oak_hanging_sign" - }, - { - "id": "minecraft:mangrove_hanging_sign" - }, - { - "id": "minecraft:cherry_hanging_sign" - }, - { - "id": "minecraft:bamboo_hanging_sign" - }, - { - "id": "minecraft:crimson_hanging_sign" - }, - { - "id": "minecraft:warped_hanging_sign" - }, - { - "id": "minecraft:painting" - }, - { - "id": "minecraft:frame" - }, - { - "id": "minecraft:glow_frame" - }, - { - "id": "minecraft:honey_bottle" - }, - { - "id": "minecraft:flower_pot" - }, - { - "id": "minecraft:bowl" - }, - { - "id": "minecraft:bucket" - }, - { - "id": "minecraft:milk_bucket" - }, - { - "id": "minecraft:water_bucket" - }, - { - "id": "minecraft:lava_bucket" - }, - { - "id": "minecraft:cod_bucket" - }, - { - "id": "minecraft:salmon_bucket" - }, - { - "id": "minecraft:tropical_fish_bucket" - }, - { - "id": "minecraft:pufferfish_bucket" - }, - { - "id": "minecraft:powder_snow_bucket" - }, - { - "id": "minecraft:axolotl_bucket" - }, - { - "id": "minecraft:tadpole_bucket" - }, - { - "id": "minecraft:skull", - "damage": 3 - }, - { - "id": "minecraft:skull", - "damage": 2 - }, - { - "id": "minecraft:skull", - "damage": 4 - }, - { - "id": "minecraft:skull", - "damage": 5 - }, - { - "id": "minecraft:skull" - }, - { - "id": "minecraft:skull", - "damage": 1 - }, - { - "id": "minecraft:skull", - "damage": 6 - }, - { - "id": "minecraft:beacon", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmJlYWNvbgQJAG5hbWVfaGFzaACwhhfSkdkHAwoAbmV0d29ya19pZCcCAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:bell", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OmJlbGwECQBuYW1lX2hhc2iPqsgDXRcsxAMKAG5ldHdvcmtfaWQgLAAACgYAc3RhdGVzCAoAYXR0YWNobWVudAgAc3RhbmRpbmcDCQBkaXJlY3Rpb24AAAAAAQoAdG9nZ2xlX2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:conduit", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmNvbmR1aXQECQBuYW1lX2hhc2jqxKAxq2EaWQMKAG5ldHdvcmtfaWRVGQAACgYAc3RhdGVzAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stonecutter_block", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lY3V0dGVyX2Jsb2NrBAkAbmFtZV9oYXNoQAXTbAM3MeYDCgBuZXR3b3JrX2lkaDAAAAoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:end_portal_frame", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmVuZF9wb3J0YWxfZnJhbWUECQBuYW1lX2hhc2gqofyUIjGOpQMKAG5ldHdvcmtfaWS7KAAACgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAESAGVuZF9wb3J0YWxfZXllX2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:coal" - }, - { - "id": "minecraft:charcoal" - }, - { - "id": "minecraft:diamond" - }, - { - "id": "minecraft:iron_nugget" - }, - { - "id": "minecraft:raw_iron" - }, - { - "id": "minecraft:raw_gold" - }, - { - "id": "minecraft:raw_copper" - }, - { - "id": "minecraft:copper_ingot" - }, - { - "id": "minecraft:iron_ingot" - }, - { - "id": "minecraft:netherite_scrap" - }, - { - "id": "minecraft:netherite_ingot" - }, - { - "id": "minecraft:gold_nugget" - }, - { - "id": "minecraft:gold_ingot" - }, - { - "id": "minecraft:emerald" - }, - { - "id": "minecraft:quartz" - }, - { - "id": "minecraft:clay_ball" - }, - { - "id": "minecraft:brick" - }, - { - "id": "minecraft:netherbrick" - }, - { - "id": "minecraft:prismarine_shard" - }, - { - "id": "minecraft:amethyst_shard" - }, - { - "id": "minecraft:prismarine_crystals" - }, - { - "id": "minecraft:nautilus_shell" - }, - { - "id": "minecraft:heart_of_the_sea" - }, - { - "id": "minecraft:scute" - }, - { - "id": "minecraft:phantom_membrane" - }, - { - "id": "minecraft:string" - }, - { - "id": "minecraft:feather" - }, - { - "id": "minecraft:flint" - }, - { - "id": "minecraft:gunpowder" - }, - { - "id": "minecraft:leather" - }, - { - "id": "minecraft:rabbit_hide" - }, - { - "id": "minecraft:rabbit_foot" - }, - { - "id": "minecraft:fire_charge" - }, - { - "id": "minecraft:blaze_rod" - }, - { - "id": "minecraft:blaze_powder" - }, - { - "id": "minecraft:magma_cream" - }, - { - "id": "minecraft:fermented_spider_eye" - }, - { - "id": "minecraft:echo_shard" - }, - { - "id": "minecraft:dragon_breath" - }, - { - "id": "minecraft:shulker_shell" - }, - { - "id": "minecraft:ghast_tear" - }, - { - "id": "minecraft:slime_ball" - }, - { - "id": "minecraft:ender_pearl" - }, - { - "id": "minecraft:ender_eye" - }, - { - "id": "minecraft:nether_star" - }, - { - "id": "minecraft:end_rod", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmVuZF9yb2QECQBuYW1lX2hhc2jx/q5cEA0hmQMKAG5ldHdvcmtfaWRvJgAACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:lightning_rod", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmxpZ2h0bmluZ19yb2QECQBuYW1lX2hhc2ioXQF1xvfHNQMKAG5ldHdvcmtfaWTnCAAACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:end_crystal" - }, - { - "id": "minecraft:paper" - }, - { - "id": "minecraft:book" - }, - { - "id": "minecraft:writable_book" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQFAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQFAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQFAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQGAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQGAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQGAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQHAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQHAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQHAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQIAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAUAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAUAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAUAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQMAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQMAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQNAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQNAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQOAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQOAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQOAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAUAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQQAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQRAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQRAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQRAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQSAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQSAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQSAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAUAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQUAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQUAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQVAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQWAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQXAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQXAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQXAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQYAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQYAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQYAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQZAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQZAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQaAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQbAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQcAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAUAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQeAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQeAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQeAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQfAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQfAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQfAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQgAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQhAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQjAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQjAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQjAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQkAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQkAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQkAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQlAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQlAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQlAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:oak_boat" - }, - { - "id": "minecraft:spruce_boat" - }, - { - "id": "minecraft:birch_boat" - }, - { - "id": "minecraft:jungle_boat" - }, - { - "id": "minecraft:acacia_boat" - }, - { - "id": "minecraft:dark_oak_boat" - }, - { - "id": "minecraft:mangrove_boat" - }, - { - "id": "minecraft:cherry_boat" - }, - { - "id": "minecraft:bamboo_raft" - }, - { - "id": "minecraft:oak_chest_boat" - }, - { - "id": "minecraft:spruce_chest_boat" - }, - { - "id": "minecraft:birch_chest_boat" - }, - { - "id": "minecraft:jungle_chest_boat" - }, - { - "id": "minecraft:acacia_chest_boat" - }, - { - "id": "minecraft:dark_oak_chest_boat" - }, - { - "id": "minecraft:mangrove_chest_boat" - }, - { - "id": "minecraft:cherry_chest_boat" - }, - { - "id": "minecraft:bamboo_chest_raft" - }, - { - "id": "minecraft:rail", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OnJhaWwECQBuYW1lX2hhc2hUzmhUXYJDUQMKAG5ldHdvcmtfaWQaGAAACgYAc3RhdGVzAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:golden_rail", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmdvbGRlbl9yYWlsBAkAbmFtZV9oYXNoOoV5MaKipoUDCgBuZXR3b3JrX2lkGiEAAAoGAHN0YXRlcwENAHJhaWxfZGF0YV9iaXQAAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:detector_rail", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmRldGVjdG9yX3JhaWwECQBuYW1lX2hhc2gVUk31qOysUQMKAG5ldHdvcmtfaWTuGAAACgYAc3RhdGVzAQ0AcmFpbF9kYXRhX2JpdAADDgByYWlsX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:activator_rail", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmFjdGl2YXRvcl9yYWlsBAkAbmFtZV9oYXNosIL91qriCRkDCgBuZXR3b3JrX2lkCAQAAAoGAHN0YXRlcwENAHJhaWxfZGF0YV9iaXQAAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:minecart" - }, - { - "id": "minecraft:chest_minecart" - }, - { - "id": "minecraft:hopper_minecart" - }, - { - "id": "minecraft:tnt_minecart" - }, - { - "id": "minecraft:redstone" - }, - { - "id": "minecraft:redstone_block", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZHN0b25lX2Jsb2NrBAkAbmFtZV9oYXNoRhULL0r8o0sDCgBuZXR3b3JrX2lkEBYAAAoGAHN0YXRlcwADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:redstone_torch", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZHN0b25lX3RvcmNoBAkAbmFtZV9oYXNoizFRjpYMIDgDCgBuZXR3b3JrX2lkiRMAAAoGAHN0YXRlcwgWAHRvcmNoX2ZhY2luZ19kaXJlY3Rpb24HAHVua25vd24AAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:lever", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmxldmVyBAkAbmFtZV9oYXNoGMJeLJsUMLYDCgBuZXR3b3JrX2lkkioAAAoGAHN0YXRlcwgPAGxldmVyX2RpcmVjdGlvbg4AZG93bl9lYXN0X3dlc3QBCABvcGVuX2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:wooden_button", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Ondvb2Rlbl9idXR0b24ECQBuYW1lX2hhc2hR7PgSTQt0sQMKAG5ldHdvcmtfaWQUKgAACgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:spruce_button", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9idXR0b24ECQBuYW1lX2hhc2jBW9Z8aYE7YQMKAG5ldHdvcmtfaWTUGQAACgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:birch_button", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX2J1dHRvbgQJAG5hbWVfaGFzaJXYgGuSHbTwAwoAbmV0d29ya19pZDMxAAAKBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:jungle_button", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9idXR0b24ECQBuYW1lX2hhc2iCgNANcJs+BQMKAG5ldHdvcmtfaWR5AAAACgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:acacia_button", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9idXR0b24ECQBuYW1lX2hhc2gVvmcT7LTO0wMKAG5ldHdvcmtfaWQKLwAACgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:dark_oak_button", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX2J1dHRvbgQJAG5hbWVfaGFzaIV10ZGGrCIEAwoAbmV0d29ya19pZGAAAAAKBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:mangrove_button", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX2J1dHRvbgQJAG5hbWVfaGFzaNzeYYKLgOzJAwoAbmV0d29ya19pZL8sAAAKBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:cherry_button", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9idXR0b24ECQBuYW1lX2hhc2j2/IHjeAbUcwMKAG5ldHdvcmtfaWQNGwAACgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:bamboo_button", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19idXR0b24ECQBuYW1lX2hhc2j7AddMi+6nsgMKAG5ldHdvcmtfaWRtKgAACgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stone_button", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnN0b25lX2J1dHRvbgQJAG5hbWVfaGFzaM4ejMctmvohAwoAbmV0d29ya19pZC0FAAAKBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:crimson_button", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fYnV0dG9uBAkAbmFtZV9oYXNofnjYHaYIeWgDCgBuZXR3b3JrX2lkTRoAAAoGAHN0YXRlcwESAGJ1dHRvbl9wcmVzc2VkX2JpdAADEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:warped_button", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9idXR0b24ECQBuYW1lX2hhc2jwkV2EU6Cn1QMKAG5ldHdvcmtfaWQdLwAACgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:polished_blackstone_button", - "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnV0dG9uBAkAbmFtZV9oYXNojmxzQKS0S/EDCgBuZXR3b3JrX2lkSzEAAAoGAHN0YXRlcwESAGJ1dHRvbl9wcmVzc2VkX2JpdAADEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:tripwire_hook", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnRyaXB3aXJlX2hvb2sECQBuYW1lX2hhc2gQdp+oGZLNnAMKAG5ldHdvcmtfaWSKJgAACgYAc3RhdGVzAQwAYXR0YWNoZWRfYml0AAMJAGRpcmVjdGlvbgAAAAABCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:wooden_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0Ondvb2Rlbl9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaGkGs5kCuA74AwoAbmV0d29ya19pZF0yAAAKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:spruce_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnNwcnVjZV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaNmwuq549fJKAwoAbmV0d29ya19pZP4VAAAKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:birch_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmJpcmNoX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNorQkT9kDdlTwDCgBuZXR3b3JrX2lkKBUAAAoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:jungle_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0Omp1bmdsZV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaJ7DcteCkb8/AwoAbmV0d29ya19pZH4VAAAKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:acacia_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmFjYWNpYV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaC2frZtfoYqCAwoAbmV0d29ya19pZMUgAAAKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:dark_oak_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmRhcmtfb2FrX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoHUCJsTy52pwDCgBuZXR3b3JrX2lktCYAAAoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:mangrove_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0Om1hbmdyb3ZlX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoiDsTfJaX100DCgBuZXR3b3JrX2lk5xcAAAoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:cherry_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmNoZXJyeV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaALMqYEZDUQHAwoAbmV0d29ya19pZI8AAAAKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:bamboo_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmJhbWJvb19wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaNvxJ7NIAaqlAwoAbmV0d29ya19pZMMoAAAKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:crimson_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmNyaW1zb25fcHJlc3N1cmVfcGxhdGUECQBuYW1lX2hhc2hqBDVDAd31/gMKAG5ldHdvcmtfaWRAMwAACgYAc3RhdGVzAw8AcmVkc3RvbmVfc2lnbmFsAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:warped_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OndhcnBlZF9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaBxFoQksWtYUAwoAbmV0d29ya19pZK4CAAAKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:stone_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnN0b25lX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNounJuTBUTrU8DCgBuZXR3b3JrX2lk+BcAAAoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:light_weighted_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X3dlaWdodGVkX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoOyOJkNxLtkEDCgBuZXR3b3JrX2lknBUAAAoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:heavy_weighted_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZScAbWluZWNyYWZ0OmhlYXZ5X3dlaWdodGVkX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoltgDmDvTajUDCgBuZXR3b3JrX2lk1wgAAAoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:polished_blackstone_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZSwAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfcHJlc3N1cmVfcGxhdGUECQBuYW1lX2hhc2h65Ci6/CeGqwMKAG5ldHdvcmtfaWRzKQAACgYAc3RhdGVzAw8AcmVkc3RvbmVfc2lnbmFsAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:observer", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0Om9ic2VydmVyBAkAbmFtZV9oYXNoYhlh1lpmHTgDCgBuZXR3b3JrX2lkfRMAAAoGAHN0YXRlcwgaAG1pbmVjcmFmdDpmYWNpbmdfZGlyZWN0aW9uBABkb3duAQsAcG93ZXJlZF9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:daylight_detector", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmRheWxpZ2h0X2RldGVjdG9yBAkAbmFtZV9oYXNoV0F0s7B7PVgDCgBuZXR3b3JrX2lkMhkAAAoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:repeater" - }, - { - "id": "minecraft:comparator" - }, - { - "id": "minecraft:hopper" - }, - { - "id": "minecraft:dropper", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmRyb3BwZXIECQBuYW1lX2hhc2joXP7XqU0l3QMKAG5ldHdvcmtfaWSpLwAACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgMAAAABDQB0cmlnZ2VyZWRfYml0AAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:dispenser", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmRpc3BlbnNlcgQJAG5hbWVfaGFzaP1RR+zAbYP2AwoAbmV0d29ya19pZCoyAAAKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAwAAAAENAHRyaWdnZXJlZF9iaXQAAAMHAHZlcnNpb24gChQBAA==" - }, - { - "id": "minecraft:piston", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBpc3RvbgQJAG5hbWVfaGFzaDs3AFh1fL0uAwoAbmV0d29ya19pZO4HAAAKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAQAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:sticky_piston", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnN0aWNreV9waXN0b24ECQBuYW1lX2hhc2hPFJFJSiJ0ZQMKAG5ldHdvcmtfaWQDGgAACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgEAAAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:tnt", - "block_state_b64": "CgAACAQAbmFtZQ0AbWluZWNyYWZ0OnRudAQJAG5hbWVfaGFzaEYOHwCvJH29AwoAbmV0d29ya19pZEorAAAKBgBzdGF0ZXMBFABhbGxvd191bmRlcndhdGVyX2JpdAABCwBleHBsb2RlX2JpdAAAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:name_tag" - }, - { - "id": "minecraft:loom", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Omxvb20ECQBuYW1lX2hhc2i7DKjAXNq8TAMKAG5ldHdvcmtfaWTCFwAACgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:banner" - }, - { - "id": "minecraft:banner", - "damage": 8 - }, - { - "id": "minecraft:banner", - "damage": 7 - }, - { - "id": "minecraft:banner", - "damage": 15 - }, - { - "id": "minecraft:banner", - "damage": 12 - }, - { - "id": "minecraft:banner", - "damage": 14 - }, - { - "id": "minecraft:banner", - "damage": 1 - }, - { - "id": "minecraft:banner", - "damage": 4 - }, - { - "id": "minecraft:banner", - "damage": 5 - }, - { - "id": "minecraft:banner", - "damage": 13 - }, - { - "id": "minecraft:banner", - "damage": 9 - }, - { - "id": "minecraft:banner", - "damage": 3 - }, - { - "id": "minecraft:banner", - "damage": 11 - }, - { - "id": "minecraft:banner", - "damage": 10 - }, - { - "id": "minecraft:banner", - "damage": 2 - }, - { - "id": "minecraft:banner", - "damage": 6 - }, - { - "id": "minecraft:banner", - "damage": 15, - "nbt_b64": "CgAAAwQAVHlwZQEAAAAA" - }, - { - "id": "minecraft:creeper_banner_pattern" - }, - { - "id": "minecraft:skull_banner_pattern" - }, - { - "id": "minecraft:flower_banner_pattern" - }, - { - "id": "minecraft:mojang_banner_pattern" - }, - { - "id": "minecraft:field_masoned_banner_pattern" - }, - { - "id": "minecraft:bordure_indented_banner_pattern" - }, - { - "id": "minecraft:piglin_banner_pattern" - }, - { - "id": "minecraft:globe_banner_pattern" - }, - { - "id": "minecraft:angler_pottery_sherd" - }, - { - "id": "minecraft:archer_pottery_sherd" - }, - { - "id": "minecraft:arms_up_pottery_sherd" - }, - { - "id": "minecraft:blade_pottery_sherd" - }, - { - "id": "minecraft:brewer_pottery_sherd" - }, - { - "id": "minecraft:burn_pottery_sherd" - }, - { - "id": "minecraft:danger_pottery_sherd" - }, - { - "id": "minecraft:explorer_pottery_sherd" - }, - { - "id": "minecraft:friend_pottery_sherd" - }, - { - "id": "minecraft:heart_pottery_sherd" - }, - { - "id": "minecraft:heartbreak_pottery_sherd" - }, - { - "id": "minecraft:howl_pottery_sherd" - }, - { - "id": "minecraft:miner_pottery_sherd" - }, - { - "id": "minecraft:mourner_pottery_sherd" - }, - { - "id": "minecraft:plenty_pottery_sherd" - }, - { - "id": "minecraft:prize_pottery_sherd" - }, - { - "id": "minecraft:sheaf_pottery_sherd" - }, - { - "id": "minecraft:shelter_pottery_sherd" - }, - { - "id": "minecraft:skull_pottery_sherd" - }, - { - "id": "minecraft:snort_pottery_sherd" - }, - { - "id": "minecraft:netherite_upgrade_smithing_template" - }, - { - "id": "minecraft:sentry_armor_trim_smithing_template" - }, - { - "id": "minecraft:vex_armor_trim_smithing_template" - }, - { - "id": "minecraft:wild_armor_trim_smithing_template" - }, - { - "id": "minecraft:coast_armor_trim_smithing_template" - }, - { - "id": "minecraft:dune_armor_trim_smithing_template" - }, - { - "id": "minecraft:wayfinder_armor_trim_smithing_template" - }, - { - "id": "minecraft:shaper_armor_trim_smithing_template" - }, - { - "id": "minecraft:raiser_armor_trim_smithing_template" - }, - { - "id": "minecraft:host_armor_trim_smithing_template" - }, - { - "id": "minecraft:ward_armor_trim_smithing_template" - }, - { - "id": "minecraft:silence_armor_trim_smithing_template" - }, - { - "id": "minecraft:tide_armor_trim_smithing_template" - }, - { - "id": "minecraft:snout_armor_trim_smithing_template" - }, - { - "id": "minecraft:rib_armor_trim_smithing_template" - }, - { - "id": "minecraft:eye_armor_trim_smithing_template" - }, - { - "id": "minecraft:spire_armor_trim_smithing_template" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwAAAAAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAABwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAIBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAHBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAPBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAMBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAOBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAABBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAEBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAFBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAANBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAJBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAADBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAALBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAKBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAACBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAGBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_star", - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yIR0d/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 8, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yUk9H/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 7, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yl52d/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 15, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9y8PDw/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 12, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9y2rM6/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 14, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yHYD5/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 1, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yJi6w/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 4, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yqkQ8/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 5, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yuDKJ/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 13, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yvU7H/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 9, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yqovz/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 3, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yMlSD/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 11, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yPdj+/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 10, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yH8eA/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 2, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yFnxe/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 6, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9ynJwW/wA=" - }, - { - "id": "minecraft:chain" - }, - { - "id": "minecraft:target", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnRhcmdldAQJAG5hbWVfaGFzaJc66SVbYlaxAwoAbmV0d29ya19pZBMqAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbiAKFAEA" - }, - { - "id": "minecraft:decorated_pot", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmRlY29yYXRlZF9wb3QECQBuYW1lX2hhc2jjQgckn8VTvwMKAG5ldHdvcmtfaWRcKwAACgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uIAoUAQA=" - }, - { - "id": "minecraft:lodestone_compass" - }, - { - "id": "minecraft:wither_spawn_egg" - }, - { - "id": "minecraft:ender_dragon_spawn_egg" - }, - { - "id": "minecraft:debug_stick" - }, - { - "id": "minecraft:suspicious_stew" - } - ] -} \ No newline at end of file diff --git a/core/src/main/resources/bedrock/creative_items.1_20_30.json b/core/src/main/resources/bedrock/creative_items.1_20_30.json deleted file mode 100644 index cce3f8a50..000000000 --- a/core/src/main/resources/bedrock/creative_items.1_20_30.json +++ /dev/null @@ -1,5787 +0,0 @@ -{ - "items": [ - { - "id": "minecraft:planks", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBsYW5rcwQJAG5hbWVfaGFzaA+7EGxL5oikAwoAbmV0d29ya19pZE/NqzcKBgBzdGF0ZXMICQB3b29kX3R5cGUDAG9hawADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:planks", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBsYW5rcwQJAG5hbWVfaGFzaA+7EGxL5oikAwoAbmV0d29ya19pZHl/r2YKBgBzdGF0ZXMICQB3b29kX3R5cGUGAHNwcnVjZQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:planks", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBsYW5rcwQJAG5hbWVfaGFzaA+7EGxL5oikAwoAbmV0d29ya19pZL6SoXYKBgBzdGF0ZXMICQB3b29kX3R5cGUFAGJpcmNoAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:planks", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBsYW5rcwQJAG5hbWVfaGFzaA+7EGxL5oikAwoAbmV0d29ya19pZKYD6L0KBgBzdGF0ZXMICQB3b29kX3R5cGUGAGp1bmdsZQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:planks", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBsYW5rcwQJAG5hbWVfaGFzaA+7EGxL5oikAwoAbmV0d29ya19pZJ0zTHYKBgBzdGF0ZXMICQB3b29kX3R5cGUGAGFjYWNpYQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:planks", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBsYW5rcwQJAG5hbWVfaGFzaA+7EGxL5oikAwoAbmV0d29ya19pZOf6hVkKBgBzdGF0ZXMICQB3b29kX3R5cGUIAGRhcmtfb2FrAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:mangrove_planks", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX3BsYW5rcwQJAG5hbWVfaGFzaPvLtcEA0F8xAwoAbmV0d29ya19pZEvnlCYKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:cherry_planks", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9wbGFua3MECQBuYW1lX2hhc2hNIvVh/lVW7gMKAG5ldHdvcmtfaWQTXpRoCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:bamboo_planks", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19wbGFua3MECQBuYW1lX2hhc2gYnjNz7SCCjgMKAG5ldHdvcmtfaWTi8ySSCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:bamboo_mosaic", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19tb3NhaWMECQBuYW1lX2hhc2izSEgiMKOp/AMKAG5ldHdvcmtfaWQZ/p8xCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:crimson_planks", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fcGxhbmtzBAkAbmFtZV9oYXNoJc5IKqNXJnwDCgBuZXR3b3JrX2lkwtJDdQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:warped_planks", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9wbGFua3MECQBuYW1lX2hhc2g3yGXEWhe6LgMKAG5ldHdvcmtfaWStTABvCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWSE4JosCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCwBjb2JibGVzdG9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWTUvV6XCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEQBtb3NzeV9jb2JibGVzdG9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWT4opb2CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBwBncmFuaXRlCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQAMQTVCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBwBkaW9yaXRlCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQIbDOcCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCABhbmRlc2l0ZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWSZKhusCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCQBzYW5kc3RvbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWSp4zgCCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlDQByZWRfc2FuZHN0b25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRbqVHTCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCwBzdG9uZV9icmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRr0ZT/CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEQBtb3NzeV9zdG9uZV9icmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRnLis3CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBQBicmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQNLzfSCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlDABuZXRoZXJfYnJpY2sIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQ5h0xwCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEAByZWRfbmV0aGVyX2JyaWNrCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWS9J0B2CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCQBlbmRfYnJpY2sIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRPbkJeCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCgBwcmlzbWFyaW5lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:blackstone_wall", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmJsYWNrc3RvbmVfd2FsbAQJAG5hbWVfaGFzaMP8XppUSU1RAwoAbmV0d29ya19pZMbeBBsKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:polished_blackstone_wall", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfd2FsbAQJAG5hbWVfaGFzaP6SwV08YwzAAwoAbmV0d29ya19pZAJLsz8KBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:polished_blackstone_brick_wall", - "block_state_b64": "CgAACAQAbmFtZSgAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfd2FsbAQJAG5hbWVfaGFzaBBIDZbHxiEzAwoAbmV0d29ya19pZEbLV8cKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:cobbled_deepslate_wall", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3dhbGwECQBuYW1lX2hhc2iECY5oKxeT+gMKAG5ldHdvcmtfaWRCnPrFCgYAc3RhdGVzCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:deepslate_tile_wall", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3dhbGwECQBuYW1lX2hhc2jz7N+PeuEXgQMKAG5ldHdvcmtfaWTqw4s4CgYAc3RhdGVzCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:polished_deepslate_wall", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV93YWxsBAkAbmFtZV9oYXNoHxjTdj9pevMDCgBuZXR3b3JrX2lkIvBYYwoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:deepslate_brick_wall", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja193YWxsBAkAbmFtZV9oYXNoEs3EQrjroyEDCgBuZXR3b3JrX2lkwlrCGwoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:mud_brick_wall", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0Om11ZF9icmlja193YWxsBAkAbmFtZV9oYXNov9b98ATpUSwDCgBuZXR3b3JrX2lkH/1WZQoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:oak_fence", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0Om9ha19mZW5jZQQJAG5hbWVfaGFzaGEmid7AaCWRAwoAbmV0d29ya19pZDvPEXcKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:spruce_fence", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnNwcnVjZV9mZW5jZQQJAG5hbWVfaGFzaPQCm+aX1ZQeAwoAbmV0d29ya19pZD1QUEoKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:birch_fence", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmJpcmNoX2ZlbmNlBAkAbmFtZV9oYXNo6CJ2ATpANfgDCgBuZXR3b3JrX2lkmCUV2QoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:jungle_fence", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0Omp1bmdsZV9mZW5jZQQJAG5hbWVfaGFzaOX4cD9uAmsdAwoAbmV0d29ya19pZHz1VxkKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:acacia_fence", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmFjYWNpYV9mZW5jZQQJAG5hbWVfaGFzaGjn+RlKVDH6AwoAbmV0d29ya19pZNVGubwKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:dark_oak_fence", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmRhcmtfb2FrX2ZlbmNlBAkAbmFtZV9oYXNoGPj0gCgM0c0DCgBuZXR3b3JrX2lk2w+gEwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:mangrove_fence", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hbmdyb3ZlX2ZlbmNlBAkAbmFtZV9oYXNowwAd7tPu9bsDCgBuZXR3b3JrX2lkKEcd0goGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:cherry_fence", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmNoZXJyeV9mZW5jZQQJAG5hbWVfaGFzaFmtUfHfTxcxAwoAbmV0d29ya19pZPCBxAIKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:bamboo_fence", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJhbWJvb19mZW5jZQQJAG5hbWVfaGFzaCKRbxfXsfkiAwoAbmV0d29ya19pZJNXKFcKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:nether_brick_fence", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0Om5ldGhlcl9icmlja19mZW5jZQQJAG5hbWVfaGFzaA6030ngawxcAwoAbmV0d29ya19pZLnjLF4KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:crimson_fence", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNyaW1zb25fZmVuY2UECQBuYW1lX2hhc2jhUhKv1HGj9AMKAG5ldHdvcmtfaWR3OH3OCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:warped_fence", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OndhcnBlZF9mZW5jZQQJAG5hbWVfaGFzaJfb3/YuKmOWAwoAbmV0d29ya19pZCpaGC8KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:fence_gate", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmZlbmNlX2dhdGUECQBuYW1lX2hhc2hTxpjEDmRzAwMKAG5ldHdvcmtfaWR+T9kTCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:spruce_fence_gate", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnNwcnVjZV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoanTVB84HRbkDCgBuZXR3b3JrX2lkEnw5egoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:birch_fence_gate", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmJpcmNoX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2jmfPklI8azSwMKAG5ldHdvcmtfaWQL77/BCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:jungle_fence_gate", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0Omp1bmdsZV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNobYVQkfBomIcDCgBuZXR3b3JrX2lkA1zgtgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:acacia_fence_gate", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmFjYWNpYV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoZnrLUx/XSekDCgBuZXR3b3JrX2lkHg/kTgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:dark_oak_fence_gate", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmRhcmtfb2FrX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2j2PTvdJJHcVQMKAG5ldHdvcmtfaWTwjOCeCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:mangrove_fence_gate", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0Om1hbmdyb3ZlX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2i/kOhBKiI/dAMKAG5ldHdvcmtfaWSfweCSCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:cherry_fence_gate", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmNoZXJyeV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoKWLgCk0z+PsDCgBuZXR3b3JrX2lk/9bTZQoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:bamboo_fence_gate", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmJhbWJvb19mZW5jZV9nYXRlBAkAbmFtZV9oYXNopH1JrUgwdIADCgBuZXR3b3JrX2lkzIpPywoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:crimson_fence_gate", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmNyaW1zb25fZmVuY2VfZ2F0ZQQJAG5hbWVfaGFzaHE3Gfd0Z2d2AwoAbmV0d29ya19pZDQzVbEKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQsAaW5fd2FsbF9iaXQAAQgAb3Blbl9iaXQAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:warped_fence_gate", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OndhcnBlZF9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoy0oIBjDIG4kDCgBuZXR3b3JrX2lkkf+/3QoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:normal_stone_stairs", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0Om5vcm1hbF9zdG9uZV9zdGFpcnMECQBuYW1lX2hhc2hAEktZZOkGIwMKAG5ldHdvcmtfaWQeH1ALCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:stone_stairs", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnN0b25lX3N0YWlycwQJAG5hbWVfaGFzaNRjqVC5GRVDAwoAbmV0d29ya19pZDcCv+MKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:mossy_cobblestone_stairs", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0Om1vc3N5X2NvYmJsZXN0b25lX3N0YWlycwQJAG5hbWVfaGFzaMVSTq5z9n1RAwoAbmV0d29ya19pZFIfrhkKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:oak_stairs", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Om9ha19zdGFpcnMECQBuYW1lX2hhc2jk/HFzdXy0FQMKAG5ldHdvcmtfaWQJjyzBCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:spruce_stairs", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9zdGFpcnMECQBuYW1lX2hhc2iznygw7uBPBQMKAG5ldHdvcmtfaWTv+is3CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:birch_stairs", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX3N0YWlycwQJAG5hbWVfaGFzaPfhbL619a3GAwoAbmV0d29ya19pZFyPlHAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:jungle_stairs", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9zdGFpcnMECQBuYW1lX2hhc2jodJsHUbOVxQMKAG5ldHdvcmtfaWR0z5d4CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:acacia_stairs", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9zdGFpcnMECQBuYW1lX2hhc2h3x1NmD43IqQMKAG5ldHdvcmtfaWS7Jwz6CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:dark_oak_stairs", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX3N0YWlycwQJAG5hbWVfaGFzaMfwkbYPbNmAAwoAbmV0d29ya19pZCmBYKAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:mangrove_stairs", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX3N0YWlycwQJAG5hbWVfaGFzaNpUDY+uGMpyAwoAbmV0d29ya19pZChzUAsKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:cherry_stairs", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9zdGFpcnMECQBuYW1lX2hhc2jMtr0v9JY4zwMKAG5ldHdvcmtfaWRQwq31CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:bamboo_stairs", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19zdGFpcnMECQBuYW1lX2hhc2jFOzWL8PalKwMKAG5ldHdvcmtfaWTVPh42CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:bamboo_mosaic_stairs", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmJhbWJvb19tb3NhaWNfc3RhaXJzBAkAbmFtZV9oYXNoNLPiveSHPaoDCgBuZXR3b3JrX2lk44PHjgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:stone_brick_stairs", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnN0b25lX2JyaWNrX3N0YWlycwQJAG5hbWVfaGFzaN6tQViRo5cwAwoAbmV0d29ya19pZDMyMgIKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:mossy_stone_brick_stairs", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0Om1vc3N5X3N0b25lX2JyaWNrX3N0YWlycwQJAG5hbWVfaGFzaIB/Zv5YBPuYAwoAbmV0d29ya19pZANTOsMKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:sandstone_stairs", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnNhbmRzdG9uZV9zdGFpcnMECQBuYW1lX2hhc2hOyA0BoYUOPQMKAG5ldHdvcmtfaWSV/834CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:smooth_sandstone_stairs", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnNtb290aF9zYW5kc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNoB+CuCd8Ruz8DCgBuZXR3b3JrX2lksR+m8QoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:red_sandstone_stairs", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNoPs0LpHPL24YDCgBuZXR3b3JrX2lkLYVt3woGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:smooth_red_sandstone_stairs", - "block_state_b64": "CgAACAQAbmFtZSUAbWluZWNyYWZ0OnNtb290aF9yZWRfc2FuZHN0b25lX3N0YWlycwQJAG5hbWVfaGFzaBvjtQv5pf+MAwoAbmV0d29ya19pZMHNND8KBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:granite_stairs", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmdyYW5pdGVfc3RhaXJzBAkAbmFtZV9oYXNoGzpvtoqKQjgDCgBuZXR3b3JrX2lkPkcB1goGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:polished_granite_stairs", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2dyYW5pdGVfc3RhaXJzBAkAbmFtZV9oYXNo3PvbSfEQklIDCgBuZXR3b3JrX2lkMmEm3AoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:diorite_stairs", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmRpb3JpdGVfc3RhaXJzBAkAbmFtZV9oYXNoi73T8VQuZmcDCgBuZXR3b3JrX2lk6i6nBQoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:polished_diorite_stairs", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2Rpb3JpdGVfc3RhaXJzBAkAbmFtZV9oYXNoFKRJd5Wk5L0DCgBuZXR3b3JrX2lkbt2ioAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:andesite_stairs", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmFuZGVzaXRlX3N0YWlycwQJAG5hbWVfaGFzaO5w2FKBw76EAwoAbmV0d29ya19pZKhXEgUKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:polished_andesite_stairs", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2FuZGVzaXRlX3N0YWlycwQJAG5hbWVfaGFzaNcZZ/zmLInIAwoAbmV0d29ya19pZJTHrlEKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:brick_stairs", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJyaWNrX3N0YWlycwQJAG5hbWVfaGFzaMyt+cRDk5O2AwoAbmV0d29ya19pZNeMh58KBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:nether_brick_stairs", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0Om5ldGhlcl9icmlja19zdGFpcnMECQBuYW1lX2hhc2jRqIoOXgifBAMKAG5ldHdvcmtfaWQDiw5yCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:red_nether_brick_stairs", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnJlZF9uZXRoZXJfYnJpY2tfc3RhaXJzBAkAbmFtZV9oYXNogQvosSbcj7kDCgBuZXR3b3JrX2lkx2IMtAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:end_brick_stairs", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmVuZF9icmlja19zdGFpcnMECQBuYW1lX2hhc2hmlAk+QhsUsQMKAG5ldHdvcmtfaWTN7KFaCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:quartz_stairs", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnF1YXJ0el9zdGFpcnMECQBuYW1lX2hhc2hmvpvOqGi6egMKAG5ldHdvcmtfaWRmUTh7CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:smooth_quartz_stairs", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnNtb290aF9xdWFydHpfc3RhaXJzBAkAbmFtZV9oYXNoNZZ9rX0qZOsDCgBuZXR3b3JrX2lkzsgQyQoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:purpur_stairs", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnB1cl9zdGFpcnMECQBuYW1lX2hhc2ifwDxeezXD7gMKAG5ldHdvcmtfaWTT+rxiCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:prismarine_stairs", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnByaXNtYXJpbmVfc3RhaXJzBAkAbmFtZV9oYXNooTHSZ+IrYtcDCgBuZXR3b3JrX2lkxTJfeAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:dark_prismarine_stairs", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmRhcmtfcHJpc21hcmluZV9zdGFpcnMECQBuYW1lX2hhc2hIciLmam4o4AMKAG5ldHdvcmtfaWTVu7TCCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:prismarine_bricks_stairs", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnByaXNtYXJpbmVfYnJpY2tzX3N0YWlycwQJAG5hbWVfaGFzaNIjq1oBlZMMAwoAbmV0d29ya19pZGEFwLYKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:crimson_stairs", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fc3RhaXJzBAkAbmFtZV9oYXNoZJqIzCBpCq4DCgBuZXR3b3JrX2lktXE00AoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:warped_stairs", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9zdGFpcnMECQBuYW1lX2hhc2hOkY27jLD4RQMKAG5ldHdvcmtfaWQ+E5VrCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:blackstone_stairs", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmJsYWNrc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNokdoUb76p9McDCgBuZXR3b3JrX2lk5fWI5goGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:polished_blackstone_stairs", - "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNolCFtFIE8MmADCgBuZXR3b3JrX2lkGTf7sgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:polished_blackstone_brick_stairs", - "block_state_b64": "CgAACAQAbmFtZSoAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfc3RhaXJzBAkAbmFtZV9oYXNonks6UlfpOmkDCgBuZXR3b3JrX2lkgYeOdAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:cut_copper_stairs", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmN1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoHfoAXYq5G3MDCgBuZXR3b3JrX2lkeetf7woGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:exposed_cut_copper_stairs", - "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcl9zdGFpcnMECQBuYW1lX2hhc2howneQGtZ9cgMKAG5ldHdvcmtfaWSg73zdCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:weathered_cut_copper_stairs", - "block_state_b64": "CgAACAQAbmFtZSUAbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyX3N0YWlycwQJAG5hbWVfaGFzaP+R5loXxrVgAwoAbmV0d29ya19pZOnbRf4KBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:oxidized_cut_copper_stairs", - "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNo6Jeoq5rsPxsDCgBuZXR3b3JrX2lkmRjDnQoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:waxed_cut_copper_stairs", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoh07CQj0/SR8DCgBuZXR3b3JrX2lkmYqoqAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:waxed_exposed_cut_copper_stairs", - "block_state_b64": "CgAACAQAbmFtZSkAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcl9zdGFpcnMECQBuYW1lX2hhc2guVct1ilmxTwMKAG5ldHdvcmtfaWQgCPROCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:waxed_weathered_cut_copper_stairs", - "block_state_b64": "CgAACAQAbmFtZSsAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyX3N0YWlycwQJAG5hbWVfaGFzaPXC8Sz/phCpAwoAbmV0d29ya19pZHlwHVsKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:waxed_oxidized_cut_copper_stairs", - "block_state_b64": "CgAACAQAbmFtZSoAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoaqGdkuhxVZUDCgBuZXR3b3JrX2lkYQXzzgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:cobbled_deepslate_stairs", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3N0YWlycwQJAG5hbWVfaGFzaPIfa+TpyJcIAwoAbmV0d29ya19pZJUvOYIKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:deepslate_tile_stairs", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3N0YWlycwQJAG5hbWVfaGFzaGFRFzB72mN2AwoAbmV0d29ya19pZJEOgIsKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:polished_deepslate_stairs", - "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV9zdGFpcnMECQBuYW1lX2hhc2iNCYxVik9sGAMKAG5ldHdvcmtfaWSRVPnYCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:deepslate_brick_stairs", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja19zdGFpcnMECQBuYW1lX2hhc2hIasOahEf83wMKAG5ldHdvcmtfaWQ1qEDCCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:mud_brick_stairs", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0Om11ZF9icmlja19zdGFpcnMECQBuYW1lX2hhc2gt3qxK1NWajAMKAG5ldHdvcmtfaWSm9N3MCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:wooden_door" - }, - { - "id": "minecraft:spruce_door" - }, - { - "id": "minecraft:birch_door" - }, - { - "id": "minecraft:jungle_door" - }, - { - "id": "minecraft:acacia_door" - }, - { - "id": "minecraft:dark_oak_door" - }, - { - "id": "minecraft:mangrove_door" - }, - { - "id": "minecraft:cherry_door" - }, - { - "id": "minecraft:bamboo_door" - }, - { - "id": "minecraft:iron_door" - }, - { - "id": "minecraft:crimson_door" - }, - { - "id": "minecraft:warped_door" - }, - { - "id": "minecraft:trapdoor", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OnRyYXBkb29yBAkAbmFtZV9oYXNotYiAJGtN0xADCgBuZXR3b3JrX2lkyTAWkAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:spruce_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnNwcnVjZV90cmFwZG9vcgQJAG5hbWVfaGFzaOwlfbgBkUW4AwoAbmV0d29ya19pZPHy1K0KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:birch_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmJpcmNoX3RyYXBkb29yBAkAbmFtZV9oYXNoSLtLweOLJ7wDCgBuZXR3b3JrX2lkeJWDfgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:jungle_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Omp1bmdsZV90cmFwZG9vcgQJAG5hbWVfaGFzaDP/TnM9wyCIAwoAbmV0d29ya19pZEy2fJoKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:acacia_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmFjYWNpYV90cmFwZG9vcgQJAG5hbWVfaGFzaMj8xi3vmEKOAwoAbmV0d29ya19pZOHj8E8KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:dark_oak_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmRhcmtfb2FrX3RyYXBkb29yBAkAbmFtZV9oYXNomB2GGJQ2aOMDCgBuZXR3b3JrX2lko5ZHTwoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:mangrove_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0Om1hbmdyb3ZlX3RyYXBkb29yBAkAbmFtZV9oYXNooV3kQsQUUmkDCgBuZXR3b3JrX2lkkF/mxAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:cherry_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmNoZXJyeV90cmFwZG9vcgQJAG5hbWVfaGFzaH/PefpfdHgtAwoAbmV0d29ya19pZOA7eNgKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:bamboo_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmJhbWJvb190cmFwZG9vcgQJAG5hbWVfaGFzaJrEOpsTwtKCAwoAbmV0d29ya19pZLvbPz8KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:iron_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Omlyb25fdHJhcGRvb3IECQBuYW1lX2hhc2gwA+IumsEiGQMKAG5ldHdvcmtfaWTvSVl/CgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAEPAHVwc2lkZV9kb3duX2JpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:crimson_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNyaW1zb25fdHJhcGRvb3IECQBuYW1lX2hhc2jHXufTnwUkYgMKAG5ldHdvcmtfaWQLjMYVCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAEPAHVwc2lkZV9kb3duX2JpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:warped_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OndhcnBlZF90cmFwZG9vcgQJAG5hbWVfaGFzaA20wG/+vkd6AwoAbmV0d29ya19pZHKR/hYKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:iron_bars", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0Omlyb25fYmFycwQJAG5hbWVfaGFzaPuefWSNAe56AwoAbmV0d29ya19pZN2LB5IKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:glass", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmdsYXNzBAkAbmFtZV9oYXNowGJByfWff6gDCgBuZXR3b3JrX2lk0hdLNwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:white_stained_glass", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OndoaXRlX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2iHubqoMbu9fAMKAG5ldHdvcmtfaWRndBrUCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:light_gray_stained_glass", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaKKa+LrRsHQhAwoAbmV0d29ya19pZEv2giYKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:gray_stained_glass", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmdyYXlfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaIETy7Y/HZREAwoAbmV0d29ya19pZDomVrUKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:black_stained_glass", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmJsYWNrX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2iV6BCwpfDMmwMKAG5ldHdvcmtfaWSV7doJCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:brown_stained_glass", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmJyb3duX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2igsEiq5np8JgMKAG5ldHdvcmtfaWRMzE/lCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:red_stained_glass", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnJlZF9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNoCa2J12/lQoIDCgBuZXR3b3JrX2lk283lWAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:orange_stained_glass", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0Om9yYW5nZV9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNozgjAuvzhxGsDCgBuZXR3b3JrX2lkW5CkhQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:yellow_stained_glass", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnllbGxvd19zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNo7EbHMd5WVugDCgBuZXR3b3JrX2lkkdDyXQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:lime_stained_glass", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmxpbWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaBtZA1nZtwcFAwoAbmV0d29ya19pZDxX85UKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:green_stained_glass", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmdyZWVuX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2h91ptDgbehWwMKAG5ldHdvcmtfaWTlDhnECgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:cyan_stained_glass", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmN5YW5fc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaBkIYQ8nQLqbAwoAbmV0d29ya19pZOL1lHsKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:light_blue_stained_glass", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaLt05n1G0fiSAwoAbmV0d29ya19pZNbwulIKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:blue_stained_glass", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmJsdWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaPhLocSfzduRAwoAbmV0d29ya19pZENsjFwKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:purple_stained_glass", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnB1cnBsZV9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNoJk0DhRO0szUDCgBuZXR3b3JrX2lkD98ZxgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:magenta_stained_glass", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0Om1hZ2VudGFfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaFEDeFiJj3zSAwoAbmV0d29ya19pZG+iFRoKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:pink_stained_glass", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnBpbmtfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaDijTX87ywxhAwoAbmV0d29ya19pZKdEricKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:tinted_glass", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnRpbnRlZF9nbGFzcwQJAG5hbWVfaGFzaAFZWSamk6KdAwoAbmV0d29ya19pZGSvWX8KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:glass_pane", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmdsYXNzX3BhbmUECQBuYW1lX2hhc2gRSBHwNMQ4gQMKAG5ldHdvcmtfaWRGwixuCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:white_stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OndoaXRlX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaHgxQmgJVtRrAwoAbmV0d29ya19pZBEr/DYKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:light_gray_stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNon0aQw9lNkSEDCgBuZXR3b3JrX2lk9dp5VgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:gray_stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmdyYXlfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNors74IIw+2MMDCgBuZXR3b3JrX2lkmrGO5woGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:black_stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OmJsYWNrX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaOK/5ZRRd+M1AwoAbmV0d29ya19pZDv++oQKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:brown_stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OmJyb3duX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaLHeGJyRFTIWAwoAbmV0d29ya19pZMz9L0wKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:red_stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OnJlZF9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2gGr4x6JheAywMKAG5ldHdvcmtfaWQBjCTmCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:orange_stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0Om9yYW5nZV9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2hbHxPD2gEbEAMKAG5ldHdvcmtfaWSt/7a5CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:yellow_stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0OnllbGxvd19zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2g9tl4aOCyZBwMKAG5ldHdvcmtfaWTXRAS7CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:lime_stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmxpbWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNo3CtUyLwoGegDCgBuZXR3b3JrX2lkYJDnggoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:green_stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OmdyZWVuX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaJo6YP7IMy9SAwoAbmV0d29ya19pZHOnixoKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:cyan_stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmN5YW5fc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoti97c6QrbLQDCgBuZXR3b3JrX2lkUqFUeQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:light_blue_stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNovDg/gQle104DCgBuZXR3b3JrX2lkFuy4MQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:blue_stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmJsdWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoGc57tiexbQMDCgBuZXR3b3JrX2lk1eBLUAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:purple_stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0OnB1cnBsZV9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2hDJHYdd0FdfQMKAG5ldHdvcmtfaWSNsdK5CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:magenta_stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0Om1hZ2VudGFfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNo3pcOw5bs5XoDCgBuZXR3b3JrX2lkVbOR7AoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:pink_stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnBpbmtfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoWRhSACMWgswDCgBuZXR3b3JrX2lkIR92xwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:ladder", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmxhZGRlcgQJAG5hbWVfaGFzaKBhqheJVOz+AwoAbmV0d29ya19pZCgvzlsKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:scaffolding", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnNjYWZmb2xkaW5nBAkAbmFtZV9oYXNoYrkevrqcljwDCgBuZXR3b3JrX2lkD13mlAoGAHN0YXRlcwMJAHN0YWJpbGl0eQAAAAABDwBzdGFiaWxpdHlfY2hlY2sAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:stone_block_slab", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWTkNl0JCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQwAc21vb3RoX3N0b25lAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:stone_block_slab4", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkQJoxlgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNAUAc3RvbmUAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:stone_block_slab", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWRHh04KCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQsAY29iYmxlc3RvbmUAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:stone_block_slab2", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkVRZB+woGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhEAbW9zc3lfY29iYmxlc3RvbmUAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:wooden_slab", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lkBaobgAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20ICQB3b29kX3R5cGUDAG9hawADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:wooden_slab", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lkhz9TeQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20ICQB3b29kX3R5cGUGAHNwcnVjZQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:wooden_slab", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lk3HkwowoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20ICQB3b29kX3R5cGUFAGJpcmNoAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:wooden_slab", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lkDIBqVQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20ICQB3b29kX3R5cGUGAGp1bmdsZQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:wooden_slab", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lkL5hFYAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20ICQB3b29kX3R5cGUGAGFjYWNpYQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:wooden_slab", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lkKRUHSQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20ICQB3b29kX3R5cGUIAGRhcmtfb2FrAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:mangrove_slab", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Om1hbmdyb3ZlX3NsYWIECQBuYW1lX2hhc2jYCcmhJPeNMwMKAG5ldHdvcmtfaWQx6U1yCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:cherry_slab", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNoZXJyeV9zbGFiBAkAbmFtZV9oYXNoTt0MmVn/mqoDCgBuZXR3b3JrX2lk2VVsZQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:bamboo_slab", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmJhbWJvb19zbGFiBAkAbmFtZV9oYXNoo1xuFqINeLYDCgBuZXR3b3JrX2lkVC+0twoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:bamboo_mosaic_slab", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmJhbWJvb19tb3NhaWNfc2xhYgQJAG5hbWVfaGFzaNbVRBZ/ChI3AwoAbmV0d29ya19pZOLZHFMKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:stone_block_slab", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWQSiInOCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQsAc3RvbmVfYnJpY2sAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:stone_block_slab4", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkoF89tgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNBEAbW9zc3lfc3RvbmVfYnJpY2sAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:stone_block_slab", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWSkoAE4CgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQkAc2FuZHN0b25lAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:stone_block_slab4", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkWfF7pgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNA0AY3V0X3NhbmRzdG9uZQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:stone_block_slab2", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkbKRChAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAc21vb3RoX3NhbmRzdG9uZQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:stone_block_slab2", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkBlrvqAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMg0AcmVkX3NhbmRzdG9uZQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:stone_block_slab4", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkRWFXuwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNBEAY3V0X3JlZF9zYW5kc3RvbmUAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:stone_block_slab3", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkom8neQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxQAc21vb3RoX3JlZF9zYW5kc3RvbmUAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:stone_block_slab3", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkd1ZaWgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMwcAZ3Jhbml0ZQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:stone_block_slab3", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkISH4iwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxAAcG9saXNoZWRfZ3Jhbml0ZQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:stone_block_slab3", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkqxEDMwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMwcAZGlvcml0ZQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:stone_block_slab3", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkSYs86QoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxAAcG9saXNoZWRfZGlvcml0ZQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:stone_block_slab3", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkq6BU6goGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMwgAYW5kZXNpdGUAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:stone_block_slab3", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkTSXY8AoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxEAcG9saXNoZWRfYW5kZXNpdGUAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:stone_block_slab", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWQiYHKTCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQUAYnJpY2sAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:stone_block_slab", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWTk/0LfCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQwAbmV0aGVyX2JyaWNrAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:stone_block_slab2", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lk/hXQ7AoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAcmVkX25ldGhlcl9icmljawADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:stone_block_slab3", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkYJNxrwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMw8AZW5kX3N0b25lX2JyaWNrAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:stone_block_slab", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWRlj0/sCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQYAcXVhcnR6AAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:stone_block_slab4", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkMae+2goGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNA0Ac21vb3RoX3F1YXJ0egADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:stone_block_slab2", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lk+kMHGAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMgYAcHVycHVyAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:stone_block_slab2", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkKOSOMAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAcHJpc21hcmluZV9yb3VnaAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:stone_block_slab2", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lk8igLCQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMg8AcHJpc21hcmluZV9kYXJrAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:stone_block_slab2", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkSFbyEwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAcHJpc21hcmluZV9icmljawADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:crimson_slab", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmNyaW1zb25fc2xhYgQJAG5hbWVfaGFzaKZ+EfP0ZYOZAwoAbmV0d29ya19pZAxRUWAKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:warped_slab", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OndhcnBlZF9zbGFiBAkAbmFtZV9oYXNo/AT0e/Z9W7UDCgBuZXR3b3JrX2lk1yq11AoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:blackstone_slab", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmJsYWNrc3RvbmVfc2xhYgQJAG5hbWVfaGFzaF/DD4ZUlNgtAwoAbmV0d29ya19pZGy1DjwKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:polished_blackstone_slab", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfc2xhYgQJAG5hbWVfaGFzaDYnuUs86EWfAwoAbmV0d29ya19pZJj2bXIKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:polished_blackstone_brick_slab", - "block_state_b64": "CgAACAQAbmFtZSgAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfc2xhYgQJAG5hbWVfaGFzaKySLqvHc4xXAwoAbmV0d29ya19pZOyWX94KBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:cut_copper_slab", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmN1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaDsNpb2qs4iBAwoAbmV0d29ya19pZOTm2nsKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:exposed_cut_copper_slab", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcl9zbGFiBAkAbmFtZV9oYXNoahQ5OwIQb7kDCgBuZXR3b3JrX2lkrUlZLwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:weathered_cut_copper_slab", - "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyX3NsYWIECQBuYW1lX2hhc2hBIuGIOVVXogMKAG5ldHdvcmtfaWQgnaDiCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:oxidized_cut_copper_slab", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaOptj9ycfpaDAwoAbmV0d29ya19pZMzFSRgKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:waxed_cut_copper_slab", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaAlx6DZOCTHzAwoAbmV0d29ya19pZFRBvDAKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:waxed_exposed_cut_copper_slab", - "block_state_b64": "CgAACAQAbmFtZScAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcl9zbGFiBAkAbmFtZV9oYXNo3KqS5OnhtRIDCgBuZXR3b3JrX2lkHTGcTgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:waxed_weathered_cut_copper_slab", - "block_state_b64": "CgAACAQAbmFtZSkAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyX3NsYWIECQBuYW1lX2hhc2gzZ1oX0HCFtwMKAG5ldHdvcmtfaWSgJR+XCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:waxed_oxidized_cut_copper_slab", - "block_state_b64": "CgAACAQAbmFtZSgAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaMjjTnLu1KcqAwoAbmV0d29ya19pZIxsnFYKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:cobbled_deepslate_slab", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3NsYWIECQBuYW1lX2hhc2gwJIVWK1TM2QMKAG5ldHdvcmtfaWTYAoX5CgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:polished_deepslate_slab", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV9zbGFiBAkAbmFtZV9oYXNoC/Adiz8k6RYDCgBuZXR3b3JrX2lkuFYMAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:deepslate_tile_slab", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3NsYWIECQBuYW1lX2hhc2hPydV6emzIXAMKAG5ldHdvcmtfaWQwlbFCCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:deepslate_brick_slab", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja19zbGFiBAkAbmFtZV9oYXNoSv62V7iw10UDCgBuZXR3b3JrX2lkWMoragoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:mud_brick_slab", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0Om11ZF9icmlja19zbGFiBAkAbmFtZV9oYXNoq/tGBQWkv08DCgBuZXR3b3JrX2lkl4nnMwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:brick_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmJyaWNrX2Jsb2NrBAkAbmFtZV9oYXNo5Qc2E005S3oDCgBuZXR3b3JrX2lkqeGWRgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:chiseled_nether_bricks", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmNoaXNlbGVkX25ldGhlcl9icmlja3MECQBuYW1lX2hhc2g31SBPTcUK1QMKAG5ldHdvcmtfaWS8TJ+TCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:cracked_nether_bricks", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmNyYWNrZWRfbmV0aGVyX2JyaWNrcwQJAG5hbWVfaGFzaAdC6eKzXT5tAwoAbmV0d29ya19pZIUSejwKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:quartz_bricks", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnF1YXJ0el9icmlja3MECQBuYW1lX2hhc2jSZO590dd8sAMKAG5ldHdvcmtfaWSc5xCLCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:stonebrick", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWQ5kni1CgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQcAZGVmYXVsdAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:stonebrick", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWTDw813CgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQUAbW9zc3kAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:stonebrick", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWSTvQGECgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQcAY3JhY2tlZAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:stonebrick", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWQIM0OwCgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQgAY2hpc2VsZWQAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:end_bricks", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmVuZF9icmlja3MECQBuYW1lX2hhc2hIUFfxNLZaFgMKAG5ldHdvcmtfaWQ/vDihCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:prismarine", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnByaXNtYXJpbmUECQBuYW1lX2hhc2jcnQCHi9CspQMKAG5ldHdvcmtfaWSH021WCgYAc3RhdGVzCBUAcHJpc21hcmluZV9ibG9ja190eXBlBgBicmlja3MAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:polished_blackstone_bricks", - "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tzBAkAbmFtZV9oYXNoIHgsgIdzKXcDCgBuZXR3b3JrX2lkUw9b3woGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:cracked_polished_blackstone_bricks", - "block_state_b64": "CgAACAQAbmFtZSwAbWluZWNyYWZ0OmNyYWNrZWRfcG9saXNoZWRfYmxhY2tzdG9uZV9icmlja3MECQBuYW1lX2hhc2jQIO1GQDk80AMKAG5ldHdvcmtfaWQ3UlRYCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:gilded_blackstone", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmdpbGRlZF9ibGFja3N0b25lBAkAbmFtZV9oYXNoNoWt1ocG0HEDCgBuZXR3b3JrX2lktL8gUwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:chiseled_polished_blackstone", - "block_state_b64": "CgAACAQAbmFtZSYAbWluZWNyYWZ0OmNoaXNlbGVkX3BvbGlzaGVkX2JsYWNrc3RvbmUECQBuYW1lX2hhc2gzFa+kEjCJgAMKAG5ldHdvcmtfaWR2NJX2CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:deepslate_tiles", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlcwQJAG5hbWVfaGFzaGcLLx3NXAFvAwoAbmV0d29ya19pZI/G/xYKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:cracked_deepslate_tiles", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmNyYWNrZWRfZGVlcHNsYXRlX3RpbGVzBAkAbmFtZV9oYXNo9zWgkFuMM1QDCgBuZXR3b3JrX2lkGwY6OgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:deepslate_bricks", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja3MECQBuYW1lX2hhc2gucvFmPdZxigMKAG5ldHdvcmtfaWSH4HDPCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:cracked_deepslate_bricks", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OmNyYWNrZWRfZGVlcHNsYXRlX2JyaWNrcwQJAG5hbWVfaGFzaN40aqhh9WqHAwoAbmV0d29ya19pZO9GPBQKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:chiseled_deepslate", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmNoaXNlbGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaEU7/uRG8HSBAwoAbmV0d29ya19pZEqmI0EKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:cobblestone", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvYmJsZXN0b25lBAkAbmFtZV9oYXNoPoK7mGlSUz4DCgBuZXR3b3JrX2lkLm7RZwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:mossy_cobblestone", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0Om1vc3N5X2NvYmJsZXN0b25lBAkAbmFtZV9oYXNoGJ67FCbkChMDCgBuZXR3b3JrX2lk/pYs1AoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:cobbled_deepslate", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlBAkAbmFtZV9oYXNoLUz9Y/ywmLwDCgBuZXR3b3JrX2lkNwzZ+AoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:smooth_stone", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnNtb290aF9zdG9uZQQJAG5hbWVfaGFzaMwf87/JaTNvAwoAbmV0d29ya19pZLkZICEKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:sandstone", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZB2wApMKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGUHAGRlZmF1bHQAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:sandstone", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZB7E+eQKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGULAGhlaXJvZ2x5cGhzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:sandstone", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZFQnDaEKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGUDAGN1dAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:sandstone", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZPO4A3IKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGUGAHNtb290aAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:red_sandstone", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWRhNYiFCgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlBwBkZWZhdWx0AAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:red_sandstone", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWTqXJr1CgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlCwBoZWlyb2dseXBocwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:red_sandstone", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWTQRGkFCgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlAwBjdXQAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:red_sandstone", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWTvAHWDCgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlBgBzbW9vdGgAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:coal_block", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmNvYWxfYmxvY2sECQBuYW1lX2hhc2jH8QQP3t5PiAMKAG5ldHdvcmtfaWRo+sR+CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:dried_kelp_block", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmRyaWVkX2tlbHBfYmxvY2sECQBuYW1lX2hhc2iRoucexkrl8wMKAG5ldHdvcmtfaWQQCCrvCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:gold_block", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmdvbGRfYmxvY2sECQBuYW1lX2hhc2iYLshvjtXzFwMKAG5ldHdvcmtfaWTDJGBcCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:iron_block", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Omlyb25fYmxvY2sECQBuYW1lX2hhc2jYINmJQbvV/gMKAG5ldHdvcmtfaWRf7AbICgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:copper_block", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmNvcHBlcl9ibG9jawQJAG5hbWVfaGFzaDVxnehsGaZ1AwoAbmV0d29ya19pZIiUodwKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:exposed_copper", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmV4cG9zZWRfY29wcGVyBAkAbmFtZV9oYXNoQH3Fukmu3CEDCgBuZXR3b3JrX2lk72jFIwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:weathered_copper", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OndlYXRoZXJlZF9jb3BwZXIECQBuYW1lX2hhc2hJCQXbvobv+gMKAG5ldHdvcmtfaWQwM0lJCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:oxidized_copper", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om94aWRpemVkX2NvcHBlcgQJAG5hbWVfaGFzaMDtJqR0G5Y7AwoAbmV0d29ya19pZGjN8bUKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:waxed_copper", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OndheGVkX2NvcHBlcgQJAG5hbWVfaGFzaPF+FG6Eh5fsAwoAbmV0d29ya19pZIjtz/0KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:waxed_exposed_copper", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY29wcGVyBAkAbmFtZV9oYXNoig8IOc+SCikDCgBuZXR3b3JrX2lklz8yWQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:waxed_weathered_copper", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jb3BwZXIECQBuYW1lX2hhc2gjtPq8MOdvKgMKAG5ldHdvcmtfaWSQ9Ln9CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:waxed_oxidized_copper", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OndheGVkX294aWRpemVkX2NvcHBlcgQJAG5hbWVfaGFzaMaORhsO+LzjAwoAbmV0d29ya19pZJhGfLEKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:cut_copper", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmN1dF9jb3BwZXIECQBuYW1lX2hhc2hAfN3NGax3eAMKAG5ldHdvcmtfaWTnFBtYCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:exposed_cut_copper", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcgQJAG5hbWVfaGFzaA85G3yv/w6pAwoAbmV0d29ya19pZMQhr0QKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:weathered_cut_copper", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyBAkAbmFtZV9oYXNoVgRV0fBaz88DCgBuZXR3b3JrX2lk/0cYugoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:oxidized_cut_copper", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2iP8WmFWOkriwMKAG5ldHdvcmtfaWQPdce7CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:waxed_cut_copper", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2jumiwOZIqv2AMKAG5ldHdvcmtfaWQvuxx9CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:waxed_exposed_cut_copper", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcgQJAG5hbWVfaGFzaPE/OfK6IoVMAwoAbmV0d29ya19pZHy5HkcKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:waxed_weathered_cut_copper", - "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyBAkAbmFtZV9oYXNoCA1xDp11bnwDCgBuZXR3b3JrX2lkDyEDVQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:waxed_oxidized_cut_copper", - "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2i1pZAsZYHLDAMKAG5ldHdvcmtfaWQ/wSkCCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:emerald_block", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmVtZXJhbGRfYmxvY2sECQBuYW1lX2hhc2hK6QunqJznNAMKAG5ldHdvcmtfaWRk5+otCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:diamond_block", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmRpYW1vbmRfYmxvY2sECQBuYW1lX2hhc2iGKrxuvkytFQMKAG5ldHdvcmtfaWQQeQZXCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:lapis_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmxhcGlzX2Jsb2NrBAkAbmFtZV9oYXNoDZ44xdb2zVoDCgBuZXR3b3JrX2lktVy0BAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:raw_iron_block", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnJhd19pcm9uX2Jsb2NrBAkAbmFtZV9oYXNo9XyzNIQXxvwDCgBuZXR3b3JrX2lknms1QAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:raw_copper_block", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnJhd19jb3BwZXJfYmxvY2sECQBuYW1lX2hhc2hw1KG0TNUGgwMKAG5ldHdvcmtfaWS1vGo/CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:raw_gold_block", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnJhd19nb2xkX2Jsb2NrBAkAbmFtZV9oYXNo6YuwuLwfOBwDCgBuZXR3b3JrX2lkLiQ5gQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:quartz_block", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZEupC1AKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQcAZGVmYXVsdAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:quartz_block", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZM97+l0KBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQUAbGluZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:quartz_block", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZCbTfssKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQgAY2hpc2VsZWQICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:quartz_block", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZJss8V0KBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQYAc21vb3RoCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:prismarine", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnByaXNtYXJpbmUECQBuYW1lX2hhc2jcnQCHi9CspQMKAG5ldHdvcmtfaWRFIsoGCgYAc3RhdGVzCBUAcHJpc21hcmluZV9ibG9ja190eXBlBwBkZWZhdWx0AAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:prismarine", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnByaXNtYXJpbmUECQBuYW1lX2hhc2jcnQCHi9CspQMKAG5ldHdvcmtfaWTDNWOvCgYAc3RhdGVzCBUAcHJpc21hcmluZV9ibG9ja190eXBlBABkYXJrAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:slime", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnNsaW1lBAkAbmFtZV9oYXNoHJiEEJx+JlkDCgBuZXR3b3JrX2lkfgfVzAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:honey_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmhvbmV5X2Jsb2NrBAkAbmFtZV9oYXNo9zLYSUlelywDCgBuZXR3b3JrX2lko+dyWgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:honeycomb_block", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmhvbmV5Y29tYl9ibG9jawQJAG5hbWVfaGFzaASIPuOCYd1oAwoAbmV0d29ya19pZKys4n4KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:hay_block", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmhheV9ibG9jawQJAG5hbWVfaGFzaIB2VxKxX8EpAwoAbmV0d29ya19pZKuQSloKBgBzdGF0ZXMDCgBkZXByZWNhdGVkAAAAAAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:bone_block", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmJvbmVfYmxvY2sECQBuYW1lX2hhc2i4ZX576W9AWgMKAG5ldHdvcmtfaWTWGacQCgYAc3RhdGVzAwoAZGVwcmVjYXRlZAAAAAAICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:nether_brick", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0Om5ldGhlcl9icmljawQJAG5hbWVfaGFzaMxcRiheU+nXAwoAbmV0d29ya19pZMkmzloKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:red_nether_brick", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnJlZF9uZXRoZXJfYnJpY2sECQBuYW1lX2hhc2j8pRO4LfoECAMKAG5ldHdvcmtfaWRpdF0YCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:netherite_block", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om5ldGhlcml0ZV9ibG9jawQJAG5hbWVfaGFzaMghh6Zib/ZKAwoAbmV0d29ya19pZIz0mq0KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:lodestone", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmxvZGVzdG9uZQQJAG5hbWVfaGFzaJ2gmHOTlXv8AwoAbmV0d29ya19pZEfgB4wKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:white_wool", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OndoaXRlX3dvb2wECQBuYW1lX2hhc2jRWB7vaIEDiQMKAG5ldHdvcmtfaWSO8paQCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:light_gray_wool", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfd29vbAQJAG5hbWVfaGFzaOpdQ1a2v4b3AwoAbmV0d29ya19pZIqZCYEKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:gray_wool", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmdyYXlfd29vbAQJAG5hbWVfaGFzaLsc1Lp1xdIOAwoAbmV0d29ya19pZFUs+HgKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:black_wool", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmJsYWNrX3dvb2wECQBuYW1lX2hhc2hP2HC6o0X4HAMKAG5ldHdvcmtfaWRUbORcCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:brown_wool", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmJyb3duX3dvb2wECQBuYW1lX2hhc2ig5IW89PrREwMKAG5ldHdvcmtfaWRjT9j8CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:red_wool", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OnJlZF93b29sBAkAbmFtZV9oYXNoY4TBDq+mFgUDCgBuZXR3b3JrX2lktn9lcAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:orange_wool", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om9yYW5nZV93b29sBAkAbmFtZV9oYXNoFstfrTZfSCgDCgBuZXR3b3JrX2lk+rqywwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:yellow_wool", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnllbGxvd193b29sBAkAbmFtZV9oYXNoTFyus2RHegcDCgBuZXR3b3JrX2lkkKBhXAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:lime_wool", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmxpbWVfd29vbAQJAG5hbWVfaGFzaNVnnzKiMxmeAwoAbmV0d29ya19pZG9b32kKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:green_wool", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmdyZWVuX3dvb2wECQBuYW1lX2hhc2i3mElRYHIcSQMKAG5ldHdvcmtfaWSssprwCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:cyan_wool", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmN5YW5fd29vbAQJAG5hbWVfaGFzaBNDfvHn8dqFAwoAbmV0d29ya19pZK0hAbgKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:light_blue_wool", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfd29vbAQJAG5hbWVfaGFzaLWFAUfyxFPNAwoAbmV0d29ya19pZL2oEugKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:blue_wool", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmJsdWVfd29vbAQJAG5hbWVfaGFzaLjHyxxbTWCLAwoAbmV0d29ya19pZPaLdFQKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:purple_wool", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnB1cnBsZV93b29sBAkAbmFtZV9oYXNojvFtqzjAf/4DCgBuZXR3b3JrX2lklqASNQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:magenta_wool", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0Om1hZ2VudGFfd29vbAQJAG5hbWVfaGFzaGuOHvf+Pd4yAwoAbmV0d29ya19pZI4UoDQKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:pink_wool", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnBpbmtfd29vbAQJAG5hbWVfaGFzaPiVA2pFeoFLAwoAbmV0d29ya19pZOZRO6oKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:white_carpet", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OndoaXRlX2NhcnBldAQJAG5hbWVfaGFzaNeMHTI1fWPXAwoAbmV0d29ya19pZEahDFcKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:light_gray_carpet", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY2FycGV0BAkAbmFtZV9oYXNoHPw6ArBAsP0DCgBuZXR3b3JrX2lkQoAeUAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:gray_carpet", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmdyYXlfY2FycGV0BAkAbmFtZV9oYXNoZVR0OI+1VRADCgBuZXR3b3JrX2lkETF4WwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:black_carpet", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJsYWNrX2NhcnBldAQJAG5hbWVfaGFzaOk7LP9NptyhAwoAbmV0d29ya19pZFjmXtIKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:brown_carpet", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJyb3duX2NhcnBldAQJAG5hbWVfaGFzaNaXFyOsAvIvAwoAbmV0d29ya19pZHPjFuoKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:red_carpet", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9jYXJwZXQECQBuYW1lX2hhc2i9eSKBf6SO3wMKAG5ldHdvcmtfaWQuhI/KCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:orange_carpet", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Om9yYW5nZV9jYXJwZXQECQBuYW1lX2hhc2hIUkO4HlAdygMKAG5ldHdvcmtfaWSyKV9OCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:yellow_carpet", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19jYXJwZXQECQBuYW1lX2hhc2hSDKX3scCamwMKAG5ldHdvcmtfaWT8nq+ECgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:lime_carpet", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmxpbWVfY2FycGV0BAkAbmFtZV9oYXNo+6KFOpzsib4DCgBuZXR3b3JrX2lkT+DS4woGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:green_carpet", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmdyZWVuX2NhcnBldAQJAG5hbWVfaGFzaCHPMP9ltqFJAwoAbmV0d29ya19pZBgwAvAKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:cyan_carpet", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmN5YW5fY2FycGV0BAkAbmFtZV9oYXNobXf62dQBJj8DCgBuZXR3b3JrX2lkKVppLgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:light_blue_carpet", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY2FycGV0BAkAbmFtZV9oYXNo20l4oktdZ3sDCgBuZXR3b3JrX2lkjdeMiwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:blue_carpet", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmJsdWVfY2FycGV0BAkAbmFtZV9oYXNo3p3lsW0eQwsDCgBuZXR3b3JrX2lkAovdPQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:purple_carpet", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnBsZV9jYXJwZXQECQBuYW1lX2hhc2jwIA9pW/qp7QMKAG5ldHdvcmtfaWTqJqhjCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:magenta_carpet", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hZ2VudGFfY2FycGV0BAkAbmFtZV9oYXNoFXT36YNNZhMDCgBuZXR3b3JrX2lk+tqsGAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:pink_carpet", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfY2FycGV0BAkAbmFtZV9oYXNoHll72oqk+OoDCgBuZXR3b3JrX2lkrnBYDwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:white_concrete_powder", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OndoaXRlX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaFUk9iXVjwV8AwoAbmV0d29ya19pZJPZY8AKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:light_gray_concrete_powder", - "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNo7EUk30hmUtYDCgBuZXR3b3JrX2lkh8jVIwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:gray_concrete_powder", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmdyYXlfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoW77af6WihdwDCgBuZXR3b3JrX2lkSsqC1woGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:black_concrete_powder", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmJsYWNrX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaAfWYp0xtgcfAwoAbmV0d29ya19pZMWTC8EKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:brown_concrete_powder", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmJyb3duX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaB74EeiLO46XAwoAbmV0d29ya19pZEDHKqwKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:red_concrete_powder", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OnJlZF9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2gjFut6Z/VH1gMKAG5ldHdvcmtfaWSvcmwYCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:orange_concrete_powder", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0Om9yYW5nZV9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2gADDj2IJiw+gMKAG5ldHdvcmtfaWTHph0FCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:yellow_concrete_powder", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OnllbGxvd19jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2iy6qKNn3ob5wMKAG5ldHdvcmtfaWQZAI39CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:lime_concrete_powder", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmxpbWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNo4dYIPslbXPUDCgBuZXR3b3JrX2lk2O8X0AoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:green_concrete_powder", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmdyZWVuX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaM/c9x2aJh3HAwoAbmV0d29ya19pZA0VfBMKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:cyan_concrete_powder", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmN5YW5fY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNok+xKAe7XXjoDCgBuZXR3b3JrX2lkmkn6uwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:light_blue_concrete_powder", - "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNogScpIQceyAEDCgBuZXR3b3JrX2lkOmVSbgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:blue_concrete_powder", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmJsdWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoFp7mmeL86r0DCgBuZXR3b3JrX2lkS3b3RQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:purple_concrete_powder", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OnB1cnBsZV9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2iYcVU04hoStwMKAG5ldHdvcmtfaWQXimEjCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:magenta_concrete_powder", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0Om1hZ2VudGFfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoy/70q6VPsWgDCgBuZXR3b3JrX2lkf9mxQwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:pink_concrete_powder", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnBpbmtfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoVikSAf8DwV0DCgBuZXR3b3JrX2lku2MivwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:white_concrete", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OndoaXRlX2NvbmNyZXRlBAkAbmFtZV9oYXNo6zAp7lsLlvkDCgBuZXR3b3JrX2lk3MAYQAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:light_gray_concrete", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY29uY3JldGUECQBuYW1lX2hhc2hEtet5wuDIKAMKAG5ldHdvcmtfaWQISs02CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:gray_concrete", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmdyYXlfY29uY3JldGUECQBuYW1lX2hhc2j92INnb0a83AMKAG5ldHdvcmtfaWQj8RHwCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:black_concrete", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmJsYWNrX2NvbmNyZXRlBAkAbmFtZV9oYXNo2X7NDIQmZ70DCgBuZXR3b3JrX2lk2uiVDQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:brown_concrete", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmJyb3duX2NvbmNyZXRlBAkAbmFtZV9oYXNoeka02BwXf6oDCgBuZXR3b3JrX2lkYf+xDQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:red_concrete", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZF9jb25jcmV0ZQQJAG5hbWVfaGFzaPWmNowLGubqAwoAbmV0d29ya19pZKwyx58KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:orange_concrete", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om9yYW5nZV9jb25jcmV0ZQQJAG5hbWVfaGFzaAgE8XmaAi6+AwoAbmV0d29ya19pZMDQNz8KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:yellow_concrete", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnllbGxvd19jb25jcmV0ZQQJAG5hbWVfaGFzaE6ONfJPBd0+AwoAbmV0d29ya19pZMarutwKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:lime_concrete", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmxpbWVfY29uY3JldGUECQBuYW1lX2hhc2gnd8JW6wmJcAMKAG5ldHdvcmtfaWTd47aoCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:green_concrete", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmdyZWVuX2NvbmNyZXRlBAkAbmFtZV9oYXNokbFxRKchQZkDCgBuZXR3b3JrX2lkmhZWUgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:cyan_concrete", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmN5YW5fY29uY3JldGUECQBuYW1lX2hhc2hFRrWJ33qj1wMKAG5ldHdvcmtfaWQbi5b8CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:light_blue_concrete", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY29uY3JldGUECQBuYW1lX2hhc2gHAe0kl0SE4AMKAG5ldHdvcmtfaWRL/GbSCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:blue_concrete", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmJsdWVfY29uY3JldGUECQBuYW1lX2hhc2hiay301nnj1wMKAG5ldHdvcmtfaWRMvFXNCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:purple_concrete", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnB1cnBsZV9jb25jcmV0ZQQJAG5hbWVfaGFzaHBHflsPIwdXAwoAbmV0d29ya19pZCyKA5gKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:magenta_concrete", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0Om1hZ2VudGFfY29uY3JldGUECQBuYW1lX2hhc2gN7LuB/OvdZAMKAG5ldHdvcmtfaWTc6ZOdCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:pink_concrete", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnBpbmtfY29uY3JldGUECQBuYW1lX2hhc2ii2G5F0u3SOAMKAG5ldHdvcmtfaWSszGgrCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:clay", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OmNsYXkECQBuYW1lX2hhc2j/S6sKXRcpzwMKAG5ldHdvcmtfaWRmsb8nCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:hardened_clay", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmhhcmRlbmVkX2NsYXkECQBuYW1lX2hhc2jrnRwCJ0krJAMKAG5ldHdvcmtfaWRBCOrrCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:white_terracotta", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OndoaXRlX3RlcnJhY290dGEECQBuYW1lX2hhc2j3RSdgmnAIewMKAG5ldHdvcmtfaWSimKw+CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:light_gray_terracotta", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmxpZ2h0X2dyYXlfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAz1Ri3wIxomAwoAbmV0d29ya19pZH5qgOcKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:gray_terracotta", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmdyYXlfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAXdSLAaNZ9vAwoAbmV0d29ya19pZM1QDV0KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:black_terracotta", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmJsYWNrX3RlcnJhY290dGEECQBuYW1lX2hhc2jxssdv5vlbpgMKAG5ldHdvcmtfaWRE3Ru/CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:brown_terracotta", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmJyb3duX3RlcnJhY290dGEECQBuYW1lX2hhc2gG4kPenmOF9gMKAG5ldHdvcmtfaWQ/i0iNCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:red_terracotta", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNo7fX56HXFejEDCgBuZXR3b3JrX2lk8tTF8QoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:orange_terracotta", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0Om9yYW5nZV90ZXJyYWNvdHRhBAkAbmFtZV9oYXNo0Hjmql3sruMDCgBuZXR3b3JrX2lklmqmkAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:yellow_terracotta", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnllbGxvd190ZXJyYWNvdHRhBAkAbmFtZV9oYXNoqkyKKrmA3VcDCgBuZXR3b3JrX2lkaM/orAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:lime_terracotta", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmxpbWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaANjADFOF9v7AwoAbmV0d29ya19pZJt0XsgKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:green_terracotta", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmdyZWVuX3RlcnJhY290dGEECQBuYW1lX2hhc2j5Ybq36yYwRQMKAG5ldHdvcmtfaWQ8kGdHCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:cyan_terracotta", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmN5YW5fdGVycmFjb3R0YQQJAG5hbWVfaGFzaN09COzMuHwAAwoAbmV0d29ya19pZIWPCzoKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:light_blue_terracotta", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmxpZ2h0X2JsdWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaOMytez7cOZiAwoAbmV0d29ya19pZFHK1UsKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:blue_terracotta", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmJsdWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaF6inyTK5RpAAwoAbmV0d29ya19pZF5mVZIKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:purple_terracotta", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnB1cnBsZV90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoKF7YG61yTbEDCgBuZXR3b3JrX2lkhtRDlwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:magenta_terracotta", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0Om1hZ2VudGFfdGVycmFjb3R0YQQJAG5hbWVfaGFzaLWvtpAVtztyAwoAbmV0d29ya19pZN5SoakKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:pink_terracotta", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnBpbmtfdGVycmFjb3R0YQQJAG5hbWVfaGFzaJ7mzvyzSQZTAwoAbmV0d29ya19pZDJWe4YKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:white_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OndoaXRlX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoiVzCdoHAJo0DCgBuZXR3b3JrX2lkIlj9AAoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:silver_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnNpbHZlcl9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAVsA0CnhzA4AwoAbmV0d29ya19pZPnxtJEKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:gray_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmdyYXlfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2jvLZt9u/lF/AMKAG5ldHdvcmtfaWQVU8eFCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:black_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmJsYWNrX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoe8I4xAXbO5UDCgBuZXR3b3JrX2lk2Icb9AoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:brown_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmJyb3duX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoSiNZOobbpjoDCgBuZXR3b3JrX2lkJy0jwgoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:red_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnJlZF9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaBdWFGLmCLFVAwoAbmV0d29ya19pZMYBJSEKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:orange_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0Om9yYW5nZV9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaMyJMrnPr7szAwoAbmV0d29ya19pZN6+7TUKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:yellow_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnllbGxvd19nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaN6NaIhf6m0uAwoAbmV0d29ya19pZKRHXeoKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:lime_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmxpbWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2iF3E68/rB2EAMKAG5ldHdvcmtfaWSP7qQWCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:green_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmdyZWVuX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNow5mo8aQDFboDCgBuZXR3b3JrX2lkoF11kgoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:cyan_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmN5YW5fZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2gnNB+cCFRJhwMKAG5ldHdvcmtfaWT9buMtCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:light_blue_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSYAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2gladnCDBKCigMKAG5ldHdvcmtfaWS5CszFCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:blue_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmJsdWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2giOZK+2nB1igMKAG5ldHdvcmtfaWR+e22CCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:purple_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnB1cnBsZV9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaIQU03txeAfHAwoAbmV0d29ya19pZLKbSE4KBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:magenta_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0Om1hZ2VudGFfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2i/SNqDJbfjMgMKAG5ldHdvcmtfaWQKf9UvCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:pink_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OnBpbmtfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2hik8DVt4g+twMKAG5ldHdvcmtfaWTKzav2CgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:purpur_block", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnB1cnB1cl9ibG9jawQJAG5hbWVfaGFzaAgLwnUZGlzsAwoAbmV0d29ya19pZLD8ox4KBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQcAZGVmYXVsdAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:purpur_block", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnB1cnB1cl9ibG9jawQJAG5hbWVfaGFzaAgLwnUZGlzsAwoAbmV0d29ya19pZPSAFFsKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQUAbGluZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:packed_mud", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnBhY2tlZF9tdWQECQBuYW1lX2hhc2gHOMa121h4FgMKAG5ldHdvcmtfaWTUb6LyCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:mud_bricks", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Om11ZF9icmlja3MECQBuYW1lX2hhc2iDL/SVl/PewQMKAG5ldHdvcmtfaWSkBjaDCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:nether_wart_block", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0Om5ldGhlcl93YXJ0X2Jsb2NrBAkAbmFtZV9oYXNo9XGS4GNnlV4DCgBuZXR3b3JrX2lkh3apIgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:warped_wart_block", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OndhcnBlZF93YXJ0X2Jsb2NrBAkAbmFtZV9oYXNo9IqDS9yUPJoDCgBuZXR3b3JrX2lkMpKAbAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:shroomlight", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnNocm9vbWxpZ2h0BAkAbmFtZV9oYXNoZHCHcHX/HYADCgBuZXR3b3JrX2lkLG2JiwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:crimson_nylium", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fbnlsaXVtBAkAbmFtZV9oYXNoOr6DJYW2bFYDCgBuZXR3b3JrX2lkuWpRDgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:warped_nylium", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9ueWxpdW0ECQBuYW1lX2hhc2g0Zf89cfr3rwMKAG5ldHdvcmtfaWSu/kekCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:netherrack", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Om5ldGhlcnJhY2sECQBuYW1lX2hhc2i/r5ZyRsvPyQMKAG5ldHdvcmtfaWTAiTOACgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:basalt", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmJhc2FsdAQJAG5hbWVfaGFzaH+UQO2yWodiAwoAbmV0d29ya19pZBPNSV4KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:polished_basalt", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnBvbGlzaGVkX2Jhc2FsdAQJAG5hbWVfaGFzaMS+L0gMnRcBAwoAbmV0d29ya19pZF+/mHwKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:smooth_basalt", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnNtb290aF9iYXNhbHQECQBuYW1lX2hhc2jKPUdz89kuNAMKAG5ldHdvcmtfaWTkb/oVCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:soul_soil", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnNvdWxfc29pbAQJAG5hbWVfaGFzaC1/87ccutuTAwoAbmV0d29ya19pZKc63SMKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:dirt", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OmRpcnQECQBuYW1lX2hhc2hXp6jnXAe+kQMKAG5ldHdvcmtfaWQmkQtoCgYAc3RhdGVzCAkAZGlydF90eXBlBgBub3JtYWwAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:dirt", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OmRpcnQECQBuYW1lX2hhc2hXp6jnXAe+kQMKAG5ldHdvcmtfaWQId9pLCgYAc3RhdGVzCAkAZGlydF90eXBlBgBjb2Fyc2UAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:farmland", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OmZhcm1sYW5kBAkAbmFtZV9oYXNoxyQ5ag7LolADCgBuZXR3b3JrX2lkX618FQoGAHN0YXRlcwMSAG1vaXN0dXJpemVkX2Ftb3VudAAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:grass", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmdyYXNzBAkAbmFtZV9oYXNosppASPWFlsUDCgBuZXR3b3JrX2lkhLLQkQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:grass_path", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmdyYXNzX3BhdGgECQBuYW1lX2hhc2i0/KZV8Qsy+gMKAG5ldHdvcmtfaWT7CcdzCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:podzol", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBvZHpvbAQJAG5hbWVfaGFzaBzqokRjH4Z1AwoAbmV0d29ya19pZPPS/GUKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:mycelium", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0Om15Y2VsaXVtBAkAbmFtZV9oYXNojTN09cKickIDCgBuZXR3b3JrX2lkLNPxXQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:mud", - "block_state_b64": "CgAACAQAbmFtZQ0AbWluZWNyYWZ0Om11ZAQJAG5hbWVfaGFzaPb/3P+uLy+9AwoAbmV0d29ya19pZPIUlUkKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:stone", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lky8FPmgoGAHN0YXRlcwgKAHN0b25lX3R5cGUFAHN0b25lAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:iron_ore", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0Omlyb25fb3JlBAkAbmFtZV9oYXNoS7BYtLnfx3gDCgBuZXR3b3JrX2lk3loneQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:gold_ore", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OmdvbGRfb3JlBAkAbmFtZV9oYXNoC5Y+DUGXLC4DCgBuZXR3b3JrX2lkNhvMfwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:diamond_ore", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmRpYW1vbmRfb3JlBAkAbmFtZV9oYXNokUOJ2wZZrGQDCgBuZXR3b3JrX2lk/dChVAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:lapis_ore", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmxhcGlzX29yZQQJAG5hbWVfaGFzaMrmrUrSzb7qAwoAbmV0d29ya19pZMg+qK4KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:redstone_ore", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZHN0b25lX29yZQQJAG5hbWVfaGFzaFHVnp8Wc4JbAwoAbmV0d29ya19pZKDYvQoKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:coal_ore", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OmNvYWxfb3JlBAkAbmFtZV9oYXNo1OjA+Iuy51oDCgBuZXR3b3JrX2lk+R/aKAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:copper_ore", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmNvcHBlcl9vcmUECQBuYW1lX2hhc2iSZduSntOzOwMKAG5ldHdvcmtfaWQtIuCnCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:emerald_ore", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmVtZXJhbGRfb3JlBAkAbmFtZV9oYXNoJTovr+VgINsDCgBuZXR3b3JrX2lknbkqCgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:quartz_ore", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnF1YXJ0el9vcmUECQBuYW1lX2hhc2g0yNHLMK9TaQMKAG5ldHdvcmtfaWSzN7nzCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:nether_gold_ore", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om5ldGhlcl9nb2xkX29yZQQJAG5hbWVfaGFzaEJZ7segIBgBAwoAbmV0d29ya19pZNI9pDgKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:ancient_debris", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmFuY2llbnRfZGVicmlzBAkAbmFtZV9oYXNoNrbxMc9AwKcDCgBuZXR3b3JrX2lkrSNjEAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:deepslate_iron_ore", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9pcm9uX29yZQQJAG5hbWVfaGFzaB/fDL9pgvXXAwoAbmV0d29ya19pZFA0bz4KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:deepslate_gold_ore", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9nb2xkX29yZQQJAG5hbWVfaGFzaF9G7WYhKFinAwoAbmV0d29ya19pZHQTfBUKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:deepslate_diamond_ore", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV9kaWFtb25kX29yZQQJAG5hbWVfaGFzaEUH5USh+iD3AwoAbmV0d29ya19pZHP6VzAKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:deepslate_lapis_ore", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV9sYXBpc19vcmUECQBuYW1lX2hhc2j+yFxU/KZs1gMKAG5ldHdvcmtfaWRKINzICgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:deepslate_redstone_ore", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmRlZXBzbGF0ZV9yZWRzdG9uZV9vcmUECQBuYW1lX2hhc2iVgM3wWWD6ugMKAG5ldHdvcmtfaWReBdYRCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:deepslate_emerald_ore", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV9lbWVyYWxkX29yZQQJAG5hbWVfaGFzaNlfo5HTwS6wAwoAbmV0d29ya19pZNeie6sKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:deepslate_coal_ore", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9jb2FsX29yZQQJAG5hbWVfaGFzaIjikmcbRrPPAwoAbmV0d29ya19pZD9TiygKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:deepslate_copper_ore", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9jb3BwZXJfb3JlBAkAbmFtZV9oYXNottjV4Ev5LAQDCgBuZXR3b3JrX2lkP23rgQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:gravel", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmdyYXZlbAQJAG5hbWVfaGFzaOFxz8XJd2r/AwoAbmV0d29ya19pZBpfI1sKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:stone", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lkbtgs0goGAHN0YXRlcwgKAHN0b25lX3R5cGUHAGdyYW5pdGUAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:stone", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lk3sDePAoGAHN0YXRlcwgKAHN0b25lX3R5cGUHAGRpb3JpdGUAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:stone", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lkYG+0YwoGAHN0YXRlcwgKAHN0b25lX3R5cGUIAGFuZGVzaXRlAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:blackstone", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmJsYWNrc3RvbmUECQBuYW1lX2hhc2iMFYziD80D6QMKAG5ldHdvcmtfaWSrUryHCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:deepslate", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmRlZXBzbGF0ZQQJAG5hbWVfaGFzaKX5pAblxz8TAwoAbmV0d29ya19pZOJoQjsKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:stone", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lkREbyhwoGAHN0YXRlcwgKAHN0b25lX3R5cGUOAGdyYW5pdGVfc21vb3RoAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:stone", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lk/EZ3UwoGAHN0YXRlcwgKAHN0b25lX3R5cGUOAGRpb3JpdGVfc21vb3RoAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:stone", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lkmjeVIwoGAHN0YXRlcwgKAHN0b25lX3R5cGUPAGFuZGVzaXRlX3Ntb290aAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:polished_blackstone", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmUECQBuYW1lX2hhc2jT9fHCl6vWQQMKAG5ldHdvcmtfaWR/Ho6oCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:polished_deepslate", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaHC1edoaWF3uAwoAbmV0d29ya19pZCPeQsEKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:sand", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OnNhbmQECQBuYW1lX2hhc2i6lthXXbAyWAMKAG5ldHdvcmtfaWTekU/mCgYAc3RhdGVzCAkAc2FuZF90eXBlBgBub3JtYWwAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:sand", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OnNhbmQECQBuYW1lX2hhc2i6lthXXbAyWAMKAG5ldHdvcmtfaWSTgcqmCgYAc3RhdGVzCAkAc2FuZF90eXBlAwByZWQAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:cactus", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmNhY3R1cwQJAG5hbWVfaGFzaCG9zL0N4wvGAwoAbmV0d29ya19pZDeCERAKBgBzdGF0ZXMDAwBhZ2UAAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:oak_log", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0Om9ha19sb2cECQBuYW1lX2hhc2ho6TS+K7PZFQMKAG5ldHdvcmtfaWQjfjoxCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:stripped_oak_log", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0cmlwcGVkX29ha19sb2cECQBuYW1lX2hhc2h8dqh+OOHU4wMKAG5ldHdvcmtfaWSYKjdrCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:spruce_log", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnNwcnVjZV9sb2cECQBuYW1lX2hhc2hZ03qaLoF3WgMKAG5ldHdvcmtfaWRlFD8eCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:stripped_spruce_log", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX3NwcnVjZV9sb2cECQBuYW1lX2hhc2iNrhKjS5IyrgMKAG5ldHdvcmtfaWRQcEC3CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:birch_log", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmJpcmNoX2xvZwQJAG5hbWVfaGFzaBUzT3NxsZAnAwoAbmV0d29ya19pZBKN3VQKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:stripped_birch_log", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnN0cmlwcGVkX2JpcmNoX2xvZwQJAG5hbWVfaGFzaCFKS4AeuSidAwoAbmV0d29ya19pZN0IONIKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:jungle_log", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Omp1bmdsZV9sb2cECQBuYW1lX2hhc2gkwW0KNulqDgMKAG5ldHdvcmtfaWQaziU/CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:stripped_jungle_log", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2p1bmdsZV9sb2cECQBuYW1lX2hhc2hAwMsgOk02JAMKAG5ldHdvcmtfaWQvls0eCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:acacia_log", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmFjYWNpYV9sb2cECQBuYW1lX2hhc2iV48VpYhjoYQMKAG5ldHdvcmtfaWRxEqe0CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:stripped_acacia_log", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2FjYWNpYV9sb2cECQBuYW1lX2hhc2hJb0lQqnEqlgMKAG5ldHdvcmtfaWRg3IdRCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:dark_oak_log", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRhcmtfb2FrX2xvZwQJAG5hbWVfaGFzaIWfVRd0XUo3AwoAbmV0d29ya19pZPMM7LYKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:stripped_dark_oak_log", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2Rhcmtfb2FrX2xvZwQJAG5hbWVfaGFzaPFTdxRdPwkOAwoAbmV0d29ya19pZDIzenIKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:mangrove_log", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0Om1hbmdyb3ZlX2xvZwQJAG5hbWVfaGFzaHZe6DzPZBobAwoAbmV0d29ya19pZG6DuYkKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:stripped_mangrove_log", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX21hbmdyb3ZlX2xvZwQJAG5hbWVfaGFzaLqIBo4hwA//AwoAbmV0d29ya19pZPtRn7UKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:cherry_log", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmNoZXJyeV9sb2cECQBuYW1lX2hhc2hwFlaioppB1wMKAG5ldHdvcmtfaWS2sdXECgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:stripped_cherry_log", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2NoZXJyeV9sb2cECQBuYW1lX2hhc2i85H6G+WhXaAMKAG5ldHdvcmtfaWRjzoglCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:crimson_stem", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmNyaW1zb25fc3RlbQQJAG5hbWVfaGFzaM0FzfL0UTKZAwoAbmV0d29ya19pZKvzID0KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:stripped_crimson_stem", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2NyaW1zb25fc3RlbQQJAG5hbWVfaGFzaDlA6nood57EAwoAbmV0d29ya19pZHrIqjIKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:warped_stem", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OndhcnBlZF9zdGVtBAkAbmFtZV9oYXNon7cKfPZxdrUDCgBuZXR3b3JrX2lkerWyMwoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:stripped_warped_stem", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX3dhcnBlZF9zdGVtBAkAbmFtZV9oYXNoEw+y0dDPSd8DCgBuZXR3b3JrX2lkIQ9vBAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWSYGFlqCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlAwBvYWsAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWSxnUzvCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlAwBvYWsAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWToyw4RCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlBgBzcHJ1Y2UAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWTL0a3ZCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlBgBzcHJ1Y2UAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWQV99vJCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlBQBiaXJjaAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWQYDJk1CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlBQBiaXJjaAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWSfH48gCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlBgBqdW5nbGUAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWQ44auiCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlBgBqdW5nbGUAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWSogpPYCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlBgBhY2FjaWEAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWSD7hT1CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlBgBhY2FjaWEAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWQagb3gCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlCABkYXJrX29hawADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWQdnWU+CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlCABkYXJrX29hawADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:mangrove_wood", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Om1hbmdyb3ZlX3dvb2QECQBuYW1lX2hhc2iXVxG0JG2fVAMKAG5ldHdvcmtfaWTok1JCCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:stripped_mangrove_wood", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OnN0cmlwcGVkX21hbmdyb3ZlX3dvb2QECQBuYW1lX2hhc2h7CkbaBF7/WAMKAG5ldHdvcmtfaWQLAX88CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:cherry_wood", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNoZXJyeV93b29kBAkAbmFtZV9oYXNoAW8srlmpBM8DCgBuZXR3b3JrX2lkEALMfAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AQwAc3RyaXBwZWRfYml0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:stripped_cherry_wood", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX2NoZXJyeV93b29kBAkAbmFtZV9oYXNo/e7KXv+CB38DCgBuZXR3b3JrX2lkg5aVtQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:crimson_hyphae", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25faHlwaGFlBAkAbmFtZV9oYXNouRmKmfSqEWADCgBuZXR3b3JrX2lk+Tm5rQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:stripped_crimson_hyphae", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnN0cmlwcGVkX2NyaW1zb25faHlwaGFlBAkAbmFtZV9oYXNoFffwmABq4LUDCgBuZXR3b3JrX2lkZAlUbgoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:warped_hyphae", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9oeXBoYWUECQBuYW1lX2hhc2hn8plQUr6pmQMKAG5ldHdvcmtfaWRU2AIBCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:stripped_warped_hyphae", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OnN0cmlwcGVkX3dhcnBlZF9oeXBoYWUECQBuYW1lX2hhc2irKq+HYPSgjQMKAG5ldHdvcmtfaWSbrOPDCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:bamboo_block", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJhbWJvb19ibG9jawQJAG5hbWVfaGFzaAbDeur6stIBAwoAbmV0d29ya19pZCJAwn0KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:stripped_bamboo_block", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2JhbWJvb19ibG9jawQJAG5hbWVfaGFzaJpwytpZOZM9AwoAbmV0d29ya19pZKuRbNEKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:leaves", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmxlYXZlcwQJAG5hbWVfaGFzaACPIsusW0mnAwoAbmV0d29ya19pZOmqtzMKBgBzdGF0ZXMIDQBvbGRfbGVhZl90eXBlAwBvYWsBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:leaves", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmxlYXZlcwQJAG5hbWVfaGFzaACPIsusW0mnAwoAbmV0d29ya19pZFMVNEQKBgBzdGF0ZXMIDQBvbGRfbGVhZl90eXBlBgBzcHJ1Y2UBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:leaves", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmxlYXZlcwQJAG5hbWVfaGFzaACPIsusW0mnAwoAbmV0d29ya19pZKCZEm8KBgBzdGF0ZXMIDQBvbGRfbGVhZl90eXBlBQBiaXJjaAEOAHBlcnNpc3RlbnRfYml0AAEKAHVwZGF0ZV9iaXQAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:leaves", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmxlYXZlcwQJAG5hbWVfaGFzaACPIsusW0mnAwoAbmV0d29ya19pZABprGgKBgBzdGF0ZXMIDQBvbGRfbGVhZl90eXBlBgBqdW5nbGUBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:leaves2", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmxlYXZlczIECQBuYW1lX2hhc2gy/bgrncY1ZAMKAG5ldHdvcmtfaWSFh3olCgYAc3RhdGVzCA0AbmV3X2xlYWZfdHlwZQYAYWNhY2lhAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:leaves2", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmxlYXZlczIECQBuYW1lX2hhc2gy/bgrncY1ZAMKAG5ldHdvcmtfaWTvEAyeCgYAc3RhdGVzCA0AbmV3X2xlYWZfdHlwZQgAZGFya19vYWsBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:mangrove_leaves", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX2xlYXZlcwQJAG5hbWVfaGFzaKyI/dWvhEG8AwoAbmV0d29ya19pZPQxCZ8KBgBzdGF0ZXMBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:cherry_leaves", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9sZWF2ZXMECQBuYW1lX2hhc2giTs9ChhYBlQMKAG5ldHdvcmtfaWR8bPpwCgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:azalea_leaves", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmF6YWxlYV9sZWF2ZXMECQBuYW1lX2hhc2iXFhD57wFS7AMKAG5ldHdvcmtfaWTNB/9ECgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:azalea_leaves_flowered", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmF6YWxlYV9sZWF2ZXNfZmxvd2VyZWQECQBuYW1lX2hhc2gs8jxlS/pMrwMKAG5ldHdvcmtfaWQ7W4PyCgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:sapling", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWQmoOEvCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUDAG9hawADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:sapling", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWQO8pAmCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUGAHNwcnVjZQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:sapling", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWQDHhokCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUFAGJpcmNoAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:sapling", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWTdQrcyCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUGAGp1bmdsZQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:sapling", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWRCDffNCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUGAGFjYWNpYQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:sapling", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWR0BRzPCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUIAGRhcmtfb2FrAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:mangrove_propagule", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0Om1hbmdyb3ZlX3Byb3BhZ3VsZQQJAG5hbWVfaGFzaJGeox6hkfLFAwoAbmV0d29ya19pZAIpvpYKBgBzdGF0ZXMBBwBoYW5naW5nAAMPAHByb3BhZ3VsZV9zdGFnZQAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:cherry_sapling", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNoZXJyeV9zYXBsaW5nBAkAbmFtZV9oYXNoGrPpNMf1LtcDCgBuZXR3b3JrX2lkypakXQoGAHN0YXRlcwEHAGFnZV9iaXQAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:bee_nest", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OmJlZV9uZXN0BAkAbmFtZV9oYXNo2R2WBxUHEZIDCgBuZXR3b3JrX2lkiXWLEAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAADCwBob25leV9sZXZlbAAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:wheat_seeds" - }, - { - "id": "minecraft:pumpkin_seeds" - }, - { - "id": "minecraft:melon_seeds" - }, - { - "id": "minecraft:beetroot_seeds" - }, - { - "id": "minecraft:torchflower_seeds" - }, - { - "id": "minecraft:pitcher_pod" - }, - { - "id": "minecraft:wheat" - }, - { - "id": "minecraft:beetroot" - }, - { - "id": "minecraft:potato" - }, - { - "id": "minecraft:poisonous_potato" - }, - { - "id": "minecraft:carrot" - }, - { - "id": "minecraft:golden_carrot" - }, - { - "id": "minecraft:apple" - }, - { - "id": "minecraft:golden_apple" - }, - { - "id": "minecraft:enchanted_golden_apple" - }, - { - "id": "minecraft:melon_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1lbG9uX2Jsb2NrBAkAbmFtZV9oYXNoXxSm0iYpAx8DCgBuZXR3b3JrX2lkC9rqygoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:melon_slice" - }, - { - "id": "minecraft:glistering_melon_slice" - }, - { - "id": "minecraft:sweet_berries" - }, - { - "id": "minecraft:glow_berries" - }, - { - "id": "minecraft:pumpkin", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnB1bXBraW4ECQBuYW1lX2hhc2gc8A3jaSzWbgMKAG5ldHdvcmtfaWRFGA+xCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:carved_pumpkin", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNhcnZlZF9wdW1wa2luBAkAbmFtZV9oYXNoPu1T0MJuG90DCgBuZXR3b3JrX2lkXNNn5QoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:lit_pumpkin", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmxpdF9wdW1wa2luBAkAbmFtZV9oYXNo7gWtEm2uPL0DCgBuZXR3b3JrX2lki8sU4AoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:honeycomb" - }, - { - "id": "minecraft:tallgrass", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnRhbGxncmFzcwQJAG5hbWVfaGFzaC3PXpAXXYswAwoAbmV0d29ya19pZOh33DMKBgBzdGF0ZXMIDwB0YWxsX2dyYXNzX3R5cGUEAGZlcm4AAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:double_plant", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZMx1sfgKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQQAZmVybgEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:tallgrass", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnRhbGxncmFzcwQJAG5hbWVfaGFzaC3PXpAXXYswAwoAbmV0d29ya19pZErptfIKBgBzdGF0ZXMIDwB0YWxsX2dyYXNzX3R5cGUEAHRhbGwAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:double_plant", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZAbadmIKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQUAZ3Jhc3MBDwB1cHBlcl9ibG9ja19iaXQAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:nether_sprouts" - }, - { - "id": "minecraft:fire_coral", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmZpcmVfY29yYWwECQBuYW1lX2hhc2hOHyyECVQVJwMKAG5ldHdvcmtfaWS9vF0UCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:brain_coral", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmJyYWluX2NvcmFsBAkAbmFtZV9oYXNoRiWlLCwA2ycDCgBuZXR3b3JrX2lkrjAuhgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:bubble_coral", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJ1YmJsZV9jb3JhbAQJAG5hbWVfaGFzaJz6rWnl+v2qAwoAbmV0d29ya19pZImIWy0KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:tube_coral", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnR1YmVfY29yYWwECQBuYW1lX2hhc2iYa8oO/tgk7wMKAG5ldHdvcmtfaWRTfND5CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:horn_coral", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Omhvcm5fY29yYWwECQBuYW1lX2hhc2iZnRHjZbnLPgMKAG5ldHdvcmtfaWR+GGp8CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:dead_fire_coral", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfZmlyZV9jb3JhbAQJAG5hbWVfaGFzaEPU6tFy/latAwoAbmV0d29ya19pZNMa7V4KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:dead_brain_coral", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmRlYWRfYnJhaW5fY29yYWwECQBuYW1lX2hhc2j5L6QJCISvzwMKAG5ldHdvcmtfaWQkKzeiCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:dead_bubble_coral", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmRlYWRfYnViYmxlX2NvcmFsBAkAbmFtZV9oYXNoSTOZ/8wpeNYDCgBuZXR3b3JrX2lka6w9DAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:dead_tube_coral", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfdHViZV9jb3JhbAQJAG5hbWVfaGFzaJGjNWhlaIJeAwoAbmV0d29ya19pZO3Z0ygKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:dead_horn_coral", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfaG9ybl9jb3JhbAQJAG5hbWVfaGFzaJBkz3qt+g2cAwoAbmV0d29ya19pZBAN+eYKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:coral_fan", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZOg7iS4KBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgMAcmVkAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:coral_fan", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZIDj8HMKBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgQAcGluawMTAGNvcmFsX2Zhbl9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:coral_fan", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZLCJP0kKBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgYAcHVycGxlAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:coral_fan", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZFz2ly4KBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgQAYmx1ZQMTAGNvcmFsX2Zhbl9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:coral_fan", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZE4TgnYKBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgYAeWVsbG93AxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:coral_fan_dead", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkdhLQzwoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yAwByZWQDEwBjb3JhbF9mYW5fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:coral_fan_dead", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkSi6srQoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABwaW5rAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:coral_fan_dead", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkGiGSzAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgBwdXJwbGUDEwBjb3JhbF9mYW5fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:coral_fan_dead", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkmvZKOgoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABibHVlAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:coral_fan_dead", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lknLw+4QoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgB5ZWxsb3cDEwBjb3JhbF9mYW5fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:crimson_roots", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNyaW1zb25fcm9vdHMECQBuYW1lX2hhc2j1fWgQLViv5QMKAG5ldHdvcmtfaWRLh5DXCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:warped_roots", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OndhcnBlZF9yb290cwQJAG5hbWVfaGFzaBc3WvbJOLlkAwoAbmV0d29ya19pZNLgDnAKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:yellow_flower", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19mbG93ZXIECQBuYW1lX2hhc2jWbU1pF0OUGAMKAG5ldHdvcmtfaWQgO3hpCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWSqsqQGCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUFAHBvcHB5AAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWTqDajjCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUGAG9yY2hpZAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWT5CjveCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUGAGFsbGl1bQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWTORIBJCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUJAGhvdXN0b25pYQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWTuNhmYCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUJAHR1bGlwX3JlZAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWT0O4nfCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUMAHR1bGlwX29yYW5nZQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWTqkthyCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGULAHR1bGlwX3doaXRlAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWRMbBA7CgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUKAHR1bGlwX3BpbmsAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWRexMAuCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUFAG94ZXllAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWQgs7BECgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUKAGNvcm5mbG93ZXIAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWRvDuNbCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUSAGxpbHlfb2ZfdGhlX3ZhbGxleQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:double_plant", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZOemRt4KBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQkAc3VuZmxvd2VyAQ8AdXBwZXJfYmxvY2tfYml0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:double_plant", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZOFugoEKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQcAc3lyaW5nYQEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:double_plant", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZN4O+/gKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQQAcm9zZQEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:double_plant", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZI3w4GMKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQcAcGFlb25pYQEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:pitcher_plant", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnBpdGNoZXJfcGxhbnQECQBuYW1lX2hhc2hRJHzsbDH+SQMKAG5ldHdvcmtfaWRnY76VCgYAc3RhdGVzAQ8AdXBwZXJfYmxvY2tfYml0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:pink_petals", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfcGV0YWxzBAkAbmFtZV9oYXNo6DQwN9SwV3QDCgBuZXR3b3JrX2lkNWneGgoGAHN0YXRlcwMGAGdyb3d0aAAAAAAIHABtaW5lY3JhZnQ6Y2FyZGluYWxfZGlyZWN0aW9uBQBzb3V0aAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:wither_rose", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OndpdGhlcl9yb3NlBAkAbmFtZV9oYXNoaSKxl3I516gDCgBuZXR3b3JrX2lkATXLPwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:torchflower", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnRvcmNoZmxvd2VyBAkAbmFtZV9oYXNoL+mHtElwbqQDCgBuZXR3b3JrX2lkI34O+AoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:white_dye" - }, - { - "id": "minecraft:light_gray_dye" - }, - { - "id": "minecraft:gray_dye" - }, - { - "id": "minecraft:black_dye" - }, - { - "id": "minecraft:brown_dye" - }, - { - "id": "minecraft:red_dye" - }, - { - "id": "minecraft:orange_dye" - }, - { - "id": "minecraft:yellow_dye" - }, - { - "id": "minecraft:lime_dye" - }, - { - "id": "minecraft:green_dye" - }, - { - "id": "minecraft:cyan_dye" - }, - { - "id": "minecraft:light_blue_dye" - }, - { - "id": "minecraft:blue_dye" - }, - { - "id": "minecraft:purple_dye" - }, - { - "id": "minecraft:magenta_dye" - }, - { - "id": "minecraft:pink_dye" - }, - { - "id": "minecraft:ink_sac" - }, - { - "id": "minecraft:glow_ink_sac" - }, - { - "id": "minecraft:cocoa_beans" - }, - { - "id": "minecraft:lapis_lazuli" - }, - { - "id": "minecraft:bone_meal" - }, - { - "id": "minecraft:vine", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OnZpbmUECQBuYW1lX2hhc2j0Sj8/XeXOLAMKAG5ldHdvcmtfaWSUkDtbCgYAc3RhdGVzAxMAdmluZV9kaXJlY3Rpb25fYml0cwAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:weeping_vines", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndlZXBpbmdfdmluZXMECQBuYW1lX2hhc2jrLgLHkQygiwMKAG5ldHdvcmtfaWQ8NHSJCgYAc3RhdGVzAxEAd2VlcGluZ192aW5lc19hZ2UAAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:twisting_vines", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnR3aXN0aW5nX3ZpbmVzBAkAbmFtZV9oYXNoDYR5QgVUQJADCgBuZXR3b3JrX2lk5kYVIQoGAHN0YXRlcwMSAHR3aXN0aW5nX3ZpbmVzX2FnZQAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:waterlily", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OndhdGVybGlseQQJAG5hbWVfaGFzaEHgC4c1SXg0AwoAbmV0d29ya19pZOOerp8KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:seagrass", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OnNlYWdyYXNzBAkAbmFtZV9oYXNoHSBFtoHdWxIDCgBuZXR3b3JrX2lkd3lhEAoGAHN0YXRlcwgOAHNlYV9ncmFzc190eXBlBwBkZWZhdWx0AAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:kelp" - }, - { - "id": "minecraft:deadbush", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OmRlYWRidXNoBAkAbmFtZV9oYXNoPFODe4IScnYDCgBuZXR3b3JrX2lkVfnl+goGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:bamboo", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmJhbWJvbwQJAG5hbWVfaGFzaBgpGmyzhedCAwoAbmV0d29ya19pZIZv1nYKBgBzdGF0ZXMBBwBhZ2VfYml0AAgQAGJhbWJvb19sZWFmX3NpemUJAG5vX2xlYXZlcwgWAGJhbWJvb19zdGFsa190aGlja25lc3MEAHRoaW4AAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:snow", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OnNub3cECQBuYW1lX2hhc2gVHr5XXdETWAMKAG5ldHdvcmtfaWQ0zCeHCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:ice", - "block_state_b64": "CgAACAQAbmFtZQ0AbWluZWNyYWZ0OmljZQQJAG5hbWVfaGFzaNF26f+uUT29AwoAbmV0d29ya19pZOUMaQYKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:packed_ice", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnBhY2tlZF9pY2UECQBuYW1lX2hhc2hk4bu123ZrFgMKAG5ldHdvcmtfaWTr/ooaCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:blue_ice", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OmJsdWVfaWNlBAkAbmFtZV9oYXNo+EKxYgFhKcgDCgBuZXR3b3JrX2lkxfsA8goGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:snow_layer", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnNub3dfbGF5ZXIECQBuYW1lX2hhc2hXka6atMYUCQMKAG5ldHdvcmtfaWRCrIPcCgYAc3RhdGVzAQsAY292ZXJlZF9iaXQAAwYAaGVpZ2h0AAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:pointed_dripstone", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnBvaW50ZWRfZHJpcHN0b25lBAkAbmFtZV9oYXNoJMISzmHQgt8DCgBuZXR3b3JrX2lkbWrtYgoGAHN0YXRlcwgTAGRyaXBzdG9uZV90aGlja25lc3MDAHRpcAEHAGhhbmdpbmcBAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:dripstone_block", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRyaXBzdG9uZV9ibG9jawQJAG5hbWVfaGFzaIIXnEqY77YsAwoAbmV0d29ya19pZMZi2kwKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:moss_carpet", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vc3NfY2FycGV0BAkAbmFtZV9oYXNo/NEDxRPTshYDCgBuZXR3b3JrX2lkaGG3QwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:moss_block", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Om1vc3NfYmxvY2sECQBuYW1lX2hhc2iovcsPUYX2tgMKAG5ldHdvcmtfaWT3JSbfCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:dirt_with_roots", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRpcnRfd2l0aF9yb290cwQJAG5hbWVfaGFzaLCNDYPviDCIAwoAbmV0d29ya19pZNCkwzoKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:hanging_roots", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Omhhbmdpbmdfcm9vdHMECQBuYW1lX2hhc2jaXn+Y5UZpDAMKAG5ldHdvcmtfaWRU4c2vCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:mangrove_roots", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hbmdyb3ZlX3Jvb3RzBAkAbmFtZV9oYXNoa786PzQGZ6kDCgBuZXR3b3JrX2lklA0AHgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:muddy_mangrove_roots", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0Om11ZGR5X21hbmdyb3ZlX3Jvb3RzBAkAbmFtZV9oYXNo9YApdHpo1RkDCgBuZXR3b3JrX2lkH0Oc4woGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:big_dripleaf", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJpZ19kcmlwbGVhZgQJAG5hbWVfaGFzaGBEhXjo6qSdAwoAbmV0d29ya19pZMETsb8KBgBzdGF0ZXMBEQBiaWdfZHJpcGxlYWZfaGVhZAEIEQBiaWdfZHJpcGxlYWZfdGlsdAQAbm9uZQgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:small_dripleaf_block", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnNtYWxsX2RyaXBsZWFmX2Jsb2NrBAkAbmFtZV9oYXNojxRAgXP9uWADCgBuZXR3b3JrX2lkozbVPwoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24EAGVhc3QBDwB1cHBlcl9ibG9ja19iaXQBAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:spore_blossom", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnNwb3JlX2Jsb3Nzb20ECQBuYW1lX2hhc2il3U72Gbco2gMKAG5ldHdvcmtfaWSbbbgcCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:azalea", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmF6YWxlYQQJAG5hbWVfaGFzaNyUl+BW9JrBAwoAbmV0d29ya19pZO/XZtQKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:flowering_azalea", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmZsb3dlcmluZ19hemFsZWEECQBuYW1lX2hhc2ie9r33wz8kiwMKAG5ldHdvcmtfaWQ3ij0VCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:glow_lichen", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Omdsb3dfbGljaGVuBAkAbmFtZV9oYXNobyPUrIYlo44DCgBuZXR3b3JrX2lkCh8lSAoGAHN0YXRlcwMZAG11bHRpX2ZhY2VfZGlyZWN0aW9uX2JpdHM/AAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:amethyst_block", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmFtZXRoeXN0X2Jsb2NrBAkAbmFtZV9oYXNob+JK1iiAthcDCgBuZXR3b3JrX2lk8HtpzgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:budding_amethyst", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmJ1ZGRpbmdfYW1ldGh5c3QECQBuYW1lX2hhc2gJvAwfI14fxgMKAG5ldHdvcmtfaWTQYqfACgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:amethyst_cluster", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmFtZXRoeXN0X2NsdXN0ZXIECQBuYW1lX2hhc2jK82S88Jgm8wMKAG5ldHdvcmtfaWSCPMPGCgYAc3RhdGVzCBQAbWluZWNyYWZ0OmJsb2NrX2ZhY2UCAHVwAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:large_amethyst_bud", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmxhcmdlX2FtZXRoeXN0X2J1ZAQJAG5hbWVfaGFzaAHhdpWD+sd5AwoAbmV0d29ya19pZKkQxOcKBgBzdGF0ZXMIFABtaW5lY3JhZnQ6YmxvY2tfZmFjZQIAdXAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:medium_amethyst_bud", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0Om1lZGl1bV9hbWV0aHlzdF9idWQECQBuYW1lX2hhc2g5lBGtC0DzZQMKAG5ldHdvcmtfaWSYiP4gCgYAc3RhdGVzCBQAbWluZWNyYWZ0OmJsb2NrX2ZhY2UCAHVwAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:small_amethyst_bud", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnNtYWxsX2FtZXRoeXN0X2J1ZAQJAG5hbWVfaGFzaEnb4+q9PO4YAwoAbmV0d29ya19pZGWzxrQKBgBzdGF0ZXMIFABtaW5lY3JhZnQ6YmxvY2tfZmFjZQIAdXAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:tuff", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OnR1ZmYECQBuYW1lX2hhc2h1Rwc1XYsBGwMKAG5ldHdvcmtfaWRwQGn0CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:calcite", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmNhbGNpdGUECQBuYW1lX2hhc2ixKLu8ZIdzDQMKAG5ldHdvcmtfaWQlSbJDCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:chicken" - }, - { - "id": "minecraft:porkchop" - }, - { - "id": "minecraft:beef" - }, - { - "id": "minecraft:mutton" - }, - { - "id": "minecraft:rabbit" - }, - { - "id": "minecraft:cod" - }, - { - "id": "minecraft:salmon" - }, - { - "id": "minecraft:tropical_fish" - }, - { - "id": "minecraft:pufferfish" - }, - { - "id": "minecraft:brown_mushroom", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmJyb3duX211c2hyb29tBAkAbmFtZV9oYXNonYw/FO78WDoDCgBuZXR3b3JrX2lkLh1OXAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:red_mushroom", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZF9tdXNocm9vbQQJAG5hbWVfaGFzaPpzJua7669xAwoAbmV0d29ya19pZCvWPYkKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:crimson_fungus", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fZnVuZ3VzBAkAbmFtZV9oYXNolIcCUuFM2u0DCgBuZXR3b3JrX2lkD2NN0QoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:warped_fungus", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9mdW5ndXMECQBuYW1lX2hhc2gq8bSnRVTAFgMKAG5ldHdvcmtfaWTkwS+rCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:brown_mushroom_block", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkdOMhDAoGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cw4AAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:red_mushroom_block", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnJlZF9tdXNocm9vbV9ibG9jawQJAG5hbWVfaGFzaJTTyJbth9M9AwoAbmV0d29ya19pZM+AyboKBgBzdGF0ZXMDEgBodWdlX211c2hyb29tX2JpdHMOAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:brown_mushroom_block", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkbdt3CAoGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cw8AAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:brown_mushroom_block", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkSrMl9goGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cwAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:egg" - }, - { - "id": "minecraft:sugar_cane" - }, - { - "id": "minecraft:sugar" - }, - { - "id": "minecraft:rotten_flesh" - }, - { - "id": "minecraft:bone" - }, - { - "id": "minecraft:web", - "block_state_b64": "CgAACAQAbmFtZQ0AbWluZWNyYWZ0OndlYgQJAG5hbWVfaGFzaA4GKQCvG4i9AwoAbmV0d29ya19pZApt+jgKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:spider_eye" - }, - { - "id": "minecraft:mob_spawner", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vYl9zcGF3bmVyBAkAbmFtZV9oYXNoNwGrCV/Fkh8DCgBuZXR3b3JrX2lkM1wTmgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:monster_egg", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkqXH7RgoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGUFAHN0b25lAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:monster_egg", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkeIBb6QoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGULAGNvYmJsZXN0b25lAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:monster_egg", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkDZ2cFQoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGULAHN0b25lX2JyaWNrAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:monster_egg", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkOR/cTAoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGURAG1vc3N5X3N0b25lX2JyaWNrAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:monster_egg", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkqdwlHAoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGUTAGNyYWNrZWRfc3RvbmVfYnJpY2sAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:monster_egg", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkFqqPggoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGUUAGNoaXNlbGVkX3N0b25lX2JyaWNrAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:infested_deepslate", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmluZmVzdGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaICF2VYccxF1AwoAbmV0d29ya19pZDa/624KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:dragon_egg", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmRyYWdvbl9lZ2cECQBuYW1lX2hhc2inMzXrV+/e1wMKAG5ldHdvcmtfaWTgO1yRCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:turtle_egg", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnR1cnRsZV9lZ2cECQBuYW1lX2hhc2iwSRcxOJIJ9gMKAG5ldHdvcmtfaWSIRNUhCgYAc3RhdGVzCA0AY3JhY2tlZF9zdGF0ZQkAbm9fY3JhY2tzCBAAdHVydGxlX2VnZ19jb3VudAcAb25lX2VnZwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:sniffer_egg", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnNuaWZmZXJfZWdnBAkAbmFtZV9oYXNoY1lozc8lPcYDCgBuZXR3b3JrX2lk7yb/2QoGAHN0YXRlcwgNAGNyYWNrZWRfc3RhdGUJAG5vX2NyYWNrcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:frog_spawn", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmZyb2dfc3Bhd24ECQBuYW1lX2hhc2iWmd7idp3ZZwMKAG5ldHdvcmtfaWRFzJudCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:pearlescent_froglight", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnBlYXJsZXNjZW50X2Zyb2dsaWdodAQJAG5hbWVfaGFzaKkcFRyycYGyAwoAbmV0d29ya19pZJqYakAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:verdant_froglight", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnZlcmRhbnRfZnJvZ2xpZ2h0BAkAbmFtZV9oYXNoA+eXuTBohrQDCgBuZXR3b3JrX2lkDIVnsQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:ochre_froglight", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om9jaHJlX2Zyb2dsaWdodAQJAG5hbWVfaGFzaMY59kjPe+c3AwoAbmV0d29ya19pZO2TD50KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:chicken_spawn_egg" - }, - { - "id": "minecraft:bee_spawn_egg" - }, - { - "id": "minecraft:cow_spawn_egg" - }, - { - "id": "minecraft:pig_spawn_egg" - }, - { - "id": "minecraft:sheep_spawn_egg" - }, - { - "id": "minecraft:wolf_spawn_egg" - }, - { - "id": "minecraft:polar_bear_spawn_egg" - }, - { - "id": "minecraft:ocelot_spawn_egg" - }, - { - "id": "minecraft:cat_spawn_egg" - }, - { - "id": "minecraft:mooshroom_spawn_egg" - }, - { - "id": "minecraft:bat_spawn_egg" - }, - { - "id": "minecraft:parrot_spawn_egg" - }, - { - "id": "minecraft:rabbit_spawn_egg" - }, - { - "id": "minecraft:llama_spawn_egg" - }, - { - "id": "minecraft:horse_spawn_egg" - }, - { - "id": "minecraft:donkey_spawn_egg" - }, - { - "id": "minecraft:mule_spawn_egg" - }, - { - "id": "minecraft:skeleton_horse_spawn_egg" - }, - { - "id": "minecraft:zombie_horse_spawn_egg" - }, - { - "id": "minecraft:tropical_fish_spawn_egg" - }, - { - "id": "minecraft:cod_spawn_egg" - }, - { - "id": "minecraft:pufferfish_spawn_egg" - }, - { - "id": "minecraft:salmon_spawn_egg" - }, - { - "id": "minecraft:dolphin_spawn_egg" - }, - { - "id": "minecraft:turtle_spawn_egg" - }, - { - "id": "minecraft:panda_spawn_egg" - }, - { - "id": "minecraft:fox_spawn_egg" - }, - { - "id": "minecraft:creeper_spawn_egg" - }, - { - "id": "minecraft:enderman_spawn_egg" - }, - { - "id": "minecraft:silverfish_spawn_egg" - }, - { - "id": "minecraft:skeleton_spawn_egg" - }, - { - "id": "minecraft:wither_skeleton_spawn_egg" - }, - { - "id": "minecraft:stray_spawn_egg" - }, - { - "id": "minecraft:slime_spawn_egg" - }, - { - "id": "minecraft:spider_spawn_egg" - }, - { - "id": "minecraft:zombie_spawn_egg" - }, - { - "id": "minecraft:zombie_pigman_spawn_egg" - }, - { - "id": "minecraft:husk_spawn_egg" - }, - { - "id": "minecraft:drowned_spawn_egg" - }, - { - "id": "minecraft:squid_spawn_egg" - }, - { - "id": "minecraft:glow_squid_spawn_egg" - }, - { - "id": "minecraft:cave_spider_spawn_egg" - }, - { - "id": "minecraft:witch_spawn_egg" - }, - { - "id": "minecraft:guardian_spawn_egg" - }, - { - "id": "minecraft:elder_guardian_spawn_egg" - }, - { - "id": "minecraft:endermite_spawn_egg" - }, - { - "id": "minecraft:magma_cube_spawn_egg" - }, - { - "id": "minecraft:strider_spawn_egg" - }, - { - "id": "minecraft:hoglin_spawn_egg" - }, - { - "id": "minecraft:piglin_spawn_egg" - }, - { - "id": "minecraft:zoglin_spawn_egg" - }, - { - "id": "minecraft:piglin_brute_spawn_egg" - }, - { - "id": "minecraft:goat_spawn_egg" - }, - { - "id": "minecraft:axolotl_spawn_egg" - }, - { - "id": "minecraft:warden_spawn_egg" - }, - { - "id": "minecraft:allay_spawn_egg" - }, - { - "id": "minecraft:frog_spawn_egg" - }, - { - "id": "minecraft:tadpole_spawn_egg" - }, - { - "id": "minecraft:trader_llama_spawn_egg" - }, - { - "id": "minecraft:camel_spawn_egg" - }, - { - "id": "minecraft:ghast_spawn_egg" - }, - { - "id": "minecraft:blaze_spawn_egg" - }, - { - "id": "minecraft:shulker_spawn_egg" - }, - { - "id": "minecraft:vindicator_spawn_egg" - }, - { - "id": "minecraft:evoker_spawn_egg" - }, - { - "id": "minecraft:vex_spawn_egg" - }, - { - "id": "minecraft:villager_spawn_egg" - }, - { - "id": "minecraft:wandering_trader_spawn_egg" - }, - { - "id": "minecraft:zombie_villager_spawn_egg" - }, - { - "id": "minecraft:phantom_spawn_egg" - }, - { - "id": "minecraft:pillager_spawn_egg" - }, - { - "id": "minecraft:ravager_spawn_egg" - }, - { - "id": "minecraft:iron_golem_spawn_egg" - }, - { - "id": "minecraft:snow_golem_spawn_egg" - }, - { - "id": "minecraft:sniffer_spawn_egg" - }, - { - "id": "minecraft:obsidian", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0Om9ic2lkaWFuBAkAbmFtZV9oYXNoiz4qrb8QjyEDCgBuZXR3b3JrX2lkuqnPpQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:crying_obsidian", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmNyeWluZ19vYnNpZGlhbgQJAG5hbWVfaGFzaKT0JlA7Z1K+AwoAbmV0d29ya19pZCjbPV4KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:bedrock", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmJlZHJvY2sECQBuYW1lX2hhc2hWfFrh4LVtxwMKAG5ldHdvcmtfaWT7fKz1CgYAc3RhdGVzAQ4AaW5maW5pYnVybl9iaXQAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:soul_sand", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnNvdWxfc2FuZAQJAG5hbWVfaGFzaMaf+bccu+KTAwoAbmV0d29ya19pZBQSHrMKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:magma", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0Om1hZ21hBAkAbmFtZV9oYXNoqyTjKaIsWfYDCgBuZXR3b3JrX2lkyfWAZgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:nether_wart" - }, - { - "id": "minecraft:end_stone", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmVuZF9zdG9uZQQJAG5hbWVfaGFzaH1J9jA39GJNAwoAbmV0d29ya19pZFeFQ7UKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:chorus_flower", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNob3J1c19mbG93ZXIECQBuYW1lX2hhc2iMpSodli5uawMKAG5ldHdvcmtfaWRnd1ZWCgYAc3RhdGVzAwMAYWdlAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:chorus_plant", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmNob3J1c19wbGFudAQJAG5hbWVfaGFzaJhSrmNGKwaMAwoAbmV0d29ya19pZA3uVqMKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:chorus_fruit" - }, - { - "id": "minecraft:popped_chorus_fruit" - }, - { - "id": "minecraft:sponge", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnNwb25nZQQJAG5hbWVfaGFzaLrd2ScYRDMiAwoAbmV0d29ya19pZF01rO0KBgBzdGF0ZXMICwBzcG9uZ2VfdHlwZQMAZHJ5AAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:sponge", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnNwb25nZQQJAG5hbWVfaGFzaLrd2ScYRDMiAwoAbmV0d29ya19pZPiOc4QKBgBzdGF0ZXMICwBzcG9uZ2VfdHlwZQMAd2V0AAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:coral_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkGnlaAwoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABibHVlAQgAZGVhZF9iaXQAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:coral_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkSnHuagoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABwaW5rAQgAZGVhZF9iaXQAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:coral_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkmkHyegoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgBwdXJwbGUBCABkZWFkX2JpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:coral_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkdpUDxgoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yAwByZWQBCABkZWFkX2JpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:coral_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkYNWvYgoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgB5ZWxsb3cBCABkZWFkX2JpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:coral_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkZSxBQgoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABibHVlAQgAZGVhZF9iaXQBAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:coral_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lklSTVqQoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABwaW5rAQgAZGVhZF9iaXQBAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:coral_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lk5fTYuQoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgBwdXJwbGUBCABkZWFkX2JpdAEAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:coral_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkwUjqBAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yAwByZWQBCABkZWFkX2JpdAEAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:coral_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkq4iWoQoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgB5ZWxsb3cBCABkZWFkX2JpdAEAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:sculk", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnNjdWxrBAkAbmFtZV9oYXNo2Lq7T5yQF8kDCgBuZXR3b3JrX2lkyqUPPgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:sculk_vein", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnNjdWxrX3ZlaW4ECQBuYW1lX2hhc2gJUdhVooV4zwMKAG5ldHdvcmtfaWSUfn1XCgYAc3RhdGVzAxkAbXVsdGlfZmFjZV9kaXJlY3Rpb25fYml0cwAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:sculk_catalyst", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnNjdWxrX2NhdGFseXN0BAkAbmFtZV9oYXNo+gCpbrCHST4DCgBuZXR3b3JrX2lkMJ2n/woGAHN0YXRlcwEFAGJsb29tAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:sculk_shrieker", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnNjdWxrX3Nocmlla2VyBAkAbmFtZV9oYXNo5OXtyObniQ4DCgBuZXR3b3JrX2lkxapoNAoGAHN0YXRlcwEGAGFjdGl2ZQABCgBjYW5fc3VtbW9uAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:sculk_sensor", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnNjdWxrX3NlbnNvcgQJAG5hbWVfaGFzaCkmHreeTgNnAwoAbmV0d29ya19pZLj2WPcKBgBzdGF0ZXMDEgBzY3Vsa19zZW5zb3JfcGhhc2UAAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:calibrated_sculk_sensor", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmNhbGlicmF0ZWRfc2N1bGtfc2Vuc29yBAkAbmFtZV9oYXNoffAcXXN/iJUDCgBuZXR3b3JrX2lkwOx3QQoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAxIAc2N1bGtfc2Vuc29yX3BoYXNlAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:reinforced_deepslate", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnJlaW5mb3JjZWRfZGVlcHNsYXRlBAkAbmFtZV9oYXNoldDmj91EapQDCgBuZXR3b3JrX2lkHIt+aQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:leather_helmet" - }, - { - "id": "minecraft:chainmail_helmet" - }, - { - "id": "minecraft:iron_helmet" - }, - { - "id": "minecraft:golden_helmet" - }, - { - "id": "minecraft:diamond_helmet" - }, - { - "id": "minecraft:netherite_helmet" - }, - { - "id": "minecraft:leather_chestplate" - }, - { - "id": "minecraft:chainmail_chestplate" - }, - { - "id": "minecraft:iron_chestplate" - }, - { - "id": "minecraft:golden_chestplate" - }, - { - "id": "minecraft:diamond_chestplate" - }, - { - "id": "minecraft:netherite_chestplate" - }, - { - "id": "minecraft:leather_leggings" - }, - { - "id": "minecraft:chainmail_leggings" - }, - { - "id": "minecraft:iron_leggings" - }, - { - "id": "minecraft:golden_leggings" - }, - { - "id": "minecraft:diamond_leggings" - }, - { - "id": "minecraft:netherite_leggings" - }, - { - "id": "minecraft:leather_boots" - }, - { - "id": "minecraft:chainmail_boots" - }, - { - "id": "minecraft:iron_boots" - }, - { - "id": "minecraft:golden_boots" - }, - { - "id": "minecraft:diamond_boots" - }, - { - "id": "minecraft:netherite_boots" - }, - { - "id": "minecraft:wooden_sword" - }, - { - "id": "minecraft:stone_sword" - }, - { - "id": "minecraft:iron_sword" - }, - { - "id": "minecraft:golden_sword" - }, - { - "id": "minecraft:diamond_sword" - }, - { - "id": "minecraft:netherite_sword" - }, - { - "id": "minecraft:wooden_axe" - }, - { - "id": "minecraft:stone_axe" - }, - { - "id": "minecraft:iron_axe" - }, - { - "id": "minecraft:golden_axe" - }, - { - "id": "minecraft:diamond_axe" - }, - { - "id": "minecraft:netherite_axe" - }, - { - "id": "minecraft:wooden_pickaxe" - }, - { - "id": "minecraft:stone_pickaxe" - }, - { - "id": "minecraft:iron_pickaxe" - }, - { - "id": "minecraft:golden_pickaxe" - }, - { - "id": "minecraft:diamond_pickaxe" - }, - { - "id": "minecraft:netherite_pickaxe" - }, - { - "id": "minecraft:wooden_shovel" - }, - { - "id": "minecraft:stone_shovel" - }, - { - "id": "minecraft:iron_shovel" - }, - { - "id": "minecraft:golden_shovel" - }, - { - "id": "minecraft:diamond_shovel" - }, - { - "id": "minecraft:netherite_shovel" - }, - { - "id": "minecraft:wooden_hoe" - }, - { - "id": "minecraft:stone_hoe" - }, - { - "id": "minecraft:iron_hoe" - }, - { - "id": "minecraft:golden_hoe" - }, - { - "id": "minecraft:diamond_hoe" - }, - { - "id": "minecraft:netherite_hoe" - }, - { - "id": "minecraft:bow" - }, - { - "id": "minecraft:crossbow" - }, - { - "id": "minecraft:arrow" - }, - { - "id": "minecraft:arrow", - "damage": 6 - }, - { - "id": "minecraft:arrow", - "damage": 7 - }, - { - "id": "minecraft:arrow", - "damage": 8 - }, - { - "id": "minecraft:arrow", - "damage": 9 - }, - { - "id": "minecraft:arrow", - "damage": 10 - }, - { - "id": "minecraft:arrow", - "damage": 11 - }, - { - "id": "minecraft:arrow", - "damage": 12 - }, - { - "id": "minecraft:arrow", - "damage": 13 - }, - { - "id": "minecraft:arrow", - "damage": 14 - }, - { - "id": "minecraft:arrow", - "damage": 15 - }, - { - "id": "minecraft:arrow", - "damage": 16 - }, - { - "id": "minecraft:arrow", - "damage": 17 - }, - { - "id": "minecraft:arrow", - "damage": 18 - }, - { - "id": "minecraft:arrow", - "damage": 19 - }, - { - "id": "minecraft:arrow", - "damage": 20 - }, - { - "id": "minecraft:arrow", - "damage": 21 - }, - { - "id": "minecraft:arrow", - "damage": 22 - }, - { - "id": "minecraft:arrow", - "damage": 23 - }, - { - "id": "minecraft:arrow", - "damage": 24 - }, - { - "id": "minecraft:arrow", - "damage": 25 - }, - { - "id": "minecraft:arrow", - "damage": 26 - }, - { - "id": "minecraft:arrow", - "damage": 27 - }, - { - "id": "minecraft:arrow", - "damage": 28 - }, - { - "id": "minecraft:arrow", - "damage": 29 - }, - { - "id": "minecraft:arrow", - "damage": 30 - }, - { - "id": "minecraft:arrow", - "damage": 31 - }, - { - "id": "minecraft:arrow", - "damage": 32 - }, - { - "id": "minecraft:arrow", - "damage": 33 - }, - { - "id": "minecraft:arrow", - "damage": 34 - }, - { - "id": "minecraft:arrow", - "damage": 35 - }, - { - "id": "minecraft:arrow", - "damage": 36 - }, - { - "id": "minecraft:arrow", - "damage": 37 - }, - { - "id": "minecraft:arrow", - "damage": 38 - }, - { - "id": "minecraft:arrow", - "damage": 39 - }, - { - "id": "minecraft:arrow", - "damage": 40 - }, - { - "id": "minecraft:arrow", - "damage": 41 - }, - { - "id": "minecraft:arrow", - "damage": 42 - }, - { - "id": "minecraft:arrow", - "damage": 43 - }, - { - "id": "minecraft:shield" - }, - { - "id": "minecraft:cooked_chicken" - }, - { - "id": "minecraft:cooked_porkchop" - }, - { - "id": "minecraft:cooked_beef" - }, - { - "id": "minecraft:cooked_mutton" - }, - { - "id": "minecraft:cooked_rabbit" - }, - { - "id": "minecraft:cooked_cod" - }, - { - "id": "minecraft:cooked_salmon" - }, - { - "id": "minecraft:bread" - }, - { - "id": "minecraft:mushroom_stew" - }, - { - "id": "minecraft:beetroot_soup" - }, - { - "id": "minecraft:rabbit_stew" - }, - { - "id": "minecraft:baked_potato" - }, - { - "id": "minecraft:cookie" - }, - { - "id": "minecraft:pumpkin_pie" - }, - { - "id": "minecraft:cake" - }, - { - "id": "minecraft:dried_kelp" - }, - { - "id": "minecraft:fishing_rod" - }, - { - "id": "minecraft:carrot_on_a_stick" - }, - { - "id": "minecraft:warped_fungus_on_a_stick" - }, - { - "id": "minecraft:snowball" - }, - { - "id": "minecraft:shears" - }, - { - "id": "minecraft:flint_and_steel" - }, - { - "id": "minecraft:lead" - }, - { - "id": "minecraft:clock" - }, - { - "id": "minecraft:compass" - }, - { - "id": "minecraft:recovery_compass" - }, - { - "id": "minecraft:goat_horn" - }, - { - "id": "minecraft:goat_horn", - "damage": 1 - }, - { - "id": "minecraft:goat_horn", - "damage": 2 - }, - { - "id": "minecraft:goat_horn", - "damage": 3 - }, - { - "id": "minecraft:goat_horn", - "damage": 4 - }, - { - "id": "minecraft:goat_horn", - "damage": 5 - }, - { - "id": "minecraft:goat_horn", - "damage": 6 - }, - { - "id": "minecraft:goat_horn", - "damage": 7 - }, - { - "id": "minecraft:empty_map" - }, - { - "id": "minecraft:empty_map", - "damage": 2 - }, - { - "id": "minecraft:saddle" - }, - { - "id": "minecraft:leather_horse_armor" - }, - { - "id": "minecraft:iron_horse_armor" - }, - { - "id": "minecraft:golden_horse_armor" - }, - { - "id": "minecraft:diamond_horse_armor" - }, - { - "id": "minecraft:trident" - }, - { - "id": "minecraft:turtle_helmet" - }, - { - "id": "minecraft:elytra" - }, - { - "id": "minecraft:totem_of_undying" - }, - { - "id": "minecraft:glass_bottle" - }, - { - "id": "minecraft:experience_bottle" - }, - { - "id": "minecraft:potion" - }, - { - "id": "minecraft:potion", - "damage": 1 - }, - { - "id": "minecraft:potion", - "damage": 2 - }, - { - "id": "minecraft:potion", - "damage": 3 - }, - { - "id": "minecraft:potion", - "damage": 4 - }, - { - "id": "minecraft:potion", - "damage": 5 - }, - { - "id": "minecraft:potion", - "damage": 6 - }, - { - "id": "minecraft:potion", - "damage": 7 - }, - { - "id": "minecraft:potion", - "damage": 8 - }, - { - "id": "minecraft:potion", - "damage": 9 - }, - { - "id": "minecraft:potion", - "damage": 10 - }, - { - "id": "minecraft:potion", - "damage": 11 - }, - { - "id": "minecraft:potion", - "damage": 12 - }, - { - "id": "minecraft:potion", - "damage": 13 - }, - { - "id": "minecraft:potion", - "damage": 14 - }, - { - "id": "minecraft:potion", - "damage": 15 - }, - { - "id": "minecraft:potion", - "damage": 16 - }, - { - "id": "minecraft:potion", - "damage": 17 - }, - { - "id": "minecraft:potion", - "damage": 18 - }, - { - "id": "minecraft:potion", - "damage": 19 - }, - { - "id": "minecraft:potion", - "damage": 20 - }, - { - "id": "minecraft:potion", - "damage": 21 - }, - { - "id": "minecraft:potion", - "damage": 22 - }, - { - "id": "minecraft:potion", - "damage": 23 - }, - { - "id": "minecraft:potion", - "damage": 24 - }, - { - "id": "minecraft:potion", - "damage": 25 - }, - { - "id": "minecraft:potion", - "damage": 26 - }, - { - "id": "minecraft:potion", - "damage": 27 - }, - { - "id": "minecraft:potion", - "damage": 28 - }, - { - "id": "minecraft:potion", - "damage": 29 - }, - { - "id": "minecraft:potion", - "damage": 30 - }, - { - "id": "minecraft:potion", - "damage": 31 - }, - { - "id": "minecraft:potion", - "damage": 32 - }, - { - "id": "minecraft:potion", - "damage": 33 - }, - { - "id": "minecraft:potion", - "damage": 34 - }, - { - "id": "minecraft:potion", - "damage": 35 - }, - { - "id": "minecraft:potion", - "damage": 36 - }, - { - "id": "minecraft:potion", - "damage": 37 - }, - { - "id": "minecraft:potion", - "damage": 38 - }, - { - "id": "minecraft:potion", - "damage": 39 - }, - { - "id": "minecraft:potion", - "damage": 40 - }, - { - "id": "minecraft:potion", - "damage": 41 - }, - { - "id": "minecraft:potion", - "damage": 42 - }, - { - "id": "minecraft:splash_potion" - }, - { - "id": "minecraft:splash_potion", - "damage": 1 - }, - { - "id": "minecraft:splash_potion", - "damage": 2 - }, - { - "id": "minecraft:splash_potion", - "damage": 3 - }, - { - "id": "minecraft:splash_potion", - "damage": 4 - }, - { - "id": "minecraft:splash_potion", - "damage": 5 - }, - { - "id": "minecraft:splash_potion", - "damage": 6 - }, - { - "id": "minecraft:splash_potion", - "damage": 7 - }, - { - "id": "minecraft:splash_potion", - "damage": 8 - }, - { - "id": "minecraft:splash_potion", - "damage": 9 - }, - { - "id": "minecraft:splash_potion", - "damage": 10 - }, - { - "id": "minecraft:splash_potion", - "damage": 11 - }, - { - "id": "minecraft:splash_potion", - "damage": 12 - }, - { - "id": "minecraft:splash_potion", - "damage": 13 - }, - { - "id": "minecraft:splash_potion", - "damage": 14 - }, - { - "id": "minecraft:splash_potion", - "damage": 15 - }, - { - "id": "minecraft:splash_potion", - "damage": 16 - }, - { - "id": "minecraft:splash_potion", - "damage": 17 - }, - { - "id": "minecraft:splash_potion", - "damage": 18 - }, - { - "id": "minecraft:splash_potion", - "damage": 19 - }, - { - "id": "minecraft:splash_potion", - "damage": 20 - }, - { - "id": "minecraft:splash_potion", - "damage": 21 - }, - { - "id": "minecraft:splash_potion", - "damage": 22 - }, - { - "id": "minecraft:splash_potion", - "damage": 23 - }, - { - "id": "minecraft:splash_potion", - "damage": 24 - }, - { - "id": "minecraft:splash_potion", - "damage": 25 - }, - { - "id": "minecraft:splash_potion", - "damage": 26 - }, - { - "id": "minecraft:splash_potion", - "damage": 27 - }, - { - "id": "minecraft:splash_potion", - "damage": 28 - }, - { - "id": "minecraft:splash_potion", - "damage": 29 - }, - { - "id": "minecraft:splash_potion", - "damage": 30 - }, - { - "id": "minecraft:splash_potion", - "damage": 31 - }, - { - "id": "minecraft:splash_potion", - "damage": 32 - }, - { - "id": "minecraft:splash_potion", - "damage": 33 - }, - { - "id": "minecraft:splash_potion", - "damage": 34 - }, - { - "id": "minecraft:splash_potion", - "damage": 35 - }, - { - "id": "minecraft:splash_potion", - "damage": 36 - }, - { - "id": "minecraft:splash_potion", - "damage": 37 - }, - { - "id": "minecraft:splash_potion", - "damage": 38 - }, - { - "id": "minecraft:splash_potion", - "damage": 39 - }, - { - "id": "minecraft:splash_potion", - "damage": 40 - }, - { - "id": "minecraft:splash_potion", - "damage": 41 - }, - { - "id": "minecraft:splash_potion", - "damage": 42 - }, - { - "id": "minecraft:lingering_potion" - }, - { - "id": "minecraft:lingering_potion", - "damage": 1 - }, - { - "id": "minecraft:lingering_potion", - "damage": 2 - }, - { - "id": "minecraft:lingering_potion", - "damage": 3 - }, - { - "id": "minecraft:lingering_potion", - "damage": 4 - }, - { - "id": "minecraft:lingering_potion", - "damage": 5 - }, - { - "id": "minecraft:lingering_potion", - "damage": 6 - }, - { - "id": "minecraft:lingering_potion", - "damage": 7 - }, - { - "id": "minecraft:lingering_potion", - "damage": 8 - }, - { - "id": "minecraft:lingering_potion", - "damage": 9 - }, - { - "id": "minecraft:lingering_potion", - "damage": 10 - }, - { - "id": "minecraft:lingering_potion", - "damage": 11 - }, - { - "id": "minecraft:lingering_potion", - "damage": 12 - }, - { - "id": "minecraft:lingering_potion", - "damage": 13 - }, - { - "id": "minecraft:lingering_potion", - "damage": 14 - }, - { - "id": "minecraft:lingering_potion", - "damage": 15 - }, - { - "id": "minecraft:lingering_potion", - "damage": 16 - }, - { - "id": "minecraft:lingering_potion", - "damage": 17 - }, - { - "id": "minecraft:lingering_potion", - "damage": 18 - }, - { - "id": "minecraft:lingering_potion", - "damage": 19 - }, - { - "id": "minecraft:lingering_potion", - "damage": 20 - }, - { - "id": "minecraft:lingering_potion", - "damage": 21 - }, - { - "id": "minecraft:lingering_potion", - "damage": 22 - }, - { - "id": "minecraft:lingering_potion", - "damage": 23 - }, - { - "id": "minecraft:lingering_potion", - "damage": 24 - }, - { - "id": "minecraft:lingering_potion", - "damage": 25 - }, - { - "id": "minecraft:lingering_potion", - "damage": 26 - }, - { - "id": "minecraft:lingering_potion", - "damage": 27 - }, - { - "id": "minecraft:lingering_potion", - "damage": 28 - }, - { - "id": "minecraft:lingering_potion", - "damage": 29 - }, - { - "id": "minecraft:lingering_potion", - "damage": 30 - }, - { - "id": "minecraft:lingering_potion", - "damage": 31 - }, - { - "id": "minecraft:lingering_potion", - "damage": 32 - }, - { - "id": "minecraft:lingering_potion", - "damage": 33 - }, - { - "id": "minecraft:lingering_potion", - "damage": 34 - }, - { - "id": "minecraft:lingering_potion", - "damage": 35 - }, - { - "id": "minecraft:lingering_potion", - "damage": 36 - }, - { - "id": "minecraft:lingering_potion", - "damage": 37 - }, - { - "id": "minecraft:lingering_potion", - "damage": 38 - }, - { - "id": "minecraft:lingering_potion", - "damage": 39 - }, - { - "id": "minecraft:lingering_potion", - "damage": 40 - }, - { - "id": "minecraft:lingering_potion", - "damage": 41 - }, - { - "id": "minecraft:lingering_potion", - "damage": 42 - }, - { - "id": "minecraft:spyglass" - }, - { - "id": "minecraft:brush" - }, - { - "id": "minecraft:stick" - }, - { - "id": "minecraft:bed" - }, - { - "id": "minecraft:bed", - "damage": 8 - }, - { - "id": "minecraft:bed", - "damage": 7 - }, - { - "id": "minecraft:bed", - "damage": 15 - }, - { - "id": "minecraft:bed", - "damage": 12 - }, - { - "id": "minecraft:bed", - "damage": 14 - }, - { - "id": "minecraft:bed", - "damage": 1 - }, - { - "id": "minecraft:bed", - "damage": 4 - }, - { - "id": "minecraft:bed", - "damage": 5 - }, - { - "id": "minecraft:bed", - "damage": 13 - }, - { - "id": "minecraft:bed", - "damage": 9 - }, - { - "id": "minecraft:bed", - "damage": 3 - }, - { - "id": "minecraft:bed", - "damage": 11 - }, - { - "id": "minecraft:bed", - "damage": 10 - }, - { - "id": "minecraft:bed", - "damage": 2 - }, - { - "id": "minecraft:bed", - "damage": 6 - }, - { - "id": "minecraft:torch", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnRvcmNoBAkAbmFtZV9oYXNoagn7rmDBzisDCgBuZXR3b3JrX2lk+BwwuQoGAHN0YXRlcwgWAHRvcmNoX2ZhY2luZ19kaXJlY3Rpb24HAHVua25vd24AAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:soul_torch", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnNvdWxfdG9yY2gECQBuYW1lX2hhc2huixOT04BRdQMKAG5ldHdvcmtfaWShbFILCgYAc3RhdGVzCBYAdG9yY2hfZmFjaW5nX2RpcmVjdGlvbgcAdW5rbm93bgADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:sea_pickle", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnNlYV9waWNrbGUECQBuYW1lX2hhc2iONEfZJB+glgMKAG5ldHdvcmtfaWSINWQyCgYAc3RhdGVzAw0AY2x1c3Rlcl9jb3VudAAAAAABCABkZWFkX2JpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:lantern", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmxhbnRlcm4ECQBuYW1lX2hhc2hMw44VI2HWygMKAG5ldHdvcmtfaWRkjQvzCgYAc3RhdGVzAQcAaGFuZ2luZwAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:soul_lantern", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnNvdWxfbGFudGVybgQJAG5hbWVfaGFzaGjIpjxk9z+RAwoAbmV0d29ya19pZGfoP8cKBgBzdGF0ZXMBBwBoYW5naW5nAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:candle", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmNhbmRsZQQJAG5hbWVfaGFzaHPd+MsNdWTfAwoAbmV0d29ya19pZHsBMA0KBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:white_candle", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OndoaXRlX2NhbmRsZQQJAG5hbWVfaGFzaN1EG5Q1mHiEAwoAbmV0d29ya19pZKN1mmgKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:orange_candle", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Om9yYW5nZV9jYW5kbGUECQBuYW1lX2hhc2jySEVWHgUIHQMKAG5ldHdvcmtfaWSfVz82CgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:magenta_candle", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hZ2VudGFfY2FuZGxlBAkAbmFtZV9oYXNoG0u6YIOoBSEDCgBuZXR3b3JrX2lk9xGNkQoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:light_blue_candle", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY2FuZGxlBAkAbmFtZV9oYXNocXGeK0zgrG0DCgBuZXR3b3JrX2lk2m1y8goGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:yellow_candle", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19jYW5kbGUECQBuYW1lX2hhc2i00dtusU3CqQMKAG5ldHdvcmtfaWR9LTmpCgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:lime_candle", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmxpbWVfY2FuZGxlBAkAbmFtZV9oYXNokcmrw5xvz7ADCgBuZXR3b3JrX2lkIAUu6QoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:pink_candle", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfY2FuZGxlBAkAbmFtZV9oYXNoQJdEY4sZ0dwDCgBuZXR3b3JrX2lk23Rn5AoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:gray_candle", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmdyYXlfY2FuZGxlBAkAbmFtZV9oYXNoS5poSo9wBDEDCgBuZXR3b3JrX2lk3trRCAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:light_gray_candle", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY2FuZGxlBAkAbmFtZV9oYXNo9ruTZLBNMasDCgBuZXR3b3JrX2lkb6DOegoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:cyan_candle", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmN5YW5fY2FuZGxlBAkAbmFtZV9oYXNoc/M8PNVcjOwDCgBuZXR3b3JrX2lkZoIQOQoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:purple_candle", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnBsZV9jYW5kbGUECQBuYW1lX2hhc2jaI3xUW0/myQMKAG5ldHdvcmtfaWSnLI2BCgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:blue_candle", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmJsdWVfY2FuZGxlBAkAbmFtZV9oYXNoAASSPW6TgQADCgBuZXR3b3JrX2lkrxrjQAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:brown_candle", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJyb3duX2NhbmRsZQQJAG5hbWVfaGFzaDia0l6s1+WYAwoAbmV0d29ya19pZKSkBXYKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:green_candle", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmdyZWVuX2NhbmRsZQQJAG5hbWVfaGFzaLeFPO1l+fIoAwoAbmV0d29ya19pZBkznDsKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:red_candle", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9jYW5kbGUECQBuYW1lX2hhc2jjAQpGf59ZdwMKAG5ldHdvcmtfaWRbb88GCgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:black_candle", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJsYWNrX2NhbmRsZQQJAG5hbWVfaGFzaB+wRDpOqREKAwoAbmV0d29ya19pZNnOnuEKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:crafting_table", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyYWZ0aW5nX3RhYmxlBAkAbmFtZV9oYXNoe76VAmjvbpYDCgBuZXR3b3JrX2lkwCxwaAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:cartography_table", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmNhcnRvZ3JhcGh5X3RhYmxlBAkAbmFtZV9oYXNomaWiiD/znP8DCgBuZXR3b3JrX2lkI6FzMwoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:fletching_table", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmZsZXRjaGluZ190YWJsZQQJAG5hbWVfaGFzaPFibh8unKyUAwoAbmV0d29ya19pZJ2mW0oKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:smithing_table", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnNtaXRoaW5nX3RhYmxlBAkAbmFtZV9oYXNo4tFES2xOXEYDCgBuZXR3b3JrX2lkXWMBzQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:beehive", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmJlZWhpdmUECQBuYW1lX2hhc2hCcqn12UbNpwMKAG5ldHdvcmtfaWR/idcaCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAMLAGhvbmV5X2xldmVsAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:suspicious_sand", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnN1c3BpY2lvdXNfc2FuZAQJAG5hbWVfaGFzaL67QsuvLP00AwoAbmV0d29ya19pZKnkaIAKBgBzdGF0ZXMDEABicnVzaGVkX3Byb2dyZXNzAAAAAAEHAGhhbmdpbmcBAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:suspicious_gravel", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN1c3BpY2lvdXNfZ3JhdmVsBAkAbmFtZV9oYXNoJSVbGNk7C3oDCgBuZXR3b3JrX2lkvIEJAAoGAHN0YXRlcwMQAGJydXNoZWRfcHJvZ3Jlc3MAAAAAAQcAaGFuZ2luZwEAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:campfire" - }, - { - "id": "minecraft:soul_campfire" - }, - { - "id": "minecraft:furnace", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmZ1cm5hY2UECQBuYW1lX2hhc2ioOQrludYY8wMKAG5ldHdvcmtfaWRZxnDOCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:blast_furnace", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmJsYXN0X2Z1cm5hY2UECQBuYW1lX2hhc2ivDbnjkpGm5QMKAG5ldHdvcmtfaWTcEbV/CgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:smoker", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnNtb2tlcgQJAG5hbWVfaGFzaJd1rDMkRWomAwoAbmV0d29ya19pZGWswMwKBgBzdGF0ZXMIHABtaW5lY3JhZnQ6Y2FyZGluYWxfZGlyZWN0aW9uBQBzb3V0aAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:respawn_anchor", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnJlc3Bhd25fYW5jaG9yBAkAbmFtZV9oYXNoZOdcjW05qigDCgBuZXR3b3JrX2lkmhMcaQoGAHN0YXRlcwMVAHJlc3Bhd25fYW5jaG9yX2NoYXJnZQAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:brewing_stand" - }, - { - "id": "minecraft:anvil", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmFudmlsBAkAbmFtZV9oYXNoNqB3fgcUCbwDCgBuZXR3b3JrX2lk8Z3VowoGAHN0YXRlcwgGAGRhbWFnZQkAdW5kYW1hZ2VkCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:anvil", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmFudmlsBAkAbmFtZV9oYXNoNqB3fgcUCbwDCgBuZXR3b3JrX2lkpiv8BAoGAHN0YXRlcwgGAGRhbWFnZRAAc2xpZ2h0bHlfZGFtYWdlZAgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:anvil", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmFudmlsBAkAbmFtZV9oYXNoNqB3fgcUCbwDCgBuZXR3b3JrX2lkFu+pdwoGAHN0YXRlcwgGAGRhbWFnZQwAdmVyeV9kYW1hZ2VkCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:grindstone", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmdyaW5kc3RvbmUECQBuYW1lX2hhc2id56zc0nk99wMKAG5ldHdvcmtfaWS4Es07CgYAc3RhdGVzCAoAYXR0YWNobWVudAgAc3RhbmRpbmcDCQBkaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:enchanting_table", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmVuY2hhbnRpbmdfdGFibGUECQBuYW1lX2hhc2jgIx24VLvMvwMKAG5ldHdvcmtfaWRliFFJCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:bookshelf", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmJvb2tzaGVsZgQJAG5hbWVfaGFzaDU04DrgJCS9AwoAbmV0d29ya19pZBcWwIwKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:chiseled_bookshelf", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmNoaXNlbGVkX2Jvb2tzaGVsZgQJAG5hbWVfaGFzaNXDBnsIsywYAwoAbmV0d29ya19pZIprt5IKBgBzdGF0ZXMDDABib29rc19zdG9yZWQAAAAAAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:lectern", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmxlY3Rlcm4ECQBuYW1lX2hhc2j5Z4Mmi/1QxAMKAG5ldHdvcmtfaWR4JfDHCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgBCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:cauldron" - }, - { - "id": "minecraft:composter", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmNvbXBvc3RlcgQJAG5hbWVfaGFzaPAADHptzeWJAwoAbmV0d29ya19pZHIL6i4KBgBzdGF0ZXMDFABjb21wb3N0ZXJfZmlsbF9sZXZlbAAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:chest", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmNoZXN0BAkAbmFtZV9oYXNog9ozMxlcA88DCgBuZXR3b3JrX2lkcrctxAoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:trapped_chest", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnRyYXBwZWRfY2hlc3QECQBuYW1lX2hhc2g2qpF9stsEjgMKAG5ldHdvcmtfaWSdRfncCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:ender_chest", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmVuZGVyX2NoZXN0BAkAbmFtZV9oYXNohEZzOFdg0WUDCgBuZXR3b3JrX2lkOc75awoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:barrel", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmJhcnJlbAQJAG5hbWVfaGFzaHDkRPGymiRqAwoAbmV0d29ya19pZPnxzgsKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:undyed_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnVuZHllZF9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaOC9mypm/MlBAwoAbmV0d29ya19pZJ8rxp0KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:white_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OndoaXRlX3NodWxrZXJfYm94BAkAbmFtZV9oYXNosK79m1rPUBwDCgBuZXR3b3JrX2lkjrET6goGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:light_gray_shulker_box", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2iBe5zq7PxHmgMKAG5ldHdvcmtfaWSCVJv0CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:gray_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmdyYXlfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2ga2s8ctjHUhgMKAG5ldHdvcmtfaWS3WMsWCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:black_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmJsYWNrX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoPm03OZphrp8DCgBuZXR3b3JrX2lkXHztNAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:brown_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmJyb3duX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoT3DD6qAL9cADCgBuZXR3b3JrX2lkaXxpYQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:red_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnJlZF9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaMIlKSCzqSZoAwoAbmV0d29ya19pZNrf+icKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:orange_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0Om9yYW5nZV9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaG2MAXU67wGrAwoAbmV0d29ya19pZGoO05gKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:yellow_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnllbGxvd19zaHVsa2VyX2JveAQJAG5hbWVfaGFzaIsLwQHYjcIEAwoAbmV0d29ya19pZBCBSiYKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:lime_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmxpbWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2hUwBkg+faUGAMKAG5ldHdvcmtfaWRJeKqqCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:green_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmdyZWVuX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoZgUeT3LupLUDCgBuZXR3b3JrX2lkzJiohQoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:cyan_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmN5YW5fc2h1bGtlcl9ib3gECQBuYW1lX2hhc2gSfbjteXg5yAMKAG5ldHdvcmtfaWTHeliECgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:light_blue_shulker_box", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2h0VFCX0qsRxQMKAG5ldHdvcmtfaWQXD8U0CgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:blue_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmJsdWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2hn9gS0XIe6rAMKAG5ldHdvcmtfaWTO4PJaCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:purple_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnB1cnBsZV9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaEV/lkNPxRDdAwoAbmV0d29ya19pZFK25GAKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:magenta_shulker_box", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0Om1hZ2VudGFfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2iqWM7IJHxcFgMKAG5ldHdvcmtfaWTyyudTCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:pink_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnBpbmtfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2in1tkJ1GNcZgMKAG5ldHdvcmtfaWQOEGXjCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:armor_stand" - }, - { - "id": "minecraft:noteblock", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0Om5vdGVibG9jawQJAG5hbWVfaGFzaHPA8dBBH0UaAwoAbmV0d29ya19pZH1U5QkKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:jukebox", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0Omp1a2Vib3gECQBuYW1lX2hhc2ieAIPExf/ZfgMKAG5ldHdvcmtfaWSmR7JfCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:music_disc_13" - }, - { - "id": "minecraft:music_disc_cat" - }, - { - "id": "minecraft:music_disc_blocks" - }, - { - "id": "minecraft:music_disc_chirp" - }, - { - "id": "minecraft:music_disc_far" - }, - { - "id": "minecraft:music_disc_mall" - }, - { - "id": "minecraft:music_disc_mellohi" - }, - { - "id": "minecraft:music_disc_stal" - }, - { - "id": "minecraft:music_disc_strad" - }, - { - "id": "minecraft:music_disc_ward" - }, - { - "id": "minecraft:music_disc_11" - }, - { - "id": "minecraft:music_disc_wait" - }, - { - "id": "minecraft:music_disc_otherside" - }, - { - "id": "minecraft:music_disc_5" - }, - { - "id": "minecraft:music_disc_pigstep" - }, - { - "id": "minecraft:music_disc_relic" - }, - { - "id": "minecraft:disc_fragment_5" - }, - { - "id": "minecraft:glowstone_dust" - }, - { - "id": "minecraft:glowstone", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0Omdsb3dzdG9uZQQJAG5hbWVfaGFzaFYqXNkefIlPAwoAbmV0d29ya19pZGT7WYYKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:redstone_lamp", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZHN0b25lX2xhbXAECQBuYW1lX2hhc2hJ9V80caPvEgMKAG5ldHdvcmtfaWRvNPwnCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:sea_lantern", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnNlYV9sYW50ZXJuBAkAbmFtZV9oYXNoLPsv1TX9M+QDCgBuZXR3b3JrX2lk1PPVyAoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:oak_sign" - }, - { - "id": "minecraft:spruce_sign" - }, - { - "id": "minecraft:birch_sign" - }, - { - "id": "minecraft:jungle_sign" - }, - { - "id": "minecraft:acacia_sign" - }, - { - "id": "minecraft:dark_oak_sign" - }, - { - "id": "minecraft:mangrove_sign" - }, - { - "id": "minecraft:cherry_sign" - }, - { - "id": "minecraft:bamboo_sign" - }, - { - "id": "minecraft:crimson_sign" - }, - { - "id": "minecraft:warped_sign" - }, - { - "id": "minecraft:oak_hanging_sign" - }, - { - "id": "minecraft:spruce_hanging_sign" - }, - { - "id": "minecraft:birch_hanging_sign" - }, - { - "id": "minecraft:jungle_hanging_sign" - }, - { - "id": "minecraft:acacia_hanging_sign" - }, - { - "id": "minecraft:dark_oak_hanging_sign" - }, - { - "id": "minecraft:mangrove_hanging_sign" - }, - { - "id": "minecraft:cherry_hanging_sign" - }, - { - "id": "minecraft:bamboo_hanging_sign" - }, - { - "id": "minecraft:crimson_hanging_sign" - }, - { - "id": "minecraft:warped_hanging_sign" - }, - { - "id": "minecraft:painting" - }, - { - "id": "minecraft:frame" - }, - { - "id": "minecraft:glow_frame" - }, - { - "id": "minecraft:honey_bottle" - }, - { - "id": "minecraft:flower_pot" - }, - { - "id": "minecraft:bowl" - }, - { - "id": "minecraft:bucket" - }, - { - "id": "minecraft:milk_bucket" - }, - { - "id": "minecraft:water_bucket" - }, - { - "id": "minecraft:lava_bucket" - }, - { - "id": "minecraft:cod_bucket" - }, - { - "id": "minecraft:salmon_bucket" - }, - { - "id": "minecraft:tropical_fish_bucket" - }, - { - "id": "minecraft:pufferfish_bucket" - }, - { - "id": "minecraft:powder_snow_bucket" - }, - { - "id": "minecraft:axolotl_bucket" - }, - { - "id": "minecraft:tadpole_bucket" - }, - { - "id": "minecraft:skull", - "damage": 3 - }, - { - "id": "minecraft:skull", - "damage": 2 - }, - { - "id": "minecraft:skull", - "damage": 4 - }, - { - "id": "minecraft:skull", - "damage": 5 - }, - { - "id": "minecraft:skull" - }, - { - "id": "minecraft:skull", - "damage": 1 - }, - { - "id": "minecraft:skull", - "damage": 6 - }, - { - "id": "minecraft:beacon", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmJlYWNvbgQJAG5hbWVfaGFzaACwhhfSkdkHAwoAbmV0d29ya19pZF8jfiEKBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:bell", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OmJlbGwECQBuYW1lX2hhc2iPqsgDXRcsxAMKAG5ldHdvcmtfaWT7zhOoCgYAc3RhdGVzCAoAYXR0YWNobWVudAgAc3RhbmRpbmcDCQBkaXJlY3Rpb24AAAAAAQoAdG9nZ2xlX2JpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:conduit", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmNvbmR1aXQECQBuYW1lX2hhc2jqxKAxq2EaWQMKAG5ldHdvcmtfaWTWcBVnCgYAc3RhdGVzAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:stonecutter_block", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lY3V0dGVyX2Jsb2NrBAkAbmFtZV9oYXNoQAXTbAM3MeYDCgBuZXR3b3JrX2lk18KHygoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:end_portal_frame", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmVuZF9wb3J0YWxfZnJhbWUECQBuYW1lX2hhc2gqofyUIjGOpQMKAG5ldHdvcmtfaWRbGHf8CgYAc3RhdGVzARIAZW5kX3BvcnRhbF9leWVfYml0AAgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:coal" - }, - { - "id": "minecraft:charcoal" - }, - { - "id": "minecraft:diamond" - }, - { - "id": "minecraft:iron_nugget" - }, - { - "id": "minecraft:raw_iron" - }, - { - "id": "minecraft:raw_gold" - }, - { - "id": "minecraft:raw_copper" - }, - { - "id": "minecraft:copper_ingot" - }, - { - "id": "minecraft:iron_ingot" - }, - { - "id": "minecraft:netherite_scrap" - }, - { - "id": "minecraft:netherite_ingot" - }, - { - "id": "minecraft:gold_nugget" - }, - { - "id": "minecraft:gold_ingot" - }, - { - "id": "minecraft:emerald" - }, - { - "id": "minecraft:quartz" - }, - { - "id": "minecraft:clay_ball" - }, - { - "id": "minecraft:brick" - }, - { - "id": "minecraft:netherbrick" - }, - { - "id": "minecraft:prismarine_shard" - }, - { - "id": "minecraft:amethyst_shard" - }, - { - "id": "minecraft:prismarine_crystals" - }, - { - "id": "minecraft:nautilus_shell" - }, - { - "id": "minecraft:heart_of_the_sea" - }, - { - "id": "minecraft:scute" - }, - { - "id": "minecraft:phantom_membrane" - }, - { - "id": "minecraft:string" - }, - { - "id": "minecraft:feather" - }, - { - "id": "minecraft:flint" - }, - { - "id": "minecraft:gunpowder" - }, - { - "id": "minecraft:leather" - }, - { - "id": "minecraft:rabbit_hide" - }, - { - "id": "minecraft:rabbit_foot" - }, - { - "id": "minecraft:fire_charge" - }, - { - "id": "minecraft:blaze_rod" - }, - { - "id": "minecraft:blaze_powder" - }, - { - "id": "minecraft:magma_cream" - }, - { - "id": "minecraft:fermented_spider_eye" - }, - { - "id": "minecraft:echo_shard" - }, - { - "id": "minecraft:dragon_breath" - }, - { - "id": "minecraft:shulker_shell" - }, - { - "id": "minecraft:ghast_tear" - }, - { - "id": "minecraft:slime_ball" - }, - { - "id": "minecraft:ender_pearl" - }, - { - "id": "minecraft:ender_eye" - }, - { - "id": "minecraft:nether_star" - }, - { - "id": "minecraft:end_rod", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmVuZF9yb2QECQBuYW1lX2hhc2jx/q5cEA0hmQMKAG5ldHdvcmtfaWQ2eM8kCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:lightning_rod", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmxpZ2h0bmluZ19yb2QECQBuYW1lX2hhc2ioXQF1xvfHNQMKAG5ldHdvcmtfaWRLuHyACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:end_crystal" - }, - { - "id": "minecraft:paper" - }, - { - "id": "minecraft:book" - }, - { - "id": "minecraft:writable_book" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQFAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQFAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQFAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQGAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQGAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQGAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQHAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQHAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQHAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQIAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAUAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAUAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAUAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQMAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQMAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQNAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQNAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQOAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQOAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQOAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAUAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQQAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQRAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQRAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQRAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQSAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQSAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQSAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAUAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQUAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQUAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQVAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQWAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQXAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQXAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQXAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQYAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQYAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQYAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQZAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQZAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQaAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQbAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQcAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAUAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQeAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQeAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQeAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQfAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQfAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQfAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQgAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQhAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQjAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQjAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQjAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQkAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQkAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQkAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQlAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQlAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQlAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:oak_boat" - }, - { - "id": "minecraft:spruce_boat" - }, - { - "id": "minecraft:birch_boat" - }, - { - "id": "minecraft:jungle_boat" - }, - { - "id": "minecraft:acacia_boat" - }, - { - "id": "minecraft:dark_oak_boat" - }, - { - "id": "minecraft:mangrove_boat" - }, - { - "id": "minecraft:cherry_boat" - }, - { - "id": "minecraft:bamboo_raft" - }, - { - "id": "minecraft:oak_chest_boat" - }, - { - "id": "minecraft:spruce_chest_boat" - }, - { - "id": "minecraft:birch_chest_boat" - }, - { - "id": "minecraft:jungle_chest_boat" - }, - { - "id": "minecraft:acacia_chest_boat" - }, - { - "id": "minecraft:dark_oak_chest_boat" - }, - { - "id": "minecraft:mangrove_chest_boat" - }, - { - "id": "minecraft:cherry_chest_boat" - }, - { - "id": "minecraft:bamboo_chest_raft" - }, - { - "id": "minecraft:rail", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OnJhaWwECQBuYW1lX2hhc2hUzmhUXYJDUQMKAG5ldHdvcmtfaWR+Sp6YCgYAc3RhdGVzAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:golden_rail", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmdvbGRlbl9yYWlsBAkAbmFtZV9oYXNoOoV5MaKipoUDCgBuZXR3b3JrX2lkfAcxLwoGAHN0YXRlcwENAHJhaWxfZGF0YV9iaXQAAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:detector_rail", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmRldGVjdG9yX3JhaWwECQBuYW1lX2hhc2gVUk31qOysUQMKAG5ldHdvcmtfaWRVW/aICgYAc3RhdGVzAQ0AcmFpbF9kYXRhX2JpdAADDgByYWlsX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:activator_rail", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmFjdGl2YXRvcl9yYWlsBAkAbmFtZV9oYXNosIL91qriCRkDCgBuZXR3b3JrX2lkZfckmwoGAHN0YXRlcwENAHJhaWxfZGF0YV9iaXQAAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:minecart" - }, - { - "id": "minecraft:chest_minecart" - }, - { - "id": "minecraft:hopper_minecart" - }, - { - "id": "minecraft:tnt_minecart" - }, - { - "id": "minecraft:redstone" - }, - { - "id": "minecraft:redstone_block", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZHN0b25lX2Jsb2NrBAkAbmFtZV9oYXNoRhULL0r8o0sDCgBuZXR3b3JrX2lklayOHgoGAHN0YXRlcwADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:redstone_torch", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZHN0b25lX3RvcmNoBAkAbmFtZV9oYXNoizFRjpYMIDgDCgBuZXR3b3JrX2lkuHz7yAoGAHN0YXRlcwgWAHRvcmNoX2ZhY2luZ19kaXJlY3Rpb24HAHVua25vd24AAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:lever", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmxldmVyBAkAbmFtZV9oYXNoGMJeLJsUMLYDCgBuZXR3b3JrX2lkEF/GuAoGAHN0YXRlcwgPAGxldmVyX2RpcmVjdGlvbg4AZG93bl9lYXN0X3dlc3QBCABvcGVuX2JpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:wooden_button", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Ondvb2Rlbl9idXR0b24ECQBuYW1lX2hhc2hR7PgSTQt0sQMKAG5ldHdvcmtfaWSU07kYCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:spruce_button", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9idXR0b24ECQBuYW1lX2hhc2jBW9Z8aYE7YQMKAG5ldHdvcmtfaWTkUIGuCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:birch_button", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX2J1dHRvbgQJAG5hbWVfaGFzaJXYgGuSHbTwAwoAbmV0d29ya19pZGWp3yoKBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:jungle_button", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9idXR0b24ECQBuYW1lX2hhc2iCgNANcJs+BQMKAG5ldHdvcmtfaWT9fImWCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:acacia_button", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9idXR0b24ECQBuYW1lX2hhc2gVvmcT7LTO0wMKAG5ldHdvcmtfaWRQnxIJCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:dark_oak_button", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX2J1dHRvbgQJAG5hbWVfaGFzaIV10ZGGrCIEAwoAbmV0d29ya19pZN5vAmIKBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:mangrove_button", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX2J1dHRvbgQJAG5hbWVfaGFzaNzeYYKLgOzJAwoAbmV0d29ya19pZAFEGQ0KBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:cherry_button", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9idXR0b24ECQBuYW1lX2hhc2j2/IHjeAbUcwMKAG5ldHdvcmtfaWRJ1irQCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:bamboo_button", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19idXR0b24ECQBuYW1lX2hhc2j7AddMi+6nsgMKAG5ldHdvcmtfaWSa9w4/CgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:stone_button", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnN0b25lX2J1dHRvbgQJAG5hbWVfaGFzaM4ejMctmvohAwoAbmV0d29ya19pZMw+aC0KBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:crimson_button", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fYnV0dG9uBAkAbmFtZV9oYXNofnjYHaYIeWgDCgBuZXR3b3JrX2lk+n1vyQoGAHN0YXRlcwESAGJ1dHRvbl9wcmVzc2VkX2JpdAADEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:warped_button", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9idXR0b24ECQBuYW1lX2hhc2jwkV2EU6Cn1QMKAG5ldHdvcmtfaWTnHnk1CgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:polished_blackstone_button", - "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnV0dG9uBAkAbmFtZV9oYXNojmxzQKS0S/EDCgBuZXR3b3JrX2lkDtQ95woGAHN0YXRlcwESAGJ1dHRvbl9wcmVzc2VkX2JpdAADEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:tripwire_hook", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnRyaXB3aXJlX2hvb2sECQBuYW1lX2hhc2gQdp+oGZLNnAMKAG5ldHdvcmtfaWSy+1KJCgYAc3RhdGVzAQwAYXR0YWNoZWRfYml0AAMJAGRpcmVjdGlvbgAAAAABCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:wooden_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0Ondvb2Rlbl9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaGkGs5kCuA74AwoAbmV0d29ya19pZDRzPNwKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:spruce_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnNwcnVjZV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaNmwuq549fJKAwoAbmV0d29ya19pZLQMCw0KBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:birch_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmJpcmNoX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNorQkT9kDdlTwDCgBuZXR3b3JrX2lkH0G97AoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:jungle_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0Omp1bmdsZV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaJ7DcteCkb8/AwoAbmV0d29ya19pZLdPBSAKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:acacia_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmFjYWNpYV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaC2frZtfoYqCAwoAbmV0d29ya19pZIDdI18KBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:dark_oak_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmRhcmtfb2FrX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoHUCJsTy52pwDCgBuZXR3b3JrX2lkKpi8rAoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:mangrove_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0Om1hbmdyb3ZlX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoiDsTfJaX100DCgBuZXR3b3JrX2lkuwWDyQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:cherry_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmNoZXJyeV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaALMqYEZDUQHAwoAbmV0d29ya19pZPNT+r0KBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:bamboo_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmJhbWJvb19wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaNvxJ7NIAaqlAwoAbmV0d29ya19pZIZ8XnYKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:crimson_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmNyaW1zb25fcHJlc3N1cmVfcGxhdGUECQBuYW1lX2hhc2hqBDVDAd31/gMKAG5ldHdvcmtfaWRmV18LCgYAc3RhdGVzAw8AcmVkc3RvbmVfc2lnbmFsAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:warped_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OndhcnBlZF9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaBxFoQksWtYUAwoAbmV0d29ya19pZJVRoIcKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:stone_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnN0b25lX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNounJuTBUTrU8DCgBuZXR3b3JrX2lkjDydwQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:light_weighted_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X3dlaWdodGVkX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoOyOJkNxLtkEDCgBuZXR3b3JrX2lkrr2AjgoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:heavy_weighted_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZScAbWluZWNyYWZ0OmhlYXZ5X3dlaWdodGVkX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoltgDmDvTajUDCgBuZXR3b3JrX2lkFxVKuQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:polished_blackstone_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZSwAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfcHJlc3N1cmVfcGxhdGUECQBuYW1lX2hhc2h65Ci6/CeGqwMKAG5ldHdvcmtfaWTaSW5xCgYAc3RhdGVzAw8AcmVkc3RvbmVfc2lnbmFsAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:observer", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0Om9ic2VydmVyBAkAbmFtZV9oYXNoYhlh1lpmHTgDCgBuZXR3b3JrX2lkQEh55goGAHN0YXRlcwgaAG1pbmVjcmFmdDpmYWNpbmdfZGlyZWN0aW9uBABkb3duAQsAcG93ZXJlZF9iaXQAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:daylight_detector", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmRheWxpZ2h0X2RldGVjdG9yBAkAbmFtZV9oYXNoV0F0s7B7PVgDCgBuZXR3b3JrX2lkri5afQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:repeater" - }, - { - "id": "minecraft:comparator" - }, - { - "id": "minecraft:hopper" - }, - { - "id": "minecraft:dropper", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmRyb3BwZXIECQBuYW1lX2hhc2joXP7XqU0l3QMKAG5ldHdvcmtfaWQfQN6zCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgMAAAABDQB0cmlnZ2VyZWRfYml0AAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:dispenser", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmRpc3BlbnNlcgQJAG5hbWVfaGFzaP1RR+zAbYP2AwoAbmV0d29ya19pZGAayD0KBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAwAAAAENAHRyaWdnZXJlZF9iaXQAAAMHAHZlcnNpb24yHhQBAA==" - }, - { - "id": "minecraft:piston", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBpc3RvbgQJAG5hbWVfaGFzaDs3AFh1fL0uAwoAbmV0d29ya19pZLD/5XQKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAQAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:sticky_piston", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnN0aWNreV9waXN0b24ECQBuYW1lX2hhc2hPFJFJSiJ0ZQMKAG5ldHdvcmtfaWT/MzCJCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgEAAAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:tnt", - "block_state_b64": "CgAACAQAbmFtZQ0AbWluZWNyYWZ0OnRudAQJAG5hbWVfaGFzaEYOHwCvJH29AwoAbmV0d29ya19pZCGfjU4KBgBzdGF0ZXMBFABhbGxvd191bmRlcndhdGVyX2JpdAABCwBleHBsb2RlX2JpdAAAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:name_tag" - }, - { - "id": "minecraft:loom", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Omxvb20ECQBuYW1lX2hhc2i7DKjAXNq8TAMKAG5ldHdvcmtfaWR/49HXCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:banner" - }, - { - "id": "minecraft:banner", - "damage": 8 - }, - { - "id": "minecraft:banner", - "damage": 7 - }, - { - "id": "minecraft:banner", - "damage": 15 - }, - { - "id": "minecraft:banner", - "damage": 12 - }, - { - "id": "minecraft:banner", - "damage": 14 - }, - { - "id": "minecraft:banner", - "damage": 1 - }, - { - "id": "minecraft:banner", - "damage": 4 - }, - { - "id": "minecraft:banner", - "damage": 5 - }, - { - "id": "minecraft:banner", - "damage": 13 - }, - { - "id": "minecraft:banner", - "damage": 9 - }, - { - "id": "minecraft:banner", - "damage": 3 - }, - { - "id": "minecraft:banner", - "damage": 11 - }, - { - "id": "minecraft:banner", - "damage": 10 - }, - { - "id": "minecraft:banner", - "damage": 2 - }, - { - "id": "minecraft:banner", - "damage": 6 - }, - { - "id": "minecraft:banner", - "damage": 15, - "nbt_b64": "CgAAAwQAVHlwZQEAAAAA" - }, - { - "id": "minecraft:creeper_banner_pattern" - }, - { - "id": "minecraft:skull_banner_pattern" - }, - { - "id": "minecraft:flower_banner_pattern" - }, - { - "id": "minecraft:mojang_banner_pattern" - }, - { - "id": "minecraft:field_masoned_banner_pattern" - }, - { - "id": "minecraft:bordure_indented_banner_pattern" - }, - { - "id": "minecraft:piglin_banner_pattern" - }, - { - "id": "minecraft:globe_banner_pattern" - }, - { - "id": "minecraft:angler_pottery_sherd" - }, - { - "id": "minecraft:archer_pottery_sherd" - }, - { - "id": "minecraft:arms_up_pottery_sherd" - }, - { - "id": "minecraft:blade_pottery_sherd" - }, - { - "id": "minecraft:brewer_pottery_sherd" - }, - { - "id": "minecraft:burn_pottery_sherd" - }, - { - "id": "minecraft:danger_pottery_sherd" - }, - { - "id": "minecraft:explorer_pottery_sherd" - }, - { - "id": "minecraft:friend_pottery_sherd" - }, - { - "id": "minecraft:heart_pottery_sherd" - }, - { - "id": "minecraft:heartbreak_pottery_sherd" - }, - { - "id": "minecraft:howl_pottery_sherd" - }, - { - "id": "minecraft:miner_pottery_sherd" - }, - { - "id": "minecraft:mourner_pottery_sherd" - }, - { - "id": "minecraft:plenty_pottery_sherd" - }, - { - "id": "minecraft:prize_pottery_sherd" - }, - { - "id": "minecraft:sheaf_pottery_sherd" - }, - { - "id": "minecraft:shelter_pottery_sherd" - }, - { - "id": "minecraft:skull_pottery_sherd" - }, - { - "id": "minecraft:snort_pottery_sherd" - }, - { - "id": "minecraft:netherite_upgrade_smithing_template" - }, - { - "id": "minecraft:sentry_armor_trim_smithing_template" - }, - { - "id": "minecraft:vex_armor_trim_smithing_template" - }, - { - "id": "minecraft:wild_armor_trim_smithing_template" - }, - { - "id": "minecraft:coast_armor_trim_smithing_template" - }, - { - "id": "minecraft:dune_armor_trim_smithing_template" - }, - { - "id": "minecraft:wayfinder_armor_trim_smithing_template" - }, - { - "id": "minecraft:shaper_armor_trim_smithing_template" - }, - { - "id": "minecraft:raiser_armor_trim_smithing_template" - }, - { - "id": "minecraft:host_armor_trim_smithing_template" - }, - { - "id": "minecraft:ward_armor_trim_smithing_template" - }, - { - "id": "minecraft:silence_armor_trim_smithing_template" - }, - { - "id": "minecraft:tide_armor_trim_smithing_template" - }, - { - "id": "minecraft:snout_armor_trim_smithing_template" - }, - { - "id": "minecraft:rib_armor_trim_smithing_template" - }, - { - "id": "minecraft:eye_armor_trim_smithing_template" - }, - { - "id": "minecraft:spire_armor_trim_smithing_template" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwAAAAAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAABwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAIBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAHBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAPBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAMBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAOBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAABBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAEBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAFBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAANBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAJBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAADBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAALBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAKBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAACBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAGBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_star", - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yIR0d/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 8, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yUk9H/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 7, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yl52d/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 15, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9y8PDw/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 12, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9y2rM6/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 14, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yHYD5/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 1, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yJi6w/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 4, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yqkQ8/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 5, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yuDKJ/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 13, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yvU7H/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 9, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yqovz/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 3, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yMlSD/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 11, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yPdj+/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 10, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yH8eA/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 2, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yFnxe/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 6, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9ynJwW/wA=" - }, - { - "id": "minecraft:chain" - }, - { - "id": "minecraft:target", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnRhcmdldAQJAG5hbWVfaGFzaJc66SVbYlaxAwoAbmV0d29ya19pZPBozs0KBgBzdGF0ZXMAAwcAdmVyc2lvbjIeFAEA" - }, - { - "id": "minecraft:decorated_pot", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmRlY29yYXRlZF9wb3QECQBuYW1lX2hhc2jjQgckn8VTvwMKAG5ldHdvcmtfaWRwvkUUCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uMh4UAQA=" - }, - { - "id": "minecraft:lodestone_compass" - }, - { - "id": "minecraft:wither_spawn_egg" - }, - { - "id": "minecraft:ender_dragon_spawn_egg" - } - ] -} \ No newline at end of file diff --git a/core/src/main/resources/bedrock/creative_items.1_20_50.json b/core/src/main/resources/bedrock/creative_items.1_20_50.json index c72695a42..d93aa4c00 100644 --- a/core/src/main/resources/bedrock/creative_items.1_20_50.json +++ b/core/src/main/resources/bedrock/creative_items.1_20_50.json @@ -1044,34 +1044,122 @@ "id": "minecraft:copper_block", "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmNvcHBlcl9ibG9jawQJAG5hbWVfaGFzaDVxnehsGaZ1AwoAbmV0d29ya19pZIiUodwKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" }, + { + "id": "minecraft:copper_door" + }, + { + "id": "minecraft:copper_trapdoor", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmNvcHBlcl90cmFwZG9vcgQJAG5hbWVfaGFzaO9fXio+svKVAwoAbmV0d29ya19pZMCoRjEKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uATIUAQA=" + }, + { + "id": "minecraft:copper_grate", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmNvcHBlcl9ncmF0ZQQJAG5hbWVfaGFzaC/JEFOWnmEcAwoAbmV0d29ya19pZC6YiiMKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" + }, { "id": "minecraft:exposed_copper", "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmV4cG9zZWRfY29wcGVyBAkAbmFtZV9oYXNoQH3Fukmu3CEDCgBuZXR3b3JrX2lk72jFIwoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" }, + { + "id": "minecraft:exposed_copper_door" + }, + { + "id": "minecraft:exposed_copper_trapdoor", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmV4cG9zZWRfY29wcGVyX3RyYXBkb29yBAkAbmFtZV9oYXNoYhDFUysN7qUDCgBuZXR3b3JrX2lkMzwGJgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24BMhQBAA==" + }, + { + "id": "minecraft:exposed_copper_grate", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmV4cG9zZWRfY29wcGVyX2dyYXRlBAkAbmFtZV9oYXNolFIBYLYU0IcDCgBuZXR3b3JrX2lk4UqptAoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" + }, { "id": "minecraft:weathered_copper", "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OndlYXRoZXJlZF9jb3BwZXIECQBuYW1lX2hhc2hJCQXbvobv+gMKAG5ldHdvcmtfaWQwM0lJCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" }, + { + "id": "minecraft:weathered_copper_door" + }, + { + "id": "minecraft:weathered_copper_trapdoor", + "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0OndlYXRoZXJlZF9jb3BwZXJfdHJhcGRvb3IECQBuYW1lX2hhc2hFnEC282a1tgMKAG5ldHdvcmtfaWTk70oiCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAEPAHVwc2lkZV9kb3duX2JpdAAAAwcAdmVyc2lvbgEyFAEA" + }, + { + "id": "minecraft:weathered_copper_grate", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OndlYXRoZXJlZF9jb3BwZXJfZ3JhdGUECQBuYW1lX2hhc2jB3o8enlv1RgMKAG5ldHdvcmtfaWRih2pOCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" + }, { "id": "minecraft:oxidized_copper", "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om94aWRpemVkX2NvcHBlcgQJAG5hbWVfaGFzaMDtJqR0G5Y7AwoAbmV0d29ya19pZGjN8bUKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" }, + { + "id": "minecraft:oxidized_copper_door" + }, + { + "id": "minecraft:oxidized_copper_trapdoor", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0Om94aWRpemVkX2NvcHBlcl90cmFwZG9vcgQJAG5hbWVfaGFzaOJpG/XFexVwAwoAbmV0d29ya19pZPhi0J4KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uATIUAQA=" + }, + { + "id": "minecraft:oxidized_copper_grate", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0Om94aWRpemVkX2NvcHBlcl9ncmF0ZQQJAG5hbWVfaGFzaBRfNhyndve7AwoAbmV0d29ya19pZKY2cnEKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" + }, { "id": "minecraft:waxed_copper", "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OndheGVkX2NvcHBlcgQJAG5hbWVfaGFzaPF+FG6Eh5fsAwoAbmV0d29ya19pZIjtz/0KBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" }, + { + "id": "minecraft:waxed_copper_door" + }, + { + "id": "minecraft:waxed_copper_trapdoor", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OndheGVkX2NvcHBlcl90cmFwZG9vcgQJAG5hbWVfaGFzaO0JUKUHqNU6AwoAbmV0d29ya19pZJC3ZuMKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uATIUAQA=" + }, + { + "id": "minecraft:waxed_copper_grate", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OndheGVkX2NvcHBlcl9ncmF0ZQQJAG5hbWVfaGFzaDmC92M2RO+HAwoAbmV0d29ya19pZH4og2AKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" + }, { "id": "minecraft:waxed_exposed_copper", "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY29wcGVyBAkAbmFtZV9oYXNoig8IOc+SCikDCgBuZXR3b3JrX2lklz8yWQoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" }, + { + "id": "minecraft:waxed_exposed_copper_door" + }, + { + "id": "minecraft:waxed_exposed_copper_trapdoor", + "block_state_b64": "CgAACAQAbmFtZScAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY29wcGVyX3RyYXBkb29yBAkAbmFtZV9oYXNoBHHxCpkUzpgDCgBuZXR3b3JrX2lkw2XBGQoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24BMhQBAA==" + }, + { + "id": "minecraft:waxed_exposed_copper_grate", + "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY29wcGVyX2dyYXRlBAkAbmFtZV9oYXNoWmd6B+hWwiEDCgBuZXR3b3JrX2lk8d4ZQwoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" + }, { "id": "minecraft:waxed_weathered_copper", "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jb3BwZXIECQBuYW1lX2hhc2gjtPq8MOdvKgMKAG5ldHdvcmtfaWSQ9Ln9CgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" }, + { + "id": "minecraft:waxed_weathered_copper_door" + }, + { + "id": "minecraft:waxed_weathered_copper_trapdoor", + "block_state_b64": "CgAACAQAbmFtZSkAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jb3BwZXJfdHJhcGRvb3IECQBuYW1lX2hhc2gH9Fi3JCF4egMKAG5ldHdvcmtfaWRkGU6TCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAEPAHVwc2lkZV9kb3duX2JpdAAAAwcAdmVyc2lvbgEyFAEA" + }, + { + "id": "minecraft:waxed_weathered_copper_grate", + "block_state_b64": "CgAACAQAbmFtZSYAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jb3BwZXJfZ3JhdGUECQBuYW1lX2hhc2hXfilVFDAiYQMKAG5ldHdvcmtfaWQqTGC1CgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" + }, { "id": "minecraft:waxed_oxidized_copper", "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OndheGVkX294aWRpemVkX2NvcHBlcgQJAG5hbWVfaGFzaMaORhsO+LzjAwoAbmV0d29ya19pZJhGfLEKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" }, + { + "id": "minecraft:waxed_oxidized_copper_door" + }, + { + "id": "minecraft:waxed_oxidized_copper_trapdoor", + "block_state_b64": "CgAACAQAbmFtZSgAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2NvcHBlcl90cmFwZG9vcgQJAG5hbWVfaGFzaNA/q9qAy6Z9AwoAbmV0d29ya19pZDgExS8KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uATIUAQA=" + }, + { + "id": "minecraft:waxed_oxidized_copper_grate", + "block_state_b64": "CgAACAQAbmFtZSUAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2NvcHBlcl9ncmF0ZQQJAG5hbWVfaGFzaEbeMT605GP4AwoAbmV0d29ya19pZOZjpkkKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" + }, { "id": "minecraft:cut_copper", "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmN1dF9jb3BwZXIECQBuYW1lX2hhc2hAfN3NGax3eAMKAG5ldHdvcmtfaWTnFBtYCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" @@ -1104,6 +1192,70 @@ "id": "minecraft:waxed_oxidized_cut_copper", "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2i1pZAsZYHLDAMKAG5ldHdvcmtfaWQ/wSkCCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" }, + { + "id": "minecraft:chiseled_copper", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmNoaXNlbGVkX2NvcHBlcgQJAG5hbWVfaGFzaIsW5pmpJEuQAwoAbmV0d29ya19pZHetwrkKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" + }, + { + "id": "minecraft:exposed_chiseled_copper", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmV4cG9zZWRfY2hpc2VsZWRfY29wcGVyBAkAbmFtZV9oYXNoOvrLJ0UowbgDCgBuZXR3b3JrX2lkZj7cPwoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" + }, + { + "id": "minecraft:weathered_chiseled_copper", + "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0OndlYXRoZXJlZF9jaGlzZWxlZF9jb3BwZXIECQBuYW1lX2hhc2hh+42XlsWvGAMKAG5ldHdvcmtfaWS7Cy59CgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" + }, + { + "id": "minecraft:oxidized_chiseled_copper", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0Om94aWRpemVkX2NoaXNlbGVkX2NvcHBlcgQJAG5hbWVfaGFzaLpTIsnfluiCAwoAbmV0d29ya19pZB9/jS8KBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" + }, + { + "id": "minecraft:waxed_chiseled_copper", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OndheGVkX2NoaXNlbGVkX2NvcHBlcgQJAG5hbWVfaGFzaFnXvXY5OinzAwoAbmV0d29ya19pZAcKtHsKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" + }, + { + "id": "minecraft:waxed_exposed_chiseled_copper", + "block_state_b64": "CgAACAQAbmFtZScAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY2hpc2VsZWRfY29wcGVyBAkAbmFtZV9oYXNoHJdq+Pph6hMDCgBuZXR3b3JrX2lkdge7IAoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" + }, + { + "id": "minecraft:waxed_oxidized_chiseled_copper", + "block_state_b64": "CgAACAQAbmFtZSgAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2NoaXNlbGVkX2NvcHBlcgQJAG5hbWVfaGFzaMj49OvlTpgCAwoAbmV0d29ya19pZN/r+roKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" + }, + { + "id": "minecraft:waxed_weathered_chiseled_copper", + "block_state_b64": "CgAACAQAbmFtZSkAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jaGlzZWxlZF9jb3BwZXIECQBuYW1lX2hhc2hzuO+Sg9LYQwMKAG5ldHdvcmtfaWQ7AN7iCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" + }, + { + "id": "minecraft:copper_bulb", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcHBlcl9idWxiBAkAbmFtZV9oYXNo41TimHOsMWcDCgBuZXR3b3JrX2lkJnZvAgoGAHN0YXRlcwEDAGxpdAABCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgEyFAEA" + }, + { + "id": "minecraft:exposed_copper_bulb", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmV4cG9zZWRfY29wcGVyX2J1bGIECQBuYW1lX2hhc2g++f1wYLLCrAMKAG5ldHdvcmtfaWRLdMmGCgYAc3RhdGVzAQMAbGl0AAELAHBvd2VyZWRfYml0AAADBwB2ZXJzaW9uATIUAQA=" + }, + { + "id": "minecraft:weathered_copper_bulb", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OndlYXRoZXJlZF9jb3BwZXJfYnVsYgQJAG5hbWVfaGFzaMEtsYfwRTXlAwoAbmV0d29ya19pZAp51LQKBgBzdGF0ZXMBAwBsaXQAAQsAcG93ZXJlZF9iaXQAAAMHAHZlcnNpb24BMhQBAA==" + }, + { + "id": "minecraft:oxidized_copper_bulb", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0Om94aWRpemVkX2NvcHBlcl9idWxiBAkAbmFtZV9oYXNovnrBQZs8nDIDCgBuZXR3b3JrX2lkPsj0AAoGAHN0YXRlcwEDAGxpdAABCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgEyFAEA" + }, + { + "id": "minecraft:waxed_copper_bulb", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OndheGVkX2NvcHBlcl9idWxiBAkAbmFtZV9oYXNoGTg6TYllMiIDCgBuZXR3b3JrX2lk9m0WhgoGAHN0YXRlcwEDAGxpdAABCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgEyFAEA" + }, + { + "id": "minecraft:waxed_exposed_copper_bulb", + "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY29wcGVyX2J1bGIECQBuYW1lX2hhc2gI6xkPcvBDVwMKAG5ldHdvcmtfaWR7BRcACgYAc3RhdGVzAQMAbGl0AAELAHBvd2VyZWRfYml0AAADBwB2ZXJzaW9uATIUAQA=" + }, + { + "id": "minecraft:waxed_weathered_copper_bulb", + "block_state_b64": "CgAACAQAbmFtZSUAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jb3BwZXJfYnVsYgQJAG5hbWVfaGFzaMsUnmp3/VqVAwoAbmV0d29ya19pZEoworoKBgBzdGF0ZXMBAwBsaXQAAQsAcG93ZXJlZF9iaXQAAAMHAHZlcnNpb24BMhQBAA==" + }, + { + "id": "minecraft:waxed_oxidized_copper_bulb", + "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2NvcHBlcl9idWxiBAkAbmFtZV9oYXNoBFKxY3fjVq4DCgBuZXR3b3JrX2lkzrJ6aAoGAHN0YXRlcwEDAGxpdAABCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgEyFAEA" + }, { "id": "minecraft:emerald_block", "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmVtZXJhbGRfYmxvY2sECQBuYW1lX2hhc2hK6QunqJznNAMKAG5ldHdvcmtfaWRk5+otCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" @@ -2509,6 +2661,58 @@ "id": "minecraft:tuff", "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OnR1ZmYECQBuYW1lX2hhc2h1Rwc1XYsBGwMKAG5ldHdvcmtfaWRwQGn0CgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" }, + { + "id": "minecraft:tuff_stairs", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnR1ZmZfc3RhaXJzBAkAbmFtZV9oYXNoKjyNUBjcfZsDCgBuZXR3b3JrX2lk+LsycgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" + }, + { + "id": "minecraft:tuff_slab", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnR1ZmZfc2xhYgQJAG5hbWVfaGFzaIhCGdlIsnMUAwoAbmV0d29ya19pZN1dUL4KBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24BMhQBAA==" + }, + { + "id": "minecraft:tuff_wall", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnR1ZmZfd2FsbAQJAG5hbWVfaGFzaMyeeu1IRf03AwoAbmV0d29ya19pZDkIrosKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uATIUAQA=" + }, + { + "id": "minecraft:chiseled_tuff", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNoaXNlbGVkX3R1ZmYECQBuYW1lX2hhc2iVliOT8OTQ9AMKAG5ldHdvcmtfaWTLNKOiCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" + }, + { + "id": "minecraft:polished_tuff", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnBvbGlzaGVkX3R1ZmYECQBuYW1lX2hhc2hyaLe/KEVZ0gMKAG5ldHdvcmtfaWTcX3NrCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" + }, + { + "id": "minecraft:polished_tuff_stairs", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnBvbGlzaGVkX3R1ZmZfc3RhaXJzBAkAbmFtZV9oYXNo8yuah8QI1dcDCgBuZXR3b3JrX2lkjLoU4AoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" + }, + { + "id": "minecraft:polished_tuff_slab", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnBvbGlzaGVkX3R1ZmZfc2xhYgQJAG5hbWVfaGFzaLXdb48YvAsHAwoAbmV0d29ya19pZAnJ7W0KBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24BMhQBAA==" + }, + { + "id": "minecraft:polished_tuff_wall", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnBvbGlzaGVkX3R1ZmZfd2FsbAQJAG5hbWVfaGFzaJVZj6QYWXUrAwoAbmV0d29ya19pZLU7dooKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uATIUAQA=" + }, + { + "id": "minecraft:tuff_bricks", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnR1ZmZfYnJpY2tzBAkAbmFtZV9oYXNo/hbQ+mXSK7wDCgBuZXR3b3JrX2lk6gmIwQoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" + }, + { + "id": "minecraft:tuff_brick_stairs", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnR1ZmZfYnJpY2tfc3RhaXJzBAkAbmFtZV9oYXNoWJpkAurUfKwDCgBuZXR3b3JrX2lkUMcjiwoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" + }, + { + "id": "minecraft:tuff_brick_slab", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnR1ZmZfYnJpY2tfc2xhYgQJAG5hbWVfaGFzaLqPMjVCv5dIAwoAbmV0d29ya19pZOmeRhcKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24BMhQBAA==" + }, + { + "id": "minecraft:tuff_brick_wall", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnR1ZmZfYnJpY2tfd2FsbAQJAG5hbWVfaGFzaIL0IyNCOsonAwoAbmV0d29ya19pZJW4T5UKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uATIUAQA=" + }, + { + "id": "minecraft:chiseled_tuff_bricks", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmNoaXNlbGVkX3R1ZmZfYnJpY2tzBAkAbmFtZV9oYXNo3oQw6gmxYuADCgBuZXR3b3JrX2lkm3D8AgoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" + }, { "id": "minecraft:calcite", "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmNhbGNpdGUECQBuYW1lX2hhc2ixKLu8ZIdzDQMKAG5ldHdvcmtfaWQlSbJDCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" @@ -5394,6 +5598,10 @@ "id": "minecraft:dispenser", "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmRpc3BlbnNlcgQJAG5hbWVfaGFzaP1RR+zAbYP2AwoAbmV0d29ya19pZGAayD0KBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAwAAAAENAHRyaWdnZXJlZF9iaXQAAAMHAHZlcnNpb24BMhQBAA==" }, + { + "id": "minecraft:crafter", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmNyYWZ0ZXIECQBuYW1lX2hhc2iLCT/rJmRN8QMKAG5ldHdvcmtfaWTPTbvrCgYAc3RhdGVzAQgAY3JhZnRpbmcACAsAb3JpZW50YXRpb24JAGRvd25fZWFzdAENAHRyaWdnZXJlZF9iaXQAAAMHAHZlcnNpb24BMhQBAA==" + }, { "id": "minecraft:piston", "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBpc3RvbgQJAG5hbWVfaGFzaDs3AFh1fL0uAwoAbmV0d29ya19pZLD/5XQKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAQAAAAADBwB2ZXJzaW9uATIUAQA=" From e2062dd1827cd288aa67a95db473a81a7e219300 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Fri, 1 Dec 2023 15:17:41 -0500 Subject: [PATCH 151/344] Reimplement support for 1.20.40 --- README.md | 2 +- .../geysermc/geyser/network/GameProtocol.java | 3 +- .../populator/BlockRegistryPopulator.java | 11 +- .../registry/populator/Conversion630_622.java | 213 ++++++++++++++++++ .../populator/ItemRegistryPopulator.java | 20 +- .../registry/type/GeyserMappingItem.java | 2 - core/src/main/resources/mappings | 2 +- 7 files changed, 220 insertions(+), 33 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/registry/populator/Conversion630_622.java diff --git a/README.md b/README.md index b3471b4d7..1663c493a 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,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.20.0 - 1.20.50 and Minecraft Java 1.20.3 +### Currently supporting Minecraft Bedrock 1.20.40 - 1.20.50 and Minecraft Java 1.20.3 ## 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/GameProtocol.java b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java index 923779095..e22d1da97 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java @@ -29,6 +29,7 @@ import com.github.steveice10.mc.protocol.codec.MinecraftCodec; import com.github.steveice10.mc.protocol.codec.PacketCodec; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; +import org.cloudburstmc.protocol.bedrock.codec.v622.Bedrock_v622; import org.cloudburstmc.protocol.bedrock.codec.v630.Bedrock_v630; import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec; @@ -58,11 +59,9 @@ public final class GameProtocol { private static final PacketCodec DEFAULT_JAVA_CODEC = MinecraftCodec.CODEC; static { - /* SUPPORTED_BEDROCK_CODECS.add(Bedrock_v622.CODEC.toBuilder() .minecraftVersion("1.20.40/1.20.41") .build()); - */ SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC); } 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 f185119ca..415e61ac2 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 @@ -34,18 +34,11 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.*; import org.cloudburstmc.blockstateupdater.BlockStateUpdater; -import org.cloudburstmc.blockstateupdater.BlockStateUpdater_1_20_10; -import org.cloudburstmc.blockstateupdater.BlockStateUpdater_1_20_30; -import org.cloudburstmc.blockstateupdater.BlockStateUpdater_1_20_40; -import org.cloudburstmc.blockstateupdater.BlockStateUpdater_1_20_50; import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; import org.cloudburstmc.nbt.NBTInputStream; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; -import org.cloudburstmc.protocol.bedrock.codec.v589.Bedrock_v589; -import org.cloudburstmc.protocol.bedrock.codec.v594.Bedrock_v594; -import org.cloudburstmc.protocol.bedrock.codec.v618.Bedrock_v618; import org.cloudburstmc.protocol.bedrock.codec.v622.Bedrock_v622; import org.cloudburstmc.protocol.bedrock.codec.v630.Bedrock_v630; import org.cloudburstmc.protocol.bedrock.data.BlockPropertyData; @@ -83,7 +76,7 @@ public final class BlockRegistryPopulator { } @FunctionalInterface - private interface Remapper { + interface Remapper { NbtMap remap(NbtMap tag); @@ -123,7 +116,7 @@ public final class BlockRegistryPopulator { private static void registerBedrockBlocks() { var blockMappers = ImmutableMap., Remapper>builder() - //.put(ObjectIntPair.of("1_20_40", Bedrock_v622.CODEC.getProtocolVersion()), mapper622) + .put(ObjectIntPair.of("1_20_40", Bedrock_v622.CODEC.getProtocolVersion()), Conversion630_622::remapBlock) .put(ObjectIntPair.of("1_20_50", Bedrock_v630.CODEC.getProtocolVersion()), tag -> tag) .build(); diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion630_622.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion630_622.java new file mode 100644 index 000000000..9404774b8 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion630_622.java @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2019-2023 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 it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtMapBuilder; +import org.geysermc.geyser.item.type.Item; +import org.geysermc.geyser.registry.type.GeyserMappingItem; + +import java.util.List; +import java.util.Map; + +/** + * Backwards-maps the blocks and items of 1.20.50 (630) to 1.20.40 (622) + */ +public class Conversion630_622 { + + private static final List NEW_STONES = List.of("minecraft:stone", "minecraft:granite", "minecraft:polished_granite", "minecraft:diorite", "minecraft:polished_diorite", "minecraft:andesite", "minecraft:polished_andesite"); + private static final List NEW_WOODS = List.of("minecraft:oak_planks", "minecraft:spruce_planks", "minecraft:birch_planks", "minecraft:jungle_planks", "minecraft:acacia_planks", "minecraft:dark_oak_planks"); + + private static final Map ITEMS = new Object2ObjectOpenHashMap<>(); + + static { + ITEMS.put("minecraft:acacia_planks", "minecraft:planks"); + ITEMS.put("minecraft:birch_planks", "minecraft:planks"); + ITEMS.put("minecraft:dark_oak_planks", "minecraft:planks"); + ITEMS.put("minecraft:jungle_planks", "minecraft:planks"); + ITEMS.put("minecraft:oak_planks", "minecraft:planks"); + ITEMS.put("minecraft:spruce_planks", "minecraft:planks"); + + ITEMS.put("minecraft:diorite", "minecraft:stone"); + ITEMS.put("minecraft:andesite", "minecraft:stone"); + ITEMS.put("minecraft:granite", "minecraft:stone"); + ITEMS.put("minecraft:polished_andesite", "minecraft:stone"); + ITEMS.put("minecraft:polished_diorite", "minecraft:stone"); + ITEMS.put("minecraft:polished_granite", "minecraft:stone"); + + ITEMS.put("minecraft:chiseled_tuff", "minecraft:chiseled_deepslate"); + ITEMS.put("minecraft:chiseled_tuff_bricks", "minecraft:chiseled_deepslate"); + ITEMS.put("minecraft:polished_tuff", "minecraft:polished_deepslate"); + ITEMS.put("minecraft:polished_tuff_double_slab", "minecraft:polished_deepslate_double_slab"); + ITEMS.put("minecraft:polished_tuff_slab", "minecraft:polished_deepslate_slab"); + ITEMS.put("minecraft:polished_tuff_stairs", "minecraft:polished_deepslate_stairs"); + ITEMS.put("minecraft:polished_tuff_wall", "minecraft:polished_deepslate_wall"); + ITEMS.put("minecraft:tuff_brick_double_slab", "minecraft:deepslate_brick_double_slab"); + ITEMS.put("minecraft:tuff_brick_slab", "minecraft:deepslate_brick_slab"); + ITEMS.put("minecraft:tuff_brick_stairs", "minecraft:deepslate_brick_stairs"); + ITEMS.put("minecraft:tuff_brick_wall", "minecraft:deepslate_brick_wall"); + ITEMS.put("minecraft:tuff_bricks", "minecraft:deepslate_bricks"); + ITEMS.put("minecraft:tuff_double_slab", "minecraft:cobbled_deepslate_double_slab"); + ITEMS.put("minecraft:tuff_slab", "minecraft:cobbled_deepslate_slab"); + ITEMS.put("minecraft:tuff_stairs", "minecraft:cobbled_deepslate_stairs"); + ITEMS.put("minecraft:tuff_wall", "minecraft:cobbled_deepslate_wall"); + + ITEMS.put("minecraft:chiseled_copper", "minecraft:copper_block"); + ITEMS.put("minecraft:copper_bulb", "minecraft:copper_block"); + ITEMS.put("minecraft:copper_door", "minecraft:iron_door"); + ITEMS.put("minecraft:copper_grate", "minecraft:raw_iron_block"); + ITEMS.put("minecraft:copper_trapdoor", "minecraft:iron_trapdoor"); + ITEMS.put("minecraft:exposed_chiseled_copper", "minecraft:exposed_copper"); + ITEMS.put("minecraft:exposed_copper_bulb", "minecraft:exposed_copper"); + ITEMS.put("minecraft:exposed_copper_door", "minecraft:iron_door"); + ITEMS.put("minecraft:exposed_copper_grate", "minecraft:raw_iron_block"); + ITEMS.put("minecraft:exposed_copper_trapdoor", "minecraft:iron_trapdoor"); + ITEMS.put("minecraft:oxidized_chiseled_copper", "minecraft:oxidized_copper"); + ITEMS.put("minecraft:oxidized_copper_bulb", "minecraft:oxidized_copper"); + ITEMS.put("minecraft:oxidized_copper_door", "minecraft:iron_door"); + ITEMS.put("minecraft:oxidized_copper_grate", "minecraft:raw_iron_block"); + ITEMS.put("minecraft:oxidized_copper_trapdoor", "minecraft:iron_trapdoor"); + ITEMS.put("minecraft:waxed_chiseled_copper", "minecraft:waxed_copper"); + ITEMS.put("minecraft:waxed_copper_bulb", "minecraft:waxed_copper"); + ITEMS.put("minecraft:waxed_copper_door", "minecraft:iron_door"); + ITEMS.put("minecraft:waxed_copper_grate", "minecraft:raw_iron_block"); + ITEMS.put("minecraft:waxed_copper_trapdoor", "minecraft:iron_trapdoor"); + ITEMS.put("minecraft:waxed_exposed_chiseled_copper", "minecraft:waxed_exposed_copper"); + ITEMS.put("minecraft:waxed_exposed_copper_bulb", "minecraft:waxed_exposed_copper"); + ITEMS.put("minecraft:waxed_exposed_copper_door", "minecraft:iron_door"); + ITEMS.put("minecraft:waxed_exposed_copper_grate", "minecraft:raw_iron_block"); + ITEMS.put("minecraft:waxed_exposed_copper_trapdoor", "minecraft:iron_trapdoor"); + ITEMS.put("minecraft:waxed_oxidized_chiseled_copper", "minecraft:waxed_oxidized_copper"); + ITEMS.put("minecraft:waxed_oxidized_copper_bulb", "minecraft:waxed_oxidized_copper"); + ITEMS.put("minecraft:waxed_oxidized_copper_door", "minecraft:iron_door"); + ITEMS.put("minecraft:waxed_oxidized_copper_grate", "minecraft:raw_iron_block"); + ITEMS.put("minecraft:waxed_oxidized_copper_trapdoor", "minecraft:iron_trapdoor"); + ITEMS.put("minecraft:waxed_weathered_chiseled_copper", "minecraft:waxed_weathered_copper"); + ITEMS.put("minecraft:waxed_weathered_copper_bulb", "minecraft:waxed_weathered_copper"); + ITEMS.put("minecraft:waxed_weathered_copper_door", "minecraft:iron_door"); + ITEMS.put("minecraft:waxed_weathered_copper_grate", "minecraft:raw_iron_block"); + ITEMS.put("minecraft:waxed_weathered_copper_trapdoor", "minecraft:iron_trapdoor"); + ITEMS.put("minecraft:weathered_chiseled_copper", "minecraft:weathered_copper"); + ITEMS.put("minecraft:weathered_copper_bulb", "minecraft:weathered_copper"); + ITEMS.put("minecraft:weathered_copper_door", "minecraft:iron_door"); + ITEMS.put("minecraft:weathered_copper_grate", "minecraft:raw_iron_block"); + ITEMS.put("minecraft:weathered_copper_trapdoor", "minecraft:iron_trapdoor"); + + ITEMS.put("minecraft:crafter", "minecraft:crafting_table"); + } + + static GeyserMappingItem remapItem(@SuppressWarnings("unused") Item item, GeyserMappingItem mapping) { + String replacement = ITEMS.get(mapping.getBedrockIdentifier()); + if (replacement == null) { + return mapping; + } else { + return mapping.withBedrockIdentifier(replacement); + } + } + + static NbtMap remapBlock(NbtMap tag) { + final String name = tag.getString("name"); + + String replacement; + if (NEW_STONES.contains(name) || NEW_WOODS.contains(name)) { + + String typeKey; + String type = name.substring(10); + if (NEW_STONES.contains(name)) { + replacement = "minecraft:stone"; + typeKey = "stone_type"; + if (type.startsWith("polished_")) { + type = type.substring(9) + "_smooth"; + } + } else { + replacement = "minecraft:planks"; + typeKey = "wood_type"; + type = type.substring(0, type.indexOf("_planks")); + } + + return tag.toBuilder() + .putString("name", replacement) + .putCompound("states", NbtMap.builder().putString(typeKey, type).build()) + .build(); + } else if (name.contains("tuff") && !name.equals("minecraft:tuff")) { + + if (name.contains("brick") || name.contains("polished") || name.contains("chiseled")) { + replacement = name.replace("tuff", "deepslate"); + + if (name.contains("chiseled")) { + // chiseled deepslate bricks don't exist. just use chiseled deepslate instead + replacement = replacement.replace("_bricks", ""); + } + } else { + replacement = name.replace("tuff", "cobbled_deepslate"); + } + + return tag.toBuilder() + .putString("name", replacement) + .build(); + } else if (name.contains("copper")) { + + boolean removeStates = false; + if (name.contains("chiseled")) { + replacement = name.replace("_chiseled", ""); // special chiseled + replacement = replacement.replace("chiseled_", ""); // plain chiseled + } else if (name.endsWith("bulb")) { + replacement = name.replace("_bulb", ""); + removeStates = true; + } else if (name.endsWith("grate")) { + replacement = "minecraft:raw_iron_block"; + } else if (name.endsWith("door")) { + if (name.contains("trap")) { + replacement = "minecraft:iron_trapdoor"; + } else { + replacement = "minecraft:iron_door"; + } + } else { + return tag; + } + + if (replacement.endsWith(":copper")) { + // case for plain chiseled copper and plain bulb + replacement = replacement + "_block"; + } + + NbtMapBuilder builder = tag.toBuilder(); + builder.putString("name", replacement); + if (removeStates) { + builder.putCompound("states", NbtMap.EMPTY); + } + return builder.build(); + } else if (name.equals("minecraft:crafter")) { + NbtMapBuilder builder = tag.toBuilder(); + builder.put("name", "minecraft:crafting_table"); + builder.put("states", NbtMap.EMPTY); + return builder.build(); + } + + return tag; + } +} 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 5aa24de1f..74c0432b5 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 @@ -38,9 +38,6 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; -import org.cloudburstmc.protocol.bedrock.codec.v589.Bedrock_v589; -import org.cloudburstmc.protocol.bedrock.codec.v594.Bedrock_v594; -import org.cloudburstmc.protocol.bedrock.codec.v618.Bedrock_v618; import org.cloudburstmc.protocol.bedrock.codec.v622.Bedrock_v622; import org.cloudburstmc.protocol.bedrock.codec.v630.Bedrock_v630; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; @@ -89,21 +86,8 @@ public class ItemRegistryPopulator { } public static void populate() { - /* - Remapper remapper630 = (item, mapping) -> { - String id = item.javaIdentifier(); - // 1.20.50 replaced stone & planks to individual stone types - // E.g.: granite, diorite, andesite, polished variants, dark_oak_planks etc - if (mapping.getBedrockIdentifier().equals("minecraft:stone") || mapping.getBedrockIdentifier().equals("minecraft:planks")) { - return mapping.withBedrockIdentifier(id); - } - - return mapping; - }; - */ - List paletteVersions = new ArrayList<>(3); - //paletteVersions.add(new PaletteVersion("1_20_40", Bedrock_v622.CODEC.getProtocolVersion(), Collections.emptyMap(), remapper618)); // NO item changes between 1.20.30 and 1.20.40 + paletteVersions.add(new PaletteVersion("1_20_40", Bedrock_v622.CODEC.getProtocolVersion(), Collections.emptyMap(), Conversion630_622::remapItem)); // NO item changes between 1.20.30 and 1.20.40 paletteVersions.add(new PaletteVersion("1_20_50", Bedrock_v630.CODEC.getProtocolVersion())); GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap(); @@ -371,7 +355,7 @@ public class ItemRegistryPopulator { if (customBlockItemOverride != null && customBlockData != null) { // Assuming this is a valid custom block override we'll just register it now while we have the creative item int customProtocolId = nextFreeBedrockId++; - mappingItem.setBedrockData(customProtocolId); + mappingItem = mappingItem.withBedrockData(customProtocolId); bedrockIdentifier = customBlockData.identifier(); definition = new SimpleItemDefinition(bedrockIdentifier, customProtocolId, true); registry.put(customProtocolId, definition); diff --git a/core/src/main/java/org/geysermc/geyser/registry/type/GeyserMappingItem.java b/core/src/main/java/org/geysermc/geyser/registry/type/GeyserMappingItem.java index c1ef09b87..ab8c52bf6 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/type/GeyserMappingItem.java +++ b/core/src/main/java/org/geysermc/geyser/registry/type/GeyserMappingItem.java @@ -30,7 +30,6 @@ import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; -import lombok.Setter; import lombok.ToString; import lombok.With; @@ -40,7 +39,6 @@ import lombok.With; @ToString @EqualsAndHashCode @Getter -@Setter @With @NoArgsConstructor @AllArgsConstructor diff --git a/core/src/main/resources/mappings b/core/src/main/resources/mappings index ad4b7952e..2393a6555 160000 --- a/core/src/main/resources/mappings +++ b/core/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit ad4b7952e997aaff144e2ce80e9552c8db93b8f1 +Subproject commit 2393a655595abd8e0b93e88553d9d8d7cdbde95b From 22009054ab572eedf22122e200890d23cdd6b30b Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Sun, 3 Dec 2023 10:03:59 -0500 Subject: [PATCH 152/344] Crafter translation --- .../geyser/inventory/CrafterContainer.java | 61 +++++++ .../updater/CrafterInventoryUpdater.java | 94 ++++++++++ .../geysermc/geyser/network/GameProtocol.java | 5 + .../geyser/network/LoggingPacketHandler.java | 7 + .../inventory/CrafterInventoryTranslator.java | 168 ++++++++++++++++++ .../inventory/InventoryTranslator.java | 1 + .../DecoratedPotBlockEntityTranslator.java | 1 - .../TrialSpawnerBlockEntityTranslator.java | 42 +++++ ...ockToggleCrafterSlotRequestTranslator.java | 48 +++++ .../inventory/JavaOpenScreenTranslator.java | 10 +- gradle/libs.versions.toml | 2 +- 11 files changed, 436 insertions(+), 3 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/inventory/CrafterContainer.java create mode 100644 core/src/main/java/org/geysermc/geyser/inventory/updater/CrafterInventoryUpdater.java create mode 100644 core/src/main/java/org/geysermc/geyser/translator/inventory/CrafterInventoryTranslator.java create mode 100644 core/src/main/java/org/geysermc/geyser/translator/level/block/entity/TrialSpawnerBlockEntityTranslator.java create mode 100644 core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockToggleCrafterSlotRequestTranslator.java diff --git a/core/src/main/java/org/geysermc/geyser/inventory/CrafterContainer.java b/core/src/main/java/org/geysermc/geyser/inventory/CrafterContainer.java new file mode 100644 index 000000000..bcacd3587 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/inventory/CrafterContainer.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2019-2023 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.inventory; + +import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; +import lombok.Getter; +import lombok.Setter; +import org.geysermc.geyser.GeyserImpl; + +@Getter +public class CrafterContainer extends Container { + + @Setter + private boolean triggered = false; + + /** + * Bedrock Edition bitmask of the *disabled* slots. + * Disabled slots are 1, enabled slots are 0 - same as Java Edition + */ + private short disabledSlotsMask = 0; + + public CrafterContainer(String title, int id, int size, ContainerType containerType, PlayerInventory playerInventory) { + super(title, id, size, containerType, playerInventory); + } + + public void setSlot(int slot, boolean enabled) { + if (slot < 0 || slot > 8) { + GeyserImpl.getInstance().getLogger().warning("Crafter slot out of bounds: " + slot); + return; + } + + if (enabled) { + disabledSlotsMask = (short) (disabledSlotsMask & ~(1 << slot)); + } else { + disabledSlotsMask = (short) (disabledSlotsMask | (1 << slot)); + } + } +} diff --git a/core/src/main/java/org/geysermc/geyser/inventory/updater/CrafterInventoryUpdater.java b/core/src/main/java/org/geysermc/geyser/inventory/updater/CrafterInventoryUpdater.java new file mode 100644 index 000000000..4474d420c --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/inventory/updater/CrafterInventoryUpdater.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2019-2023 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.inventory.updater; + +import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId; +import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; +import org.cloudburstmc.protocol.bedrock.packet.InventoryContentPacket; +import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket; +import org.geysermc.geyser.inventory.Inventory; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.inventory.CrafterInventoryTranslator; +import org.geysermc.geyser.translator.inventory.InventoryTranslator; + +import java.util.Arrays; + +/** + * Read {@link CrafterInventoryTranslator} for context on the complete custom implementation here + */ +public class CrafterInventoryUpdater extends InventoryUpdater { + + public static final CrafterInventoryUpdater INSTANCE = new CrafterInventoryUpdater(); + + @Override + public void updateInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) { + ItemData[] bedrockItems; + InventoryContentPacket contentPacket; + + // crafter grid - but excluding the result slot + bedrockItems = new ItemData[CrafterInventoryTranslator.GRID_SIZE]; + for (int i = 0; i < bedrockItems.length; i++) { + bedrockItems[translator.javaSlotToBedrock(i)] = inventory.getItem(i).getItemData(session); + } + contentPacket = new InventoryContentPacket(); + contentPacket.setContainerId(inventory.getBedrockId()); + contentPacket.setContents(Arrays.asList(bedrockItems)); + session.sendUpstreamPacket(contentPacket); + + // inventory and hotbar + bedrockItems = new ItemData[36]; + for (int i = 0; i < 36; i++) { + final int offset = i < 9 ? 27 : -9; + bedrockItems[i] = inventory.getItem(CrafterInventoryTranslator.GRID_SIZE + i + offset).getItemData(session); + } + contentPacket = new InventoryContentPacket(); + contentPacket.setContainerId(ContainerId.INVENTORY); + contentPacket.setContents(Arrays.asList(bedrockItems)); + session.sendUpstreamPacket(contentPacket); + + // Crafter result - it doesn't come after the grid, as explained elsewhere. + updateSlot(translator, session, inventory, CrafterInventoryTranslator.JAVA_RESULT_SLOT); + } + + @Override + public boolean updateSlot(InventoryTranslator translator, GeyserSession session, Inventory inventory, int javaSlot) { + int containerId; + if (javaSlot < CrafterInventoryTranslator.GRID_SIZE || javaSlot == CrafterInventoryTranslator.JAVA_RESULT_SLOT) { + // Parts of the Crafter UI + // It doesn't seem like BDS sends the result slot, but sending it as slot 50 does actually work (it doesn't seem to show otherwise) + containerId = inventory.getBedrockId(); + } else { + containerId = ContainerId.INVENTORY; + } + + InventorySlotPacket packet = new InventorySlotPacket(); + packet.setContainerId(containerId); + packet.setSlot(translator.javaSlotToBedrock(javaSlot)); + packet.setItem(inventory.getItem(javaSlot).getItemData(session)); + session.sendUpstreamPacket(packet); + return true; + } +} diff --git a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java index e22d1da97..c811afd2e 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java @@ -32,6 +32,7 @@ import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; import org.cloudburstmc.protocol.bedrock.codec.v622.Bedrock_v622; import org.cloudburstmc.protocol.bedrock.codec.v630.Bedrock_v630; import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec; +import org.geysermc.geyser.session.GeyserSession; import java.util.ArrayList; import java.util.List; @@ -81,6 +82,10 @@ public final class GameProtocol { /* Bedrock convenience methods to gatekeep features and easily remove the check on version removal */ + public static boolean isPre1_20_50(GeyserSession session) { + return session.getUpstream().getProtocolVersion() < Bedrock_v630.CODEC.getProtocolVersion(); + } + /** * Gets the {@link PacketCodec} for Minecraft: Java Edition. * diff --git a/core/src/main/java/org/geysermc/geyser/network/LoggingPacketHandler.java b/core/src/main/java/org/geysermc/geyser/network/LoggingPacketHandler.java index 80e624895..5076dbeb2 100644 --- a/core/src/main/java/org/geysermc/geyser/network/LoggingPacketHandler.java +++ b/core/src/main/java/org/geysermc/geyser/network/LoggingPacketHandler.java @@ -869,4 +869,11 @@ public class LoggingPacketHandler implements BedrockPacketHandler { public PacketSignal handle(RequestNetworkSettingsPacket packet) { return defaultHandler(packet); } + + // todo: fix arrangement + + @Override + public PacketSignal handle(ToggleCrafterSlotRequestPacket packet) { + return defaultHandler(packet); + } } \ No newline at end of file diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/CrafterInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/CrafterInventoryTranslator.java new file mode 100644 index 000000000..97398a207 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/CrafterInventoryTranslator.java @@ -0,0 +1,168 @@ +/* + * 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.translator.inventory; + +import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; +import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtMapBuilder; +import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; +import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData; +import org.geysermc.geyser.inventory.BedrockContainerSlot; +import org.geysermc.geyser.inventory.CrafterContainer; +import org.geysermc.geyser.inventory.Inventory; +import org.geysermc.geyser.inventory.PlayerInventory; +import org.geysermc.geyser.inventory.SlotType; +import org.geysermc.geyser.inventory.updater.CrafterInventoryUpdater; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.util.BlockEntityUtils; + +/** + * Translates the Crafter. Most important thing to know about this class is that + * the result slot comes after the 3x3 grid AND the inventory. This means that the total size of the Crafter (10) + * cannot be used to calculate the inventory slot indices. The Translator and the Updater must then + * override any methods that use the size for such calculations + */ +public class CrafterInventoryTranslator extends AbstractBlockInventoryTranslator { + + public static final int JAVA_RESULT_SLOT = 45; + public static final int BEDROCK_RESULT_SLOT = 50; + public static final int GRID_SIZE = 9; + + // Properties + private static final int SLOT_ENABLED = 0; // enabled slot value + private static final int TRIGGERED_KEY = 9; // key of triggered state + private static final int TRIGGERED = 1; // triggered value + + public CrafterInventoryTranslator() { + super(10, "minecraft:crafter", org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.CRAFTER, CrafterInventoryUpdater.INSTANCE); + } + + @Override + public void updateProperty(GeyserSession session, Inventory inventory, int key, int value) { + // the slot bits and triggered state are sent here rather than in a BlockEntityDataPacket. Yippee. + CrafterContainer container = (CrafterContainer) inventory; + + if (key == TRIGGERED_KEY) { + container.setTriggered(value == TRIGGERED); + } else { + // enabling and disabling slots of the 3x3 grid + container.setSlot(key, value == SLOT_ENABLED); + } + + // Unfortunately this will be called 10 times when a Crafter is opened + // Kind of unavoidable because it must be invoked anytime an individual property is updated + updateBlockEntity(session, container); + } + + @Override + public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) { + int slot = slotInfoData.getSlot(); + switch (slotInfoData.getContainer()) { + case HOTBAR_AND_INVENTORY, HOTBAR, INVENTORY -> { + //hotbar + if (slot >= 9) { + return slot + GRID_SIZE - 9; + } else { + return slot + GRID_SIZE + 27; + } + } + } + return slot; + } + + @Override + public int javaSlotToBedrock(int slot) { + if (slot == JAVA_RESULT_SLOT) { + return BEDROCK_RESULT_SLOT; + } + + // grid slots 0-8 + if (slot < GRID_SIZE) { + return slot; + } + + // inventory and hotbar + final int tmp = slot - GRID_SIZE; + if (tmp < 27) { + return tmp + 9; + } else { + return tmp - 27; + } + } + + @Override + public BedrockContainerSlot javaSlotToBedrockContainer(int javaSlot) { + if (javaSlot == JAVA_RESULT_SLOT) { + return new BedrockContainerSlot(ContainerSlotType.CRAFTER_BLOCK_CONTAINER, BEDROCK_RESULT_SLOT); + } + + // grid slots 0-8 + if (javaSlot < GRID_SIZE) { + return new BedrockContainerSlot(ContainerSlotType.LEVEL_ENTITY, javaSlot); + } + + // inventory and hotbar + final int tmp = javaSlot - GRID_SIZE; + if (tmp < 27) { + return new BedrockContainerSlot(ContainerSlotType.INVENTORY, tmp + 9); + } else { + return new BedrockContainerSlot(ContainerSlotType.HOTBAR, tmp - 27); + } + } + + @Override + public SlotType getSlotType(int javaSlot) { + if (javaSlot == JAVA_RESULT_SLOT) { + return SlotType.OUTPUT; + } + return SlotType.NORMAL; + } + + @Override + public Inventory createInventory(String name, int windowId, ContainerType containerType, PlayerInventory playerInventory) { + // Java sends the triggered and slot bits incrementally through properties, which we store here + return new CrafterContainer(name, windowId, this.size, containerType, playerInventory); + } + + private static void updateBlockEntity(GeyserSession session, CrafterContainer container) { + /* + Here is an example of the tag sent by BDS 1.20.50.24 + It doesn't include the position or the block entity ID in the tag, for whatever reason. + + CLIENT BOUND BlockEntityDataPacket(blockPosition=(8, 110, 45), data={ + "crafting_ticks_remaining": 0i, + "disabled_slots": 511s + }) + */ + + NbtMapBuilder tag = NbtMap.builder(); + // just send some large amount since we don't know, and it'll be resent as 0 when java updates as not triggered + tag.putInt("crafting_ticks_remaining", container.isTriggered() ? 10_000 : 0); + tag.putShort("disabled_slots", container.getDisabledSlotsMask()); + + BlockEntityUtils.updateBlockEntity(session, tag.build(), container.getHolderPosition()); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java index 5262f048b..b10fa85f0 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java @@ -86,6 +86,7 @@ public abstract class InventoryTranslator { put(ContainerType.BEACON, new BeaconInventoryTranslator()); put(ContainerType.BREWING_STAND, new BrewingInventoryTranslator()); put(ContainerType.CARTOGRAPHY, new CartographyInventoryTranslator()); + put(ContainerType.CRAFTER_3x3, new CrafterInventoryTranslator()); put(ContainerType.CRAFTING, new CraftingInventoryTranslator()); put(ContainerType.ENCHANTMENT, new EnchantingInventoryTranslator()); put(ContainerType.HOPPER, new HopperInventoryTranslator()); diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DecoratedPotBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DecoratedPotBlockEntityTranslator.java index 9ff864101..1774d9c76 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DecoratedPotBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DecoratedPotBlockEntityTranslator.java @@ -44,7 +44,6 @@ public class DecoratedPotBlockEntityTranslator extends BlockEntityTranslator { if (tag == null) { return; } - // todo 1.20.3 maybe // exact same format if (tag.get("sherds") instanceof ListTag sherds) { diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/TrialSpawnerBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/TrialSpawnerBlockEntityTranslator.java new file mode 100644 index 000000000..93a4daba9 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/TrialSpawnerBlockEntityTranslator.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019-2023 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.translator.level.block.entity; + +import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import org.cloudburstmc.nbt.NbtMapBuilder; + +@BlockEntity(type = BlockEntityType.TRIAL_SPAWNER) +public class TrialSpawnerBlockEntityTranslator extends SpawnerBlockEntityTranslator { + + @Override + public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) { + if (tag != null) { + // todo 1.20.3 doesn't seem to work + super.translateTag(builder, tag, blockState); + } + } +} diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockToggleCrafterSlotRequestTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockToggleCrafterSlotRequestTranslator.java new file mode 100644 index 000000000..5c494cd88 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockToggleCrafterSlotRequestTranslator.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2019-2023 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.translator.protocol.bedrock; + +import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerSlotStateChangedPacket; +import org.cloudburstmc.protocol.bedrock.packet.ToggleCrafterSlotRequestPacket; +import org.geysermc.geyser.inventory.CrafterContainer; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.protocol.PacketTranslator; +import org.geysermc.geyser.translator.protocol.Translator; + +@Translator(packet = ToggleCrafterSlotRequestPacket.class) +public class BedrockToggleCrafterSlotRequestTranslator extends PacketTranslator { + + @Override + public void translate(GeyserSession session, ToggleCrafterSlotRequestPacket packet) { + if (!(session.getOpenInventory() instanceof CrafterContainer container)) { + return; + } + + // Note that the Bedrock packet uses disabled, whereas the java packet used enabled. + session.sendDownstreamGamePacket( + new ServerboundContainerSlotStateChangedPacket(packet.getSlot(), container.getJavaId(), !packet.isDisabled())); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaOpenScreenTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaOpenScreenTranslator.java index 8951f7171..1d0b4bf63 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaOpenScreenTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaOpenScreenTranslator.java @@ -30,7 +30,9 @@ import com.github.steveice10.mc.protocol.packet.ingame.clientbound.inventory.Cli import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClosePacket; import net.kyori.adventure.text.Component; import org.geysermc.geyser.inventory.Inventory; +import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.translator.inventory.InventoryTranslator; import org.geysermc.geyser.translator.inventory.OldSmithingTableTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator; @@ -49,12 +51,18 @@ public class JavaOpenScreenTranslator extends PacketTranslator Date: Wed, 13 Dec 2023 00:48:03 -0500 Subject: [PATCH 153/344] translate trial spawners, cleanup --- .../entity/SpawnerBlockEntityTranslator.java | 40 +++++++++++-------- .../TrialSpawnerBlockEntityTranslator.java | 13 ++++-- .../java/level/JavaBlockEventTranslator.java | 9 ----- .../java/level/JavaGameEventTranslator.java | 8 ++-- gradle/libs.versions.toml | 2 +- 5 files changed, 38 insertions(+), 34 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SpawnerBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SpawnerBlockEntityTranslator.java index 0aa8af279..f2b0f5a78 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SpawnerBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SpawnerBlockEntityTranslator.java @@ -29,6 +29,8 @@ import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; 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 org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; @@ -99,24 +101,28 @@ public class SpawnerBlockEntityTranslator extends BlockEntityTranslator { builder.put("MinSpawnDelay", current.getValue()); } - CompoundTag spawnData = tag.get("SpawnData"); - if (spawnData != null) { - CompoundTag entityTag = spawnData.get("entity"); - if (entityTag.get("id") instanceof StringTag idTag) { - // As of 1.19.3, spawners can be empty - String entityId = idTag.getValue(); - builder.put("EntityIdentifier", entityId); + translateSpawnData(builder, tag.get("SpawnData")); - EntityDefinition definition = Registries.JAVA_ENTITY_IDENTIFIERS.get(entityId); - if (definition != null) { - builder.put("DisplayEntityWidth", definition.width()); - builder.put("DisplayEntityHeight", definition.height()); - builder.put("DisplayEntityScale", 1.0f); - } - } - } - - builder.put("id", "MobSpawner"); builder.put("isMovable", (byte) 1); } + + static void translateSpawnData(@NonNull NbtMapBuilder builder, @Nullable CompoundTag spawnData) { + if (spawnData == null) { + return; + } + + CompoundTag entityTag = spawnData.get("entity"); + if (entityTag.get("id") instanceof StringTag idTag) { + // As of 1.19.3, spawners can be empty + String entityId = idTag.getValue(); + builder.put("EntityIdentifier", entityId); + + EntityDefinition definition = Registries.JAVA_ENTITY_IDENTIFIERS.get(entityId); + if (definition != null) { + builder.put("DisplayEntityWidth", definition.width()); + builder.put("DisplayEntityHeight", definition.height()); + builder.put("DisplayEntityScale", 1.0f); + } + } + } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/TrialSpawnerBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/TrialSpawnerBlockEntityTranslator.java index 93a4daba9..a6a99d868 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/TrialSpawnerBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/TrialSpawnerBlockEntityTranslator.java @@ -30,13 +30,18 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.cloudburstmc.nbt.NbtMapBuilder; @BlockEntity(type = BlockEntityType.TRIAL_SPAWNER) -public class TrialSpawnerBlockEntityTranslator extends SpawnerBlockEntityTranslator { +public class TrialSpawnerBlockEntityTranslator extends BlockEntityTranslator { @Override public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) { - if (tag != null) { - // todo 1.20.3 doesn't seem to work - super.translateTag(builder, tag, blockState); + if (tag == null) { + return; } + + // trial spawners have "spawn_data" instead of "SpawnData" + SpawnerBlockEntityTranslator.translateSpawnData(builder, tag.get("spawn_data")); + + // Because trial spawners don't exist on bedrock yet + builder.put("id", "MobSpawner"); } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEventTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEventTranslator.java index 49c54409b..28fd2401b 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEventTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEventTranslator.java @@ -33,7 +33,6 @@ import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket; import org.cloudburstmc.protocol.bedrock.packet.BlockEventPacket; import it.unimi.dsi.fastutil.objects.Object2IntMaps; -import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.physics.Direction; @@ -128,14 +127,6 @@ public class JavaBlockEventTranslator extends PacketTranslator Date: Thu, 14 Dec 2023 15:22:40 -0500 Subject: [PATCH 154/344] cleanup --- README.md | 2 +- .../main/java/org/geysermc/geyser/network/GameProtocol.java | 4 +++- .../geyser/registry/populator/Conversion630_622.java | 2 +- .../geyser/registry/populator/ItemRegistryPopulator.java | 2 +- .../protocol/java/level/JavaLevelEventTranslator.java | 2 +- .../protocol/java/scoreboard/JavaSetScoreTranslator.java | 5 +++-- 6 files changed, 10 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 1663c493a..bdd8cbe98 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,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.20.40 - 1.20.50 and Minecraft Java 1.20.3 +### Currently supporting Minecraft Bedrock 1.20.40 - 1.20.51 and Minecraft Java 1.20.4 ## 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/GameProtocol.java b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java index c811afd2e..42cce607b 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java @@ -63,7 +63,9 @@ public final class GameProtocol { SUPPORTED_BEDROCK_CODECS.add(Bedrock_v622.CODEC.toBuilder() .minecraftVersion("1.20.40/1.20.41") .build()); - SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC); + SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC.toBuilder() + .minecraftVersion("1.20.50/1.20.51") + .build()); } /** diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion630_622.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion630_622.java index 9404774b8..7c1453dc7 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion630_622.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion630_622.java @@ -37,7 +37,7 @@ import java.util.Map; /** * Backwards-maps the blocks and items of 1.20.50 (630) to 1.20.40 (622) */ -public class Conversion630_622 { +class Conversion630_622 { private static final List NEW_STONES = List.of("minecraft:stone", "minecraft:granite", "minecraft:polished_granite", "minecraft:diorite", "minecraft:polished_diorite", "minecraft:andesite", "minecraft:polished_andesite"); private static final List NEW_WOODS = List.of("minecraft:oak_planks", "minecraft:spruce_planks", "minecraft:birch_planks", "minecraft:jungle_planks", "minecraft:acacia_planks", "minecraft:dark_oak_planks"); 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 74c0432b5..bc2cf4a43 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 @@ -87,7 +87,7 @@ public class ItemRegistryPopulator { public static void populate() { List paletteVersions = new ArrayList<>(3); - paletteVersions.add(new PaletteVersion("1_20_40", Bedrock_v622.CODEC.getProtocolVersion(), Collections.emptyMap(), Conversion630_622::remapItem)); // NO item changes between 1.20.30 and 1.20.40 + paletteVersions.add(new PaletteVersion("1_20_40", Bedrock_v622.CODEC.getProtocolVersion(), Collections.emptyMap(), Conversion630_622::remapItem)); paletteVersions.add(new PaletteVersion("1_20_50", Bedrock_v630.CODEC.getProtocolVersion())); GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap(); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelEventTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelEventTranslator.java index 64d530a1f..843f3d514 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelEventTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelEventTranslator.java @@ -336,7 +336,7 @@ public class JavaLevelEventTranslator extends PacketTranslator { - GeyserImpl.getInstance().getLogger().warning("Unhandled level event: " + packet.getEvent()); + GeyserImpl.getInstance().getLogger().debug("Unhandled level event: " + packet.getEvent()); return; } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaSetScoreTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaSetScoreTranslator.java index 362fb29e8..594e2cbed 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaSetScoreTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaSetScoreTranslator.java @@ -27,6 +27,7 @@ package org.geysermc.geyser.translator.protocol.java.scoreboard; import com.github.steveice10.mc.protocol.data.game.scoreboard.ScoreboardPosition; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetScorePacket; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.packet.SetEntityDataPacket; import org.geysermc.geyser.GeyserImpl; @@ -86,7 +87,7 @@ public class JavaSetScoreTranslator extends PacketTranslator Date: Thu, 14 Dec 2023 16:30:50 -0500 Subject: [PATCH 155/344] fabric: require 1.20.4 as ViaFabric doesn't support 1.20.2 --- bootstrap/fabric/build.gradle.kts | 2 +- gradle/libs.versions.toml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bootstrap/fabric/build.gradle.kts b/bootstrap/fabric/build.gradle.kts index 83d6a48d0..ea1fef2b7 100644 --- a/bootstrap/fabric/build.gradle.kts +++ b/bootstrap/fabric/build.gradle.kts @@ -119,7 +119,7 @@ modrinth { syncBodyFrom.set(rootProject.file("README.md").readText()) uploadFile.set(tasks.getByPath("remapModrinthJar")) - gameVersions.addAll("1.20.3") + gameVersions.addAll("1.20.4") loaders.add("fabric") failSilently.set(true) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4db6a03a2..eb1008cd3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,7 +14,7 @@ protocol-connection = "3.0.0.Beta1-20231107.190703-112" raknet = "1.0.0.CR1-20230703.195238-9" blockstateupdater="1.20.50-20231106.161340-1" mcauthlib = "d9d773e" -mcprotocollib = "7123bf9" +mcprotocollib = "723fbb3" adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" @@ -28,9 +28,9 @@ adapters = "1.10-SNAPSHOT" commodore = "2.2" bungeecord = "a7c6ede" velocity = "3.1.1" -fabric-minecraft = "1.20.2" -fabric-loader = "0.14.21" -fabric-api = "0.89.0+1.20.2" +fabric-minecraft = "1.20.4" +fabric-loader = "0.15.2" +fabric-api = "0.91.2+1.20.4" [libraries] base-api = { group = "org.geysermc.api", name = "base-api", version.ref = "base-api" } From a13492e0ed4434670d6be354b7fb25340a5b18d3 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Thu, 14 Dec 2023 17:08:34 -0500 Subject: [PATCH 156/344] Final 1.20.4 cleanup --- .../geyser/platform/bungeecord/GeyserBungeePlugin.java | 2 +- bootstrap/fabric/src/main/resources/fabric.mod.json | 4 ++-- .../geyser/translator/inventory/InventoryTranslator.java | 2 +- core/src/main/resources/mappings | 2 +- gradle/libs.versions.toml | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java index c4eea66b8..c5d5cdacc 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java @@ -80,7 +80,7 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { // Copied from ViaVersion. // https://github.com/ViaVersion/ViaVersion/blob/b8072aad86695cc8ec6f5e4103e43baf3abf6cc5/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java#L43 try { - ProtocolConstants.class.getField("MINECRAFT_1_20_2"); + ProtocolConstants.class.getField("MINECRAFT_1_20_3"); } catch (NoSuchFieldException e) { getLogger().warning(" / \\"); getLogger().warning(" / \\"); diff --git a/bootstrap/fabric/src/main/resources/fabric.mod.json b/bootstrap/fabric/src/main/resources/fabric.mod.json index f401e8f23..a192109e2 100644 --- a/bootstrap/fabric/src/main/resources/fabric.mod.json +++ b/bootstrap/fabric/src/main/resources/fabric.mod.json @@ -23,9 +23,9 @@ "geyser-fabric.mixins.json" ], "depends": { - "fabricloader": ">=0.14.21", + "fabricloader": ">=0.15.2", "fabric": "*", - "minecraft": ">=1.20.2", + "minecraft": ">=1.20.4", "fabric-permissions-api-v0": "*" } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java index b10fa85f0..95ec99412 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java @@ -86,7 +86,7 @@ public abstract class InventoryTranslator { put(ContainerType.BEACON, new BeaconInventoryTranslator()); put(ContainerType.BREWING_STAND, new BrewingInventoryTranslator()); put(ContainerType.CARTOGRAPHY, new CartographyInventoryTranslator()); - put(ContainerType.CRAFTER_3x3, new CrafterInventoryTranslator()); + //put(ContainerType.CRAFTER_3x3, new CrafterInventoryTranslator()); todo Output slot is currently broken put(ContainerType.CRAFTING, new CraftingInventoryTranslator()); put(ContainerType.ENCHANTMENT, new EnchantingInventoryTranslator()); put(ContainerType.HOPPER, new HopperInventoryTranslator()); diff --git a/core/src/main/resources/mappings b/core/src/main/resources/mappings index 2393a6555..522967d6e 160000 --- a/core/src/main/resources/mappings +++ b/core/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit 2393a655595abd8e0b93e88553d9d8d7cdbde95b +Subproject commit 522967d6ee76972994ad05a992dc9d7bb4e889ba diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index eb1008cd3..71d416f72 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,7 +14,7 @@ protocol-connection = "3.0.0.Beta1-20231107.190703-112" raknet = "1.0.0.CR1-20230703.195238-9" blockstateupdater="1.20.50-20231106.161340-1" mcauthlib = "d9d773e" -mcprotocollib = "723fbb3" +mcprotocollib = "1.20.4-1-20231214.212857-1" adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" @@ -87,7 +87,7 @@ guava = { group = "com.google.guava", name = "guava", version.ref = "guava" } gson = { group = "com.google.code.gson", name = "gson", version.ref = "gson" } junit = { group = "org.junit.jupiter", name = "junit-jupiter", version.ref = "junit" } mcauthlib = { group = "com.github.GeyserMC", name = "MCAuthLib", version.ref = "mcauthlib" } -mcprotocollib = { group = "com.github.GeyserMC", name = "MCProtocolLib", version.ref = "mcprotocollib" } +mcprotocollib = { group = "com.github.steveice10", name = "mcprotocollib", version.ref = "mcprotocollib" } raknet = { group = "org.cloudburstmc.netty", name = "netty-transport-raknet", version.ref = "raknet" } terminalconsoleappender = { group = "net.minecrell", name = "terminalconsoleappender", version.ref = "terminalconsoleappender" } velocity-api = { group = "com.velocitypowered", name = "velocity-api", version.ref = "velocity" } From aaf38f46fb32c4aaf984b535d5dcc593bdab7390 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Thu, 14 Dec 2023 17:47:00 -0800 Subject: [PATCH 157/344] Target Java 17 --- bootstrap/fabric/build.gradle.kts | 6 ------ .../src/main/kotlin/geyser.base-conventions.gradle.kts | 2 +- build.gradle.kts | 2 +- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/bootstrap/fabric/build.gradle.kts b/bootstrap/fabric/build.gradle.kts index ea1fef2b7..66af130b3 100644 --- a/bootstrap/fabric/build.gradle.kts +++ b/bootstrap/fabric/build.gradle.kts @@ -5,12 +5,6 @@ plugins { id("com.modrinth.minotaur") version "2.+" } -indra { - javaVersions { - target(17) - } -} - dependencies { //to change the versions see the gradle.properties file minecraft(libs.fabric.minecraft) diff --git a/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts b/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts index 95d4d5409..01c769733 100644 --- a/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts @@ -16,7 +16,7 @@ indra { mitLicense() javaVersions { - target(16) + target(17) } } diff --git a/build.gradle.kts b/build.gradle.kts index d7360b701..a72b8a484 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -14,7 +14,7 @@ allprojects { java { toolchain { - languageVersion.set(JavaLanguageVersion.of(16)) + languageVersion.set(JavaLanguageVersion.of(17)) } } From 6e56666be2dec365125e5a1eca76aa26efec6ee0 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Fri, 15 Dec 2023 00:31:51 -0500 Subject: [PATCH 158/344] Update spigot adapters to include 1.20.4 (#4340) --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 71d416f72..0974f7b81 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -24,7 +24,7 @@ jline = "3.21.0" terminalconsoleappender = "1.2.0" folia = "1.19.4-R0.1-SNAPSHOT" viaversion = "4.0.0" -adapters = "1.10-SNAPSHOT" +adapters = "1.11-SNAPSHOT" commodore = "2.2" bungeecord = "a7c6ede" velocity = "3.1.1" From 58ff00db961641164411564fe1c6d9406750f991 Mon Sep 17 00:00:00 2001 From: Tim203 Date: Sat, 16 Dec 2023 23:42:59 +0100 Subject: [PATCH 159/344] Fixed an issue where there would be a null score in SetScorePacket --- .../java/org/geysermc/geyser/scoreboard/Scoreboard.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/scoreboard/Scoreboard.java b/core/src/main/java/org/geysermc/geyser/scoreboard/Scoreboard.java index 1e0ea5eb1..216370bde 100644 --- a/core/src/main/java/org/geysermc/geyser/scoreboard/Scoreboard.java +++ b/core/src/main/java/org/geysermc/geyser/scoreboard/Scoreboard.java @@ -258,7 +258,12 @@ public final class Scoreboard { for (Score score : objective.getScores().values()) { if (score.getUpdateType() == REMOVE) { - removeScores.add(score.getCachedInfo()); + ScoreInfo cachedInfo = score.getCachedInfo(); + // cachedInfo can be null here when ScoreboardUpdater is being used and a score is added and + // removed before a single update cycle is performed + if (cachedInfo != null) { + removeScores.add(cachedInfo); + } // score is pending to be removed, so we can remove it from the objective objective.removeScore0(score.getName()); break; From af83e9269d7a4a166f3d682419259da549a7c194 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Tue, 19 Dec 2023 02:57:34 -0500 Subject: [PATCH 160/344] Fix (de)serialization of ClientboundExplodePacket (#4351) --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0974f7b81..dd4c133ad 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,7 +14,7 @@ protocol-connection = "3.0.0.Beta1-20231107.190703-112" raknet = "1.0.0.CR1-20230703.195238-9" blockstateupdater="1.20.50-20231106.161340-1" mcauthlib = "d9d773e" -mcprotocollib = "1.20.4-1-20231214.212857-1" +mcprotocollib = "1.20.4-2-20231219.074138-2" adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" From f3e56d282ebcb4fa298a8cb2c3696ee013d1a9d5 Mon Sep 17 00:00:00 2001 From: chris Date: Wed, 20 Dec 2023 16:35:48 +0100 Subject: [PATCH 161/344] Gracefully fail on older spigot builds due to outdated netty (#4355) * Test for outdated netty to avoid https://github.com/GeyserMC/Geyser/issues/3814 * capitalization * bad spigot, go paper --- .../geyser/platform/spigot/GeyserSpigotPlugin.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java index 02ea91cf2..62a1e3f02 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java @@ -135,6 +135,17 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { } } + try { + Class.forName("io.netty.util.internal.ObjectPool.ObjectCreator"); + } catch (ClassNotFoundException e) { + getLogger().severe("*********************************************"); + getLogger().severe(""); + getLogger().severe("This version of Spigot is using an outdated version of netty. Please use Paper instead!"); + getLogger().severe(""); + getLogger().severe("*********************************************"); + return; + } + // This is manually done instead of using Bukkit methods to save the config because otherwise comments get removed try { if (!getDataFolder().exists()) { From 32a8573651c3d600ab05e21c1f92a4cea6899e4e Mon Sep 17 00:00:00 2001 From: chris Date: Wed, 20 Dec 2023 17:59:51 +0100 Subject: [PATCH 162/344] Fix broken netty util class check (#4357) --- .../org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java index 62a1e3f02..a2a08c3bf 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java @@ -136,7 +136,7 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { } try { - Class.forName("io.netty.util.internal.ObjectPool.ObjectCreator"); + Class.forName("io.netty.util.internal.ObjectPool$ObjectCreator"); } catch (ClassNotFoundException e) { getLogger().severe("*********************************************"); getLogger().severe(""); From cdb8ab344cfda20a37994d5dd59cf692cdd786d4 Mon Sep 17 00:00:00 2001 From: chris Date: Wed, 20 Dec 2023 23:48:51 +0100 Subject: [PATCH 163/344] bump cloudburst/netty dependencies (#4354) * bump cloudburst's netty-transport-raknet * bump cloudburst protocol/codec/connection bump bump netty due CVE-2022-41881 Changes in cloudburst libs: - uses netty 4.1.101.Final - bumps netty-transport-raknet which fixes https://github.com/CloudburstMC/Network/pull/36, an issue where some connection attempts did not work --- gradle/libs.versions.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index dd4c133ad..c71aa715f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -5,13 +5,13 @@ erosion = "1.0-20230406.174837-8" events = "1.1-SNAPSHOT" jackson = { strictly = "2.14.0" } # Don't let other dependencies override fastutil = "8.5.2" -netty = "4.1.80.Final" +netty = "4.1.103.Final" guava = "29.0-jre" gson = "2.3.1" # Provided by Spigot 1.8.8 websocket = "1.5.1" -protocol = "3.0.0.Beta1-20231107.190703-113" -protocol-connection = "3.0.0.Beta1-20231107.190703-112" -raknet = "1.0.0.CR1-20230703.195238-9" +protocol = "3.0.0.Beta1-20231206.150507-114" +protocol-connection = "3.0.0.Beta1-20231206.150507-113" +raknet = "1.0.0.CR1-20231206.145325-12" blockstateupdater="1.20.50-20231106.161340-1" mcauthlib = "d9d773e" mcprotocollib = "1.20.4-2-20231219.074138-2" From b0ccf45cd47f797eca2f62e5716170bc80074b86 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Sat, 23 Dec 2023 18:06:06 -0800 Subject: [PATCH 164/344] Closes GeyserMC/Geyser#4358 (#4360) Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .../geyser/level/block/BlockStateValues.java | 15 +++++++++++++++ .../java/org/geysermc/geyser/util/ChunkUtils.java | 8 ++++++++ 2 files changed, 23 insertions(+) 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 11702e78a..e665a22ef 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 @@ -67,6 +67,7 @@ public final class BlockStateValues { private static final Int2IntMap SKULL_WALL_DIRECTIONS = new Int2IntOpenHashMap(); private static final Int2ByteMap SHULKERBOX_DIRECTIONS = new FixedInt2ByteMap(); private static final Int2IntMap WATER_LEVEL = new Int2IntOpenHashMap(); + private static final IntSet UPPER_DOORS = new IntOpenHashSet(); public static final int JAVA_AIR_ID = 0; @@ -219,6 +220,10 @@ public final class BlockStateValues { if (javaId.contains("_cauldron") && !javaId.contains("water_")) { NON_WATER_CAULDRONS.add(javaBlockState); } + + if (javaId.contains("_door[") && javaId.contains("half=upper")) { + UPPER_DOORS.add(javaBlockState); + } } /** @@ -498,6 +503,16 @@ public final class BlockStateValues { return WATER_LEVEL.getOrDefault(state, -1); } + /** + * Check if a block is the upper half of a door. + * + * @param state BlockState of the block + * @return True if the block is the upper half of a door + */ + public static boolean isUpperDoor(int state) { + return UPPER_DOORS.contains(state); + } + /** * Get the height of water from the block state * This is used in FishingHookEntity to create splash sounds when the hook hits the water. In addition, diff --git a/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java b/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java index 114a7b6de..cc21e2d0a 100644 --- a/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java @@ -215,6 +215,14 @@ public class ChunkUtils { break; //No block will be a part of two classes } } + + if (BlockStateValues.isUpperDoor(blockState)) { + // Update the lower door block as Bedrock client doesn't like door to be closed from the top + // See https://github.com/GeyserMC/Geyser/issues/4358 + Vector3i belowDoorPosition = position.sub(0, 1, 0); + int belowDoorBlockState = session.getGeyser().getWorldManager().getBlockAt(session, belowDoorPosition.getX(), belowDoorPosition.getY(), belowDoorPosition.getZ()); + updateBlock(session, belowDoorBlockState, belowDoorPosition); + } } public static void sendEmptyChunk(GeyserSession session, int chunkX, int chunkZ, boolean forceUpdate) { From 592a58a0c87bf0054610f5a7ec996e65f1c0c402 Mon Sep 17 00:00:00 2001 From: chris Date: Mon, 25 Dec 2023 20:43:13 +0100 Subject: [PATCH 165/344] Use uuid for bukkit api permission checks (#4363) * lookup players by uuid instead of name * Fix: look up Players by UUID for permissions, dont throw if a player can't be found (e.g. disconnected) * use api method --- .../spigot/world/manager/GeyserSpigotWorldManager.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java index 74f359e02..42f0d17f4 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java @@ -197,7 +197,11 @@ public class GeyserSpigotWorldManager extends WorldManager { @Override public boolean hasPermission(GeyserSession session, String permission) { - return Objects.requireNonNull(Bukkit.getPlayer(session.getPlayerEntity().getUsername())).hasPermission(permission); + Player player = Bukkit.getPlayer(session.javaUuid()); + if (player != null) { + return player.hasPermission(permission); + } + return false; } @Override From 46bde0c01955cddc5b0da547f76629583f568ca4 Mon Sep 17 00:00:00 2001 From: chris Date: Sun, 31 Dec 2023 02:24:44 +0100 Subject: [PATCH 166/344] Fix: protocol being null during online mode login (#4369) * fix: protocol being null during online mode login * gimme more space * add debug logging for too early downstream packet sending --- .../java/org/geysermc/geyser/session/GeyserSession.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 28ad5887c..26e206458 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -1633,6 +1633,15 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { * @param intendedState the state the client should be in */ public void sendDownstreamPacket(Packet packet, ProtocolState intendedState) { + // protocol can be null when we're not yet logged in (online auth) + if (protocol == null) { + if (geyser.getConfig().isDebugMode()) { + geyser.getLogger().debug("Tried to send downstream packet with no downstream session!"); + Thread.dumpStack(); + } + return; + } + if (protocol.getState() != intendedState) { geyser.getLogger().debug("Tried to send " + packet.getClass().getSimpleName() + " packet while not in " + intendedState.name() + " state"); return; From 7613bdbafe402f86ec8f1bd7a446b2a1d6b86305 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Thu, 4 Jan 2024 13:49:01 -0500 Subject: [PATCH 167/344] Fix https://github.com/GeyserMC/Geyser/issues/4378 --- .../org/geysermc/geyser/network/UpstreamPacketHandler.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java index a0b104adb..7a22b8a42 100644 --- a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java +++ b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java @@ -28,6 +28,8 @@ package org.geysermc.geyser.network; import io.netty.buffer.Unpooled; import org.cloudburstmc.protocol.bedrock.BedrockDisconnectReasons; import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; +import org.cloudburstmc.protocol.bedrock.codec.compat.BedrockCompat; +import org.cloudburstmc.protocol.bedrock.codec.v622.Bedrock_v622; import org.cloudburstmc.protocol.bedrock.data.ExperimentData; import org.cloudburstmc.protocol.bedrock.data.PacketCompressionAlgorithm; import org.cloudburstmc.protocol.bedrock.data.ResourcePackType; @@ -108,6 +110,10 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { session.disconnect(disconnectMessage); return false; } else if (protocolVersion < GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()) { + if (protocolVersion < Bedrock_v622.CODEC.getProtocolVersion()) { + // https://github.com/GeyserMC/Geyser/issues/4378 + session.getUpstream().getSession().setCodec(BedrockCompat.CODEC_LEGACY); + } session.disconnect(GeyserLocale.getLocaleStringLog("geyser.network.outdated.client", supportedVersions)); return false; } else { From 3288f422b19d1eb65cbca8b36f8eb6aa4db8f582 Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 12 Jan 2024 15:39:53 +0100 Subject: [PATCH 168/344] Update ViaVersion api usage (#4386) - Switch to fluent accessor, since the getter was removed after being deprecated for 3 years --- .../geysermc/geyser/platform/spigot/GeyserSpigotInjector.java | 2 +- gradle/libs.versions.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java index 01bc0bea4..ad31131bd 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java @@ -150,7 +150,7 @@ public class GeyserSpigotInjector extends GeyserInjector { childHandler = (ChannelInitializer) childHandlerField.get(handler); // ViaVersion non-Paper-injector workaround so we aren't double-injecting if (isViaVersion && childHandler instanceof BukkitChannelInitializer) { - childHandler = ((BukkitChannelInitializer) childHandler).getOriginal(); + childHandler = ((BukkitChannelInitializer) childHandler).original(); } break; } catch (Exception e) { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c71aa715f..9e6eeca1d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -23,7 +23,7 @@ log4j = "2.20.0" jline = "3.21.0" terminalconsoleappender = "1.2.0" folia = "1.19.4-R0.1-SNAPSHOT" -viaversion = "4.0.0" +viaversion = "4.9.2" adapters = "1.11-SNAPSHOT" commodore = "2.2" bungeecord = "a7c6ede" From 710dbfc1c87253779becc1551601be651612494e Mon Sep 17 00:00:00 2001 From: chris Date: Wed, 17 Jan 2024 18:38:48 +0100 Subject: [PATCH 169/344] Bump mcpl to re-allow invalid block entity types (#4398) --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9e6eeca1d..72e34e2c8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,7 +14,7 @@ protocol-connection = "3.0.0.Beta1-20231206.150507-113" raknet = "1.0.0.CR1-20231206.145325-12" blockstateupdater="1.20.50-20231106.161340-1" mcauthlib = "d9d773e" -mcprotocollib = "1.20.4-2-20231219.074138-2" +mcprotocollib = "1.20.4-2-20240116.220521-7" adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" From 509e00c138a52d616b8fe11917a2ff42cca2e08b Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 19 Jan 2024 00:19:07 +0100 Subject: [PATCH 170/344] Fix: Geyser on Velocity after they renamed packet class names :/ (#4399) --- .../velocity/GeyserVelocityCompressionDisabler.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityCompressionDisabler.java b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityCompressionDisabler.java index e787e7355..99c759767 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityCompressionDisabler.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityCompressionDisabler.java @@ -47,8 +47,14 @@ public class GeyserVelocityCompressionDisabler extends ChannelDuplexHandler { Method setCompressionMethod = null; try { - compressionPacketClass = Class.forName("com.velocitypowered.proxy.protocol.packet.SetCompression"); - loginSuccessPacketClass = Class.forName("com.velocitypowered.proxy.protocol.packet.ServerLoginSuccess"); + try { + compressionPacketClass = Class.forName("com.velocitypowered.proxy.protocol.packet.SetCompressionPacket"); + loginSuccessPacketClass = Class.forName("com.velocitypowered.proxy.protocol.packet.ServerLoginSuccessPacket"); + } catch (Exception ignored) { + // Velocity renamed packet classes in https://github.com/PaperMC/Velocity/commit/2ac8751337befd04f4663575f5d752c748384110 + compressionPacketClass = Class.forName("com.velocitypowered.proxy.protocol.packet.SetCompression"); + loginSuccessPacketClass = Class.forName("com.velocitypowered.proxy.protocol.packet.ServerLoginSuccess"); + } compressionEnabledEvent = Class.forName("com.velocitypowered.proxy.protocol.VelocityConnectionEvent") .getDeclaredField("COMPRESSION_ENABLED").get(null); setCompressionMethod = Class.forName("com.velocitypowered.proxy.connection.MinecraftConnection") From 16f9f0d94f98b52676f992cfbcb8db48a7808aa1 Mon Sep 17 00:00:00 2001 From: chris Date: Sat, 20 Jan 2024 12:03:32 +0100 Subject: [PATCH 171/344] Don't try to show the server settings form to players who are not logged in (#4387) * Don't show the server settings form to players who are not yet logged in * Add brackets to if statement --- .../bedrock/BedrockServerSettingsRequestTranslator.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockServerSettingsRequestTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockServerSettingsRequestTranslator.java index fb02d7e3e..aa7a2e40f 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockServerSettingsRequestTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockServerSettingsRequestTranslator.java @@ -42,6 +42,11 @@ public class BedrockServerSettingsRequestTranslator extends PacketTranslator Date: Mon, 22 Jan 2024 19:21:12 +0100 Subject: [PATCH 172/344] Gracefully handle invalid stone cutter recipes (#4406) * Gracefully handle invalid stone cutter recipes Further various little fixes: - bump source version in AP to 17 to silence build log spam - remove unneeded close() on auto-closable resource --- .../geysermc/geyser/processor/BlockEntityProcessor.java | 2 +- .../geyser/processor/CollisionRemapperProcessor.java | 2 +- .../geyser/processor/PacketTranslatorProcessor.java | 2 +- .../geysermc/geyser/processor/SoundHandlerProcessor.java | 2 +- .../java/org/geysermc/geyser/text/MinecraftLocale.java | 1 - .../protocol/java/JavaUpdateRecipesTranslator.java | 7 +++++++ 6 files changed, 11 insertions(+), 5 deletions(-) diff --git a/ap/src/main/java/org/geysermc/geyser/processor/BlockEntityProcessor.java b/ap/src/main/java/org/geysermc/geyser/processor/BlockEntityProcessor.java index f9ba68302..ccdaeda4e 100644 --- a/ap/src/main/java/org/geysermc/geyser/processor/BlockEntityProcessor.java +++ b/ap/src/main/java/org/geysermc/geyser/processor/BlockEntityProcessor.java @@ -30,7 +30,7 @@ import javax.annotation.processing.SupportedSourceVersion; import javax.lang.model.SourceVersion; @SupportedAnnotationTypes("*") -@SupportedSourceVersion(SourceVersion.RELEASE_16) +@SupportedSourceVersion(SourceVersion.RELEASE_17) public class BlockEntityProcessor extends ClassProcessor { public BlockEntityProcessor() { super("org.geysermc.geyser.translator.level.block.entity.BlockEntity"); diff --git a/ap/src/main/java/org/geysermc/geyser/processor/CollisionRemapperProcessor.java b/ap/src/main/java/org/geysermc/geyser/processor/CollisionRemapperProcessor.java index 84e2e2ffd..30d94b7f5 100644 --- a/ap/src/main/java/org/geysermc/geyser/processor/CollisionRemapperProcessor.java +++ b/ap/src/main/java/org/geysermc/geyser/processor/CollisionRemapperProcessor.java @@ -30,7 +30,7 @@ import javax.annotation.processing.SupportedSourceVersion; import javax.lang.model.SourceVersion; @SupportedAnnotationTypes("*") -@SupportedSourceVersion(SourceVersion.RELEASE_16) +@SupportedSourceVersion(SourceVersion.RELEASE_17) public class CollisionRemapperProcessor extends ClassProcessor { public CollisionRemapperProcessor() { super("org.geysermc.geyser.translator.collision.CollisionRemapper"); diff --git a/ap/src/main/java/org/geysermc/geyser/processor/PacketTranslatorProcessor.java b/ap/src/main/java/org/geysermc/geyser/processor/PacketTranslatorProcessor.java index 9b99d679b..d538a9ca1 100644 --- a/ap/src/main/java/org/geysermc/geyser/processor/PacketTranslatorProcessor.java +++ b/ap/src/main/java/org/geysermc/geyser/processor/PacketTranslatorProcessor.java @@ -30,7 +30,7 @@ import javax.annotation.processing.SupportedSourceVersion; import javax.lang.model.SourceVersion; @SupportedAnnotationTypes("*") -@SupportedSourceVersion(SourceVersion.RELEASE_16) +@SupportedSourceVersion(SourceVersion.RELEASE_17) public class PacketTranslatorProcessor extends ClassProcessor { public PacketTranslatorProcessor() { super("org.geysermc.geyser.translator.protocol.Translator"); diff --git a/ap/src/main/java/org/geysermc/geyser/processor/SoundHandlerProcessor.java b/ap/src/main/java/org/geysermc/geyser/processor/SoundHandlerProcessor.java index c35c0ee4e..30ceef2c6 100644 --- a/ap/src/main/java/org/geysermc/geyser/processor/SoundHandlerProcessor.java +++ b/ap/src/main/java/org/geysermc/geyser/processor/SoundHandlerProcessor.java @@ -30,7 +30,7 @@ import javax.annotation.processing.SupportedSourceVersion; import javax.lang.model.SourceVersion; @SupportedAnnotationTypes("*") -@SupportedSourceVersion(SourceVersion.RELEASE_16) +@SupportedSourceVersion(SourceVersion.RELEASE_17) public class SoundHandlerProcessor extends ClassProcessor { public SoundHandlerProcessor() { super("org.geysermc.geyser.translator.sound.SoundTranslator"); diff --git a/core/src/main/java/org/geysermc/geyser/text/MinecraftLocale.java b/core/src/main/java/org/geysermc/geyser/text/MinecraftLocale.java index f6e37787d..692a05110 100644 --- a/core/src/main/java/org/geysermc/geyser/text/MinecraftLocale.java +++ b/core/src/main/java/org/geysermc/geyser/text/MinecraftLocale.java @@ -196,7 +196,6 @@ public class MinecraftLocale { Map.Entry entry = localeIterator.next(); langMap.put(entry.getKey(), entry.getValue().asText()); } - localeStream.close(); return langMap; } catch (FileNotFoundException e){ throw new AssertionError(GeyserLocale.getLocaleStringLog("geyser.locale.fail.file", locale, e.getMessage())); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java index 344e06c96..7beb37af9 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java @@ -169,6 +169,13 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator { StoneCuttingRecipeData stoneCuttingData = (StoneCuttingRecipeData) recipe.getData(); + if (stoneCuttingData.getIngredient().getOptions().length == 0) { + if (GeyserImpl.getInstance().getConfig().isDebugMode()) { + GeyserImpl.getInstance().getLogger().debug("Received broken stone cutter recipe: " + stoneCuttingData + " " + + recipe.getIdentifier() + " " + Registries.JAVA_ITEMS.get().get(stoneCuttingData.getResult().getId()).javaIdentifier()); + } + continue; + } ItemStack ingredient = stoneCuttingData.getIngredient().getOptions()[0]; List data = unsortedStonecutterData.get(ingredient.getId()); if (data == null) { From 7bcecdf40376044f2dc021683716e81d31e1217c Mon Sep 17 00:00:00 2001 From: chris Date: Tue, 23 Jan 2024 00:34:53 +0100 Subject: [PATCH 173/344] Fix: Opening inventory menus in spectator mode (#4407) Revert to spectator_viewer instead of the native Bedrock spectator menu. While it looks uglier - e.g. it's showing health/hunger bars; it allows opening menus. It'll also be needed for entity spectating, since clicking on things isnt possible in bedrocks spectator mode --- core/src/main/java/org/geysermc/geyser/util/EntityUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/util/EntityUtils.java b/core/src/main/java/org/geysermc/geyser/util/EntityUtils.java index 68753c009..583e15c23 100644 --- a/core/src/main/java/org/geysermc/geyser/util/EntityUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/EntityUtils.java @@ -270,7 +270,7 @@ public final class EntityUtils { return switch (gamemode) { case CREATIVE -> GameType.CREATIVE; case ADVENTURE -> GameType.ADVENTURE; - case SPECTATOR -> GameType.SPECTATOR; + case SPECTATOR -> GameType.SURVIVAL_VIEWER; default -> GameType.SURVIVAL; }; } From 97ba6a25e6c34a4825e50bdd76636fbfad2a9c86 Mon Sep 17 00:00:00 2001 From: chris Date: Wed, 24 Jan 2024 21:18:09 +0100 Subject: [PATCH 174/344] Don't warn if clients send subchunkrequest packets (#4395) --- .../org/geysermc/geyser/network/LoggingPacketHandler.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/src/main/java/org/geysermc/geyser/network/LoggingPacketHandler.java b/core/src/main/java/org/geysermc/geyser/network/LoggingPacketHandler.java index 5076dbeb2..cf794261b 100644 --- a/core/src/main/java/org/geysermc/geyser/network/LoggingPacketHandler.java +++ b/core/src/main/java/org/geysermc/geyser/network/LoggingPacketHandler.java @@ -285,6 +285,11 @@ public class LoggingPacketHandler implements BedrockPacketHandler { return defaultHandler(packet); } + @Override + public PacketSignal handle(SubChunkRequestPacket packet) { + return defaultHandler(packet); + } + @Override public PacketSignal handle(SubClientLoginPacket packet) { return defaultHandler(packet); From 3f577f41281618b23e022ba8ed727ce9d41c3d8e Mon Sep 17 00:00:00 2001 From: rtm516 Date: Wed, 24 Jan 2024 21:20:30 +0000 Subject: [PATCH 175/344] Add fetching MC versions and Console from the extensions API (#4168) * Add fetching MC versions and Console from the extensions API * Address reviews, expose custom MinecraftVersion interface * Rename of McVersion -> MinecraftVersionImpl; proper nonnull annotation * fluent consoleCommandSource(), change MinecraftVersion#name() to versionString() * Javadocs adjustments * Create impl package and move `MinecraftVersionImpl` there * api version bump --------- Co-authored-by: onebeastchris --- .../org/geysermc/geyser/api/GeyserApi.java | 26 ++++++++++ .../geyser/api/util/MinecraftVersion.java | 49 +++++++++++++++++++ .../java/org/geysermc/geyser/GeyserImpl.java | 30 ++++++++++-- .../geyser/impl/MinecraftVersionImpl.java | 31 ++++++++++++ gradle.properties | 2 +- 5 files changed, 134 insertions(+), 4 deletions(-) create mode 100644 api/src/main/java/org/geysermc/geyser/api/util/MinecraftVersion.java create mode 100644 core/src/main/java/org/geysermc/geyser/impl/MinecraftVersionImpl.java diff --git a/api/src/main/java/org/geysermc/geyser/api/GeyserApi.java b/api/src/main/java/org/geysermc/geyser/api/GeyserApi.java index 0d6007c1c..a9327d0db 100644 --- a/api/src/main/java/org/geysermc/geyser/api/GeyserApi.java +++ b/api/src/main/java/org/geysermc/geyser/api/GeyserApi.java @@ -29,12 +29,14 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.api.Geyser; import org.geysermc.api.GeyserApiBase; +import org.geysermc.geyser.api.command.CommandSource; import org.geysermc.geyser.api.connection.GeyserConnection; import org.geysermc.geyser.api.event.EventBus; import org.geysermc.geyser.api.event.EventRegistrar; import org.geysermc.geyser.api.extension.ExtensionManager; import org.geysermc.geyser.api.network.BedrockListener; import org.geysermc.geyser.api.network.RemoteServer; +import org.geysermc.geyser.api.util.MinecraftVersion; import org.geysermc.geyser.api.util.PlatformType; import java.nio.file.Path; @@ -134,6 +136,30 @@ public interface GeyserApi extends GeyserApiBase { @NonNull PlatformType platformType(); + /** + * Gets the version of Java Minecraft that is supported. + * + * @return the supported version of Java Minecraft + */ + @NonNull + MinecraftVersion supportedJavaVersion(); + + /** + * Gets a list of Bedrock Minecraft versions that are supported. + * + * @return the list of supported Bedrock Minecraft versions + */ + @NonNull + List supportedBedrockVersions(); + + /** + * Gets the {@link CommandSource} for the console. + * + * @return the console command source + */ + @NonNull + CommandSource consoleCommandSource(); + /** * Gets the current {@link GeyserApiBase} instance. * diff --git a/api/src/main/java/org/geysermc/geyser/api/util/MinecraftVersion.java b/api/src/main/java/org/geysermc/geyser/api/util/MinecraftVersion.java new file mode 100644 index 000000000..34a4b59af --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/util/MinecraftVersion.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2019-2023 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.api.util; + +import org.checkerframework.checker.nullness.qual.NonNull; + +/** + * Represents a Minecraft version. + */ +public interface MinecraftVersion { + + /** + * Gets the Minecraft version as a String. + * Example: "1.20.2", or "1.20.40/1.20.41" + * + * @return the version string + */ + @NonNull String versionString(); + + /** + * Gets the protocol version of this Minecraft version. + * + * @return the protocol version + */ + int protocolVersion(); +} diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index aef2288d6..13212b161 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -42,7 +42,11 @@ import net.kyori.adventure.text.format.NamedTextColor; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; +import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; import org.geysermc.api.Geyser; +import org.geysermc.geyser.api.command.CommandSource; +import org.geysermc.geyser.api.util.MinecraftVersion; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.cumulus.form.Form; import org.geysermc.cumulus.form.util.FormBuilder; import org.geysermc.erosion.packet.Packets; @@ -60,14 +64,15 @@ import org.geysermc.geyser.api.event.lifecycle.GeyserShutdownEvent; import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.api.network.BedrockListener; import org.geysermc.geyser.api.network.RemoteServer; -import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.command.GeyserCommandManager; import org.geysermc.geyser.configuration.GeyserConfiguration; import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.erosion.UnixSocketClientListener; import org.geysermc.geyser.event.GeyserEventBus; import org.geysermc.geyser.extension.GeyserExtensionManager; +import org.geysermc.geyser.impl.MinecraftVersionImpl; import org.geysermc.geyser.level.WorldManager; +import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.network.netty.GeyserServer; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.Registries; @@ -111,8 +116,8 @@ public class GeyserImpl implements GeyserApi { .enable(JsonParser.Feature.ALLOW_SINGLE_QUOTES); public static final String NAME = "Geyser"; - public static final String GIT_VERSION = "${gitVersion}"; // A fallback for running in IDEs - public static final String VERSION = "${version}"; // A fallback for running in IDEs + public static final String GIT_VERSION = "${gitVersion}"; + public static final String VERSION = "${version}"; public static final String BUILD_NUMBER = "${buildNumber}"; public static final String BRANCH = "${branch}"; @@ -683,6 +688,25 @@ public class GeyserImpl implements GeyserApi { return platformType; } + @Override + public @NonNull MinecraftVersion supportedJavaVersion() { + return new MinecraftVersionImpl(GameProtocol.getJavaMinecraftVersion(), GameProtocol.getJavaProtocolVersion()); + } + + @Override + public @NonNull List supportedBedrockVersions() { + ArrayList versions = new ArrayList<>(); + for (BedrockCodec codec : GameProtocol.SUPPORTED_BEDROCK_CODECS) { + versions.add(new MinecraftVersionImpl(codec.getMinecraftVersion(), codec.getProtocolVersion())); + } + return Collections.unmodifiableList(versions); + } + + @Override + public @NonNull CommandSource consoleCommandSource() { + return getLogger(); + } + public int buildNumber() { if (!this.isProductionEnvironment()) { return 0; diff --git a/core/src/main/java/org/geysermc/geyser/impl/MinecraftVersionImpl.java b/core/src/main/java/org/geysermc/geyser/impl/MinecraftVersionImpl.java new file mode 100644 index 000000000..121d33c64 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/impl/MinecraftVersionImpl.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019-2024 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.impl; + +import org.geysermc.geyser.api.util.MinecraftVersion; + +public record MinecraftVersionImpl(String versionString, int protocolVersion) implements MinecraftVersion { +} diff --git a/gradle.properties b/gradle.properties index b6425f76d..93db310ff 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,5 +7,5 @@ org.gradle.vfs.watch=false group=org.geysermc id=geyser -version=2.2.0-SNAPSHOT +version=2.2.1-SNAPSHOT description=Allows for players from Minecraft: Bedrock Edition to join Minecraft: Java Edition servers. \ No newline at end of file From 61b3ffd0deaa1d5183965aee774b8f14be1c6424 Mon Sep 17 00:00:00 2001 From: chris Date: Wed, 24 Jan 2024 22:28:03 +0100 Subject: [PATCH 176/344] Feature: Allow setting a different port in the motd (#4293) * Allow changing the broadcasted port using a system property. This may be needed if the port Geyser runs on & the port Bedrock players connect on do not match - e.g. due to port forwarding/different routing. * initial stab at making the broadcast port an (unsafe) config option * Automatically set broadcast port to be the bind port unless manually overridden * Warn about broadcast port mismatch * Use 0 instead of -1 as indicator to broadcast the port geyser is running on --- .../geyser/api/network/BedrockListener.java | 8 ++++ .../java/org/geysermc/geyser/GeyserImpl.java | 16 +++++++ .../defaults/ConnectionTestCommand.java | 46 ++++++++++++------- .../configuration/GeyserConfiguration.java | 2 + .../GeyserJacksonConfiguration.java | 9 ++++ .../geyser/network/netty/GeyserServer.java | 16 ++++++- core/src/main/resources/config.yml | 3 ++ 7 files changed, 81 insertions(+), 19 deletions(-) diff --git a/api/src/main/java/org/geysermc/geyser/api/network/BedrockListener.java b/api/src/main/java/org/geysermc/geyser/api/network/BedrockListener.java index 61fe286aa..af35d7ad1 100644 --- a/api/src/main/java/org/geysermc/geyser/api/network/BedrockListener.java +++ b/api/src/main/java/org/geysermc/geyser/api/network/BedrockListener.java @@ -50,6 +50,14 @@ public interface BedrockListener { */ int port(); + /** + * Gets the broadcast port that's sent to Bedrock clients with the motd. + * This is the port that Bedrock clients will connect with. It usually does not differ from the listening port. + * + * @return the broadcast port + */ + int broadcastPort(); + /** * Gets the primary MOTD shown to Bedrock players if a ping passthrough setting is not enabled. *

diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index 13212b161..e9ea08260 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -314,6 +314,22 @@ public class GeyserImpl implements GeyserApi { } } + String broadcastPort = System.getProperty("geyserBroadcastPort", ""); + if (!broadcastPort.isEmpty()) { + int parsedPort; + try { + parsedPort = Integer.parseInt(broadcastPort); + if (parsedPort < 1 || parsedPort > 65535) { + throw new NumberFormatException("The broadcast port must be between 1 and 65535 inclusive!"); + } + } catch (NumberFormatException e) { + logger.error(String.format("Invalid broadcast port: %s! Defaulting to configured port.", broadcastPort + " (" + e.getMessage() + ")")); + parsedPort = config.getBedrock().port(); + } + config.getBedrock().setBroadcastPort(parsedPort); + logger.info("Broadcast port set from system property: " + parsedPort); + } + boolean floodgatePresent = bootstrap.testFloodgatePluginPresent(); if (config.getRemote().authType() == AuthType.FLOODGATE && !floodgatePresent) { logger.severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.not_installed") + " " diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/ConnectionTestCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/ConnectionTestCommand.java index ad51826c3..981c97595 100644 --- a/core/src/main/java/org/geysermc/geyser/command/defaults/ConnectionTestCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/ConnectionTestCommand.java @@ -31,6 +31,7 @@ import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.command.GeyserCommand; import org.geysermc.geyser.command.GeyserCommandSource; +import org.geysermc.geyser.configuration.GeyserConfiguration; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.util.LoopbackUtil; @@ -84,7 +85,7 @@ public class ConnectionTestCommand extends GeyserCommand { return; } } else { - port = 19132; + port = geyser.getConfig().getBedrock().broadcastPort(); } String ip = fullAddress[0]; @@ -112,30 +113,41 @@ public class ConnectionTestCommand extends GeyserCommand { return; } - // Issue: do the ports not line up? - if (port != geyser.getConfig().getBedrock().port()) { - if (fullAddress.length == 2) { - sender.sendMessage("The port you are testing with (" + port + ") is not the same as you set in your Geyser configuration (" - + geyser.getConfig().getBedrock().port() + ")"); - sender.sendMessage("Re-run the command with the port in the config, or change the `bedrock` `port` in the config."); - if (geyser.getConfig().getBedrock().isCloneRemotePort()) { - sender.sendMessage("You have `clone-remote-port` enabled. This option ignores the `bedrock` `port` in the config, and uses the Java server port instead."); + GeyserConfiguration config = geyser.getConfig(); + + // Issue: do the ports not line up? We only check this if players don't override the broadcast port - if they do, they (hopefully) know what they're doing + if (config.getBedrock().broadcastPort() == config.getBedrock().port()) { + if (port != config.getBedrock().port()) { + if (fullAddress.length == 2) { + sender.sendMessage("The port you are testing with (" + port + ") is not the same as you set in your Geyser configuration (" + + config.getBedrock().port() + ")"); + sender.sendMessage("Re-run the command with the port in the config, or change the `bedrock` `port` in the config."); + if (config.getBedrock().isCloneRemotePort()) { + sender.sendMessage("You have `clone-remote-port` enabled. This option ignores the `bedrock` `port` in the config, and uses the Java server port instead."); + } + } else { + sender.sendMessage("You did not specify the port to check (add it with \":\"), " + + "and the default port 19132 does not match the port in your Geyser configuration (" + + config.getBedrock().port() + ")!"); + sender.sendMessage("Re-run the command with that port, or change the port in the config under `bedrock` `port`."); } - } else { - sender.sendMessage("You did not specify the port to check (add it with \":\"), " + - "and the default port 19132 does not match the port in your Geyser configuration (" - + geyser.getConfig().getBedrock().port() + ")!"); - sender.sendMessage("Re-run the command with that port, or change the port in the config under `bedrock` `port`."); + } + } else { + if (config.getBedrock().broadcastPort() != port) { + sender.sendMessage("The port you are testing with (" + port + ") is not the same as the broadcast port set in your Geyser configuration (" + + config.getBedrock().broadcastPort() + "). "); + sender.sendMessage("You ONLY need to change the broadcast port if clients connects with a port different from the port Geyser is running on."); + sender.sendMessage("Re-run the command with the port in the config, or change the `bedrock` `broadcast-port` in the config."); } } // Issue: is the `bedrock` `address` in the config different? - if (!geyser.getConfig().getBedrock().address().equals("0.0.0.0")) { + if (!config.getBedrock().address().equals("0.0.0.0")) { sender.sendMessage("The address specified in `bedrock` `address` is not \"0.0.0.0\" - this may cause issues unless this is deliberate and intentional."); } // Issue: did someone turn on enable-proxy-protocol, and they didn't mean it? - if (geyser.getConfig().getBedrock().isEnableProxyProtocol()) { + if (config.getBedrock().isEnableProxyProtocol()) { sender.sendMessage("You have the `enable-proxy-protocol` setting enabled. " + "Unless you're deliberately using additional software that REQUIRES this setting, you may not need it enabled."); } @@ -166,7 +178,7 @@ public class ConnectionTestCommand extends GeyserCommand { String connectionTestMotd = "Geyser Connection Test " + randomStr; CONNECTION_TEST_MOTD = connectionTestMotd; - sender.sendMessage("Testing server connection now. Please wait..."); + sender.sendMessage("Testing server connection to " + ip + " with port: " + port + " now. Please wait..."); JsonNode output; try { String hostname = URLEncoder.encode(ip, StandardCharsets.UTF_8); diff --git a/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java b/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java index f9bb15b32..d12ab79e9 100644 --- a/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java +++ b/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java @@ -122,6 +122,8 @@ public interface GeyserConfiguration { void setPort(int port); + void setBroadcastPort(int broadcastPort); + boolean isCloneRemotePort(); int getCompressionLevel(); diff --git a/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java b/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java index 0874daa07..b3b7e8cd4 100644 --- a/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java +++ b/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java @@ -172,6 +172,15 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration return port; } + @Setter + @JsonProperty("broadcast-port") + private int broadcastPort = 0; + + @Override + public int broadcastPort() { + return broadcastPort; + } + @Getter @JsonProperty("clone-remote-port") private boolean cloneRemotePort = false; diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java b/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java index 20340826f..401a7f2cf 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java @@ -102,6 +102,11 @@ public final class GeyserServer { private ChannelFuture bootstrapFuture; + /** + * The port to broadcast in the pong. This can be different from the port the server is bound to, e.g. due to port forwarding. + */ + private final int broadcastPort; + public GeyserServer(GeyserImpl geyser, int threadCount) { this.geyser = geyser; this.group = TRANSPORT.eventLoopGroupFactory().apply(threadCount); @@ -115,6 +120,13 @@ public final class GeyserServer { } else { this.proxiedAddresses = null; } + + // It's set to 0 only if no system property or manual config value was set + if (geyser.getConfig().getBedrock().broadcastPort() == 0) { + geyser.getConfig().getBedrock().setBroadcastPort(geyser.getConfig().getBedrock().port()); + } + + this.broadcastPort = geyser.getConfig().getBedrock().broadcastPort(); } public CompletableFuture bind(InetSocketAddress address) { @@ -243,8 +255,8 @@ public final class GeyserServer { .nintendoLimited(false) .protocolVersion(GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()) .version(GameProtocol.DEFAULT_BEDROCK_CODEC.getMinecraftVersion()) // Required to not be empty as of 1.16.210.59. Can only contain . and numbers. - .ipv4Port(this.geyser.getConfig().getBedrock().port()) - .ipv6Port(this.geyser.getConfig().getBedrock().port()) + .ipv4Port(this.broadcastPort) + .ipv6Port(this.broadcastPort) .serverId(bootstrapFuture.channel().config().getOption(RakChannelOption.RAK_GUID)); if (config.isPassthroughMotd() && pingInfo != null && pingInfo.getDescription() != null) { diff --git a/core/src/main/resources/config.yml b/core/src/main/resources/config.yml index b10c2788e..0617b316c 100644 --- a/core/src/main/resources/config.yml +++ b/core/src/main/resources/config.yml @@ -30,6 +30,9 @@ bedrock: # How much to compress network traffic to the Bedrock client. The higher the number, the more CPU usage used, but # the smaller the bandwidth used. Does not have any effect below -1 or above 9. Set to -1 to disable. compression-level: 6 + # The port to broadcast to Bedrock clients with the MOTD that they should use to connect to the server. + # DO NOT uncomment and change this unless Geyser runs on a different internal port than the one that is used to connect. + # broadcast-port: 19132 # Whether to enable PROXY protocol or not for clients. You DO NOT WANT this feature unless you run UDP reverse proxy # in front of your Geyser instance. enable-proxy-protocol: false From 07150db59234078879d0fae85c29d5c8d23ccb7e Mon Sep 17 00:00:00 2001 From: rtm516 Date: Sun, 28 Jan 2024 22:49:47 +0000 Subject: [PATCH 177/344] Fix language key typo when floodgate encryption fails (#4412) --- .../main/java/org/geysermc/geyser/session/GeyserSession.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 26e206458..5501e990e 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -935,7 +935,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { ).toString()); } catch (Exception e) { geyser.getLogger().error(GeyserLocale.getLocaleStringLog("geyser.auth.floodgate.encrypt_fail"), e); - disconnect(GeyserLocale.getPlayerLocaleString("geyser.auth.floodgate.encryption_fail", getClientData().getLanguageCode())); + disconnect(GeyserLocale.getPlayerLocaleString("geyser.auth.floodgate.encrypt_fail", getClientData().getLanguageCode())); return; } From f555dc0a928bf5d2e46859b726d688542158408f Mon Sep 17 00:00:00 2001 From: chris Date: Wed, 31 Jan 2024 11:21:06 +0100 Subject: [PATCH 178/344] Feature: Camera/Input locking API (#4332) Adds API methods to control player cameras - including fancy transitions, color fades, or simple input locks. --- api/build.gradle.kts | 1 + .../geyser/api/bedrock/camera/CameraData.java | 148 +++++++++++ .../api/bedrock/camera/CameraEaseType.java | 77 ++++++ .../geyser/api/bedrock/camera/CameraFade.java | 94 +++++++ .../api/bedrock/camera/CameraPerspective.java | 48 ++++ .../api/bedrock/camera/CameraPosition.java | 150 +++++++++++ .../api/bedrock/camera/CameraShake.java | 3 + .../api/connection/GeyserConnection.java | 39 ++- .../geyser/api/entity/EntityData.java | 84 +++++++ .../type/player/GeyserPlayerEntity.java | 8 + .../geyser/entity/GeyserEntityData.java | 99 ++++++++ .../entity/type/player/PlayerEntity.java | 17 +- .../geyser/impl/camera/CameraDefinitions.java | 96 +++++++ .../geyser/impl/camera/GeyserCameraData.java | 235 ++++++++++++++++++ .../geyser/impl/camera/GeyserCameraFade.java | 104 ++++++++ .../impl/camera/GeyserCameraPosition.java | 131 ++++++++++ .../geyser/item/GeyserCustomItemData.java | 2 +- .../geyser/item/GeyserCustomItemOptions.java | 2 +- .../item/GeyserNonVanillaCustomItemData.java | 38 +-- .../block/GeyserCustomBlockComponents.java | 4 +- .../level/block/GeyserCustomBlockData.java | 6 +- .../level/block/GeyserCustomBlockState.java | 2 +- .../level/block/GeyserGeometryComponent.java | 8 +- .../level/block/GeyserJavaBlockState.java | 4 +- .../level/block/GeyserMaterialInstance.java | 4 +- .../GeyserNonVanillaCustomBlockData.java | 42 ++-- .../geyser/network/LoggingPacketHandler.java | 10 + .../loader/ProviderRegistryLoader.java | 26 +- .../mappings/versions/MappingsReader_v1.java | 34 ++- .../CustomBlockRegistryPopulator.java | 16 +- .../geyser/registry/type/CustomSkull.java | 22 +- .../geyser/session/GeyserSession.java | 108 ++++---- .../protocol/java/JavaLoginTranslator.java | 2 +- .../geysermc/geyser/util/DimensionUtils.java | 4 +- gradle.properties | 2 +- gradle/libs.versions.toml | 2 + 36 files changed, 1523 insertions(+), 149 deletions(-) create mode 100644 api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraData.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraEaseType.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraFade.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraPerspective.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraPosition.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/entity/EntityData.java create mode 100644 core/src/main/java/org/geysermc/geyser/entity/GeyserEntityData.java create mode 100644 core/src/main/java/org/geysermc/geyser/impl/camera/CameraDefinitions.java create mode 100644 core/src/main/java/org/geysermc/geyser/impl/camera/GeyserCameraData.java create mode 100644 core/src/main/java/org/geysermc/geyser/impl/camera/GeyserCameraFade.java create mode 100644 core/src/main/java/org/geysermc/geyser/impl/camera/GeyserCameraPosition.java diff --git a/api/build.gradle.kts b/api/build.gradle.kts index c0ed242b6..bd54a9ce4 100644 --- a/api/build.gradle.kts +++ b/api/build.gradle.kts @@ -4,4 +4,5 @@ plugins { dependencies { api(libs.base.api) + api(libs.math) } \ No newline at end of file diff --git a/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraData.java b/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraData.java new file mode 100644 index 000000000..2f715fa1e --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraData.java @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2019-2023 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.api.bedrock.camera; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.geyser.api.connection.GeyserConnection; + +import java.util.Set; +import java.util.UUID; + +/** + * This interface holds all the methods that relate to a client's camera. + * Can be accessed through {@link GeyserConnection#camera()}. + */ +public interface CameraData { + + /** + * Sends a camera fade instruction to the client. + * If an existing camera fade is already in progress, the current fade will be prolonged. + * Can be built using {@link CameraFade.Builder}. + * To stop a fade early, use {@link #clearCameraInstructions()}. + * + * @param fade the camera fade instruction to send + */ + void sendCameraFade(@NonNull CameraFade fade); + + /** + * Sends a camera position instruction to the client. + * If an existing camera movement is already in progress, + * the final camera position will be the one of the latest instruction, and + * the (optional) camera fade will be added on top of the existing fade. + * Can be built using {@link CameraPosition.Builder}. + * To stop reset the camera position/stop ongoing instructions, use {@link #clearCameraInstructions()}. + * + * @param position the camera position instruction to send + */ + void sendCameraPosition(@NonNull CameraPosition position); + + /** + * Stops all sent camera instructions (fades, movements, and perspective locks). + * This will not stop any camera shakes/input locks/fog effects, use the respective methods for those. + */ + void clearCameraInstructions(); + + /** + * Forces a {@link CameraPerspective} on the client. This will prevent the client + * from changing their camera perspective until it is unlocked via {@link #clearCameraInstructions()}. + *

+ * Note: You cannot force a client into a free camera perspective with this method. + * To do that, send a {@link CameraPosition} via {@link #sendCameraPosition(CameraPosition)} - it requires a set position + * instead of being relative to the player. + * + * @param perspective the {@link CameraPerspective} to force + */ + void forceCameraPerspective(@NonNull CameraPerspective perspective); + + /** + * Gets the client's current {@link CameraPerspective}, if one is currently forced. + * This will return {@code null} if the client is not currently forced into a perspective. + * If a perspective is forced, the client will not be able to change their camera perspective until it is unlocked. + * + * @return the forced perspective, or {@code null} if none is forced + */ + @Nullable CameraPerspective forcedCameraPerspective(); + + /** + * Shakes the client's camera. + *

+ * If the camera is already shaking with the same {@link CameraShake} type, then the additional intensity + * will be layered on top of the existing intensity, with their own distinct durations.
+ * If the existing shake type is different and the new intensity/duration are not positive, the existing shake only + * switches to the new type. Otherwise, the existing shake is completely overridden. + * + * @param intensity the intensity of the shake. The client has a maximum total intensity of 4. + * @param duration the time in seconds that the shake will occur for + * @param type the type of shake + */ + void shakeCamera(float intensity, float duration, @NonNull CameraShake type); + + /** + * Stops all camera shakes of any type. + */ + void stopCameraShake(); + + /** + * Adds the given fog IDs to the fog cache, then sends all fog IDs in the cache to the client. + *

+ * Fog IDs can be found here + * + * @param fogNameSpaces the fog IDs to add. If empty, the existing cached IDs will still be sent. + */ + void sendFog(String... fogNameSpaces); + + /** + * Removes the given fog IDs from the fog cache, then sends all fog IDs in the cache to the client. + * + * @param fogNameSpaces the fog IDs to remove. If empty, all fog IDs will be removed. + */ + void removeFog(String... fogNameSpaces); + + /** + * Returns an immutable copy of all fog affects currently applied to this client. + */ + @NonNull + Set fogEffects(); + + /** + * (Un)locks the client's camera, so that they cannot look around. + * To ensure the camera is only unlocked when all locks are released, you must supply + * a UUID when using method, and use the same UUID to unlock the camera. + * + * @param lock whether to lock the camera + * @param owner the owner of the lock, represented with a UUID + * @return if the camera is locked after this method call + */ + boolean lockCamera(boolean lock, @NonNull UUID owner); + + /** + * Returns whether the client's camera is locked. + * + * @return whether the camera is currently locked + */ + boolean isCameraLocked(); +} \ No newline at end of file diff --git a/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraEaseType.java b/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraEaseType.java new file mode 100644 index 000000000..64c313ec1 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraEaseType.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2019-2023 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.api.bedrock.camera; + +/** + * These are all the easing types that can be used when sending a {@link CameraPosition} instruction. + * When using these, the client won't teleport to the new camera position, but instead transition to it. + *

+ * See https://easings.net/ for more information. + */ +public enum CameraEaseType { + LINEAR("linear"), + SPRING("spring"), + EASE_IN_SINE("in_sine"), + EASE_OUT_SINE("out_sine"), + EASE_IN_OUT_SINE("in_out_sine"), + EASE_IN_QUAD("in_quad"), + EASE_OUT_QUAD("out_quad"), + EASE_IN_OUT_QUAD("in_out_quad"), + EASE_IN_CUBIC("in_cubic"), + EASE_OUT_CUBIC("out_cubic"), + EASE_IN_OUT_CUBIC("in_out_cubic"), + EASE_IN_QUART("in_quart"), + EASE_OUT_QUART("out_quart"), + EASE_IN_OUT_QUART("in_out_quart"), + EASE_IN_QUINT("in_quint"), + EASE_OUT_QUINT("out_quint"), + EASE_IN_OUT_QUINT("in_out_quint"), + EASE_IN_EXPO("in_expo"), + EASE_OUT_EXPO("out_expo"), + EASE_IN_OUT_EXPO("in_out_expo"), + EASE_IN_CIRC("in_circ"), + EASE_OUT_CIRC("out_circ"), + EASE_IN_OUT_CIRC("in_out_circ"), + EASE_IN_BACK("in_back"), + EASE_OUT_BACK("out_back"), + EASE_IN_OUT_BACK("in_out_back"), + EASE_IN_ELASTIC("in_elastic"), + EASE_OUT_ELASTIC("out_elastic"), + EASE_IN_OUT_ELASTIC("in_out_elastic"), + EASE_IN_BOUNCE("in_bounce"), + EASE_OUT_BOUNCE("out_bounce"), + EASE_IN_OUT_BOUNCE("in_out_bounce"); + + private final String id; + + CameraEaseType(String id) { + this.id = id; + } + + public String id() { + return this.id; + } +} diff --git a/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraFade.java b/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraFade.java new file mode 100644 index 000000000..38baa73bb --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraFade.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2019-2023 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.api.bedrock.camera; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.common.value.qual.IntRange; +import org.geysermc.geyser.api.GeyserApi; + +import java.awt.Color; + +/** + * Represents a coloured fade overlay on the camera. + *

+ * Can be sent with {@link CameraData#sendCameraFade(CameraFade)}, or with a {@link CameraPosition} instruction. + */ +public interface CameraFade { + + /** + * Gets the color overlay of the camera. + * Bedrock uses an RGB color system. + * + * @return the color of the fade + */ + @NonNull Color color(); + + /** + * Gets the seconds it takes to fade in. + * All fade times combined must take at least 0.5 seconds, and at most 30 seconds. + * + * @return the seconds it takes to fade in + */ + float fadeInSeconds(); + + /** + * Gets the seconds the overlay is held. + * All fade times combined must take at least 0.5 seconds, and at most 30 seconds. + * + * @return the seconds the overlay is held + */ + float fadeHoldSeconds(); + + /** + * Gets the seconds it takes to fade out. + * All fade times combined must take at least 0.5 seconds, and at most 30 seconds. + * + * @return the seconds it takes to fade out + */ + float fadeOutSeconds(); + + /** + * Creates a Builder for CameraFade + * + * @return a CameraFade Builder + */ + static CameraFade.Builder builder() { + return GeyserApi.api().provider(CameraFade.Builder.class); + } + + interface Builder { + + Builder color(@NonNull Color color); + + Builder fadeInSeconds(@IntRange(from = 0, to = 10) float fadeInSeconds); + + Builder fadeHoldSeconds(@IntRange(from = 0, to = 10) float fadeHoldSeconds); + + Builder fadeOutSeconds(@IntRange(from = 0, to = 10) float fadeOutSeconds); + + CameraFade build(); + } +} diff --git a/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraPerspective.java b/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraPerspective.java new file mode 100644 index 000000000..4167f2a34 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraPerspective.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2019-2023 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.api.bedrock.camera; + +/** + * Represents a camera perspective that a player's camera can take. + * All perspectives except for {@link #FREE} are locked to the player's head, + * and are therefore relative to the player's position and rotation. + */ +public enum CameraPerspective { + FIRST_PERSON("minecraft:first_person"), + FREE("minecraft:free"), + THIRD_PERSON("minecraft:third_person"), + THIRD_PERSON_FRONT("minecraft:third_person_front"); + + private final String id; + + CameraPerspective(String id) { + this.id = id; + } + + public String id() { + return this.id; + } +} diff --git a/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraPosition.java b/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraPosition.java new file mode 100644 index 000000000..6d42d499e --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraPosition.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2019-2023 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.api.bedrock.camera; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.common.value.qual.IntRange; +import org.cloudburstmc.math.vector.Vector3f; +import org.geysermc.geyser.api.GeyserApi; + +/** + * This interface represents a camera position instruction. Can be built with the {@link #builder()}. + *

+ * Any camera position instruction pins the client camera to a specific position and rotation. + * You can set {@link CameraEaseType} to ensure a smooth transition that will last {@link #easeSeconds()} seconds. + * A {@link CameraFade} can also be sent, which will transition the player to a coloured transition during the transition. + *

+ * Use {@link CameraData#sendCameraPosition(CameraPosition)} to send such an instruction to any connection. + */ +public interface CameraPosition { + + /** + * Gets the camera's position. + * + * @return camera position vector + */ + @NonNull Vector3f position(); + + /** + * Gets the {@link CameraEaseType} of the camera. + * If not set, there is no easing. + * + * @return camera ease type + */ + @Nullable CameraEaseType easeType(); + + /** + * Gets the {@link CameraFade} to be sent along the camera position instruction. + * If set, they will run at once. + * + * @return camera fade, or null if not present + */ + @Nullable CameraFade cameraFade(); + + /** + * Gets the easing duration of the camera, in seconds. + * Is only used if a {@link CameraEaseType} is set. + * + * @return camera easing duration in seconds + */ + float easeSeconds(); + + /** + * Gets the x-axis rotation of the camera. + * To prevent the camera from being upside down, Bedrock limits the range to -90 to 90. + * Will be overridden if {@link #facingPosition()} is set. + * + * @return camera x-axis rotation + */ + @IntRange(from = -90, to = 90) int rotationX(); + + /** + * Gets the y-axis rotation of the camera. + * Will be overridden if {@link #facingPosition()} is set. + * + * @return camera y-axis rotation + */ + int rotationY(); + + /** + * Gets the position that the camera is facing. + * Can be used instead of manually setting rotation values. + *

+ * If set, the rotation values set via {@link #rotationX()} and {@link #rotationY()} will be ignored. + * + * @return Camera's facing position + */ + @Nullable Vector3f facingPosition(); + + /** + * Controls whether player effects, such as night vision or blindness, should be rendered on the camera. + * Defaults to false. + * + * @return whether player effects should be rendered + */ + boolean renderPlayerEffects(); + + /** + * Controls whether the player position should be used for directional audio. + * If false, the camera position will be used instead. + * + * @return whether the players position should be used for directional audio + */ + boolean playerPositionForAudio(); + + /** + * Creates a Builder for CameraPosition + * + * @return a CameraPosition Builder + */ + static CameraPosition.Builder builder() { + return GeyserApi.api().provider(CameraPosition.Builder.class); + } + + interface Builder { + + Builder cameraFade(@Nullable CameraFade cameraFade); + + Builder renderPlayerEffects(boolean renderPlayerEffects); + + Builder playerPositionForAudio(boolean playerPositionForAudio); + + Builder easeType(@Nullable CameraEaseType easeType); + + Builder easeSeconds(float easeSeconds); + + Builder position(@NonNull Vector3f position); + + Builder rotationX(@IntRange(from = -90, to = 90) int rotationX); + + Builder rotationY(int rotationY); + + Builder facingPosition(@Nullable Vector3f facingPosition); + + CameraPosition build(); + } +} diff --git a/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraShake.java b/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraShake.java index 67b56b1f5..304969edb 100644 --- a/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraShake.java +++ b/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraShake.java @@ -25,6 +25,9 @@ package org.geysermc.geyser.api.bedrock.camera; +/** + * Represents a camera shake instruction. Can be sent in {@link CameraData#shakeCamera(float, float, CameraShake)} + */ public enum CameraShake { POSITIONAL, ROTATIONAL diff --git a/api/src/main/java/org/geysermc/geyser/api/connection/GeyserConnection.java b/api/src/main/java/org/geysermc/geyser/api/connection/GeyserConnection.java index 7094812a0..9bda4f903 100644 --- a/api/src/main/java/org/geysermc/geyser/api/connection/GeyserConnection.java +++ b/api/src/main/java/org/geysermc/geyser/api/connection/GeyserConnection.java @@ -29,8 +29,10 @@ import org.checkerframework.checker.index.qual.NonNegative; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.api.connection.Connection; +import org.geysermc.geyser.api.bedrock.camera.CameraData; import org.geysermc.geyser.api.bedrock.camera.CameraShake; import org.geysermc.geyser.api.command.CommandSource; +import org.geysermc.geyser.api.entity.EntityData; import org.geysermc.geyser.api.entity.type.GeyserEntity; import org.geysermc.geyser.api.entity.type.player.GeyserPlayerEntity; @@ -41,10 +43,29 @@ import java.util.concurrent.CompletableFuture; * Represents a player connection used in Geyser. */ public interface GeyserConnection extends Connection, CommandSource { + + /** + * Exposes the {@link CameraData} for this connection. + * It allows you to send fogs, camera shakes, force camera perspectives, and more. + * + * @return the CameraData for this connection. + */ + @NonNull CameraData camera(); + + /** + * Exposes the {@link EntityData} for this connection. + * It allows you to get entities by their Java entity ID, show emotes, and get the player entity. + * + * @return the EntityData for this connection. + */ + @NonNull EntityData entities(); + /** * @param javaId the Java entity ID to look up. * @return a {@link GeyserEntity} if present in this connection's entity tracker. + * @deprecated Use {@link EntityData#entityByJavaId(int)} instead */ + @Deprecated @NonNull CompletableFuture<@Nullable GeyserEntity> entityByJavaId(@NonNegative int javaId); @@ -53,11 +74,14 @@ public interface GeyserConnection extends Connection, CommandSource { * * @param emoter the player entity emoting. * @param emoteId the emote ID to send to this client. + * @deprecated use {@link EntityData#showEmote(GeyserPlayerEntity, String)} instead */ + @Deprecated void showEmote(@NonNull GeyserPlayerEntity emoter, @NonNull String emoteId); /** - * Shakes the client's camera.

+ * Shakes the client's camera. + *

* If the camera is already shaking with the same {@link CameraShake} type, then the additional intensity * will be layered on top of the existing intensity, with their own distinct durations.
* If the existing shake type is different and the new intensity/duration are not positive, the existing shake only @@ -66,12 +90,18 @@ public interface GeyserConnection extends Connection, CommandSource { * @param intensity the intensity of the shake. The client has a maximum total intensity of 4. * @param duration the time in seconds that the shake will occur for * @param type the type of shake + * + * @deprecated Use {@link CameraData#shakeCamera(float, float, CameraShake)} instead. */ + @Deprecated void shakeCamera(float intensity, float duration, @NonNull CameraShake type); /** * Stops all camera shake of any type. + * + * @deprecated Use {@link CameraData#stopCameraShake()} instead. */ + @Deprecated void stopCameraShake(); /** @@ -80,19 +110,26 @@ public interface GeyserConnection extends Connection, CommandSource { * Fog IDs can be found here * * @param fogNameSpaces the fog IDs to add. If empty, the existing cached IDs will still be sent. + * @deprecated Use {@link CameraData#sendFog(String...)} instead. */ + @Deprecated void sendFog(String... fogNameSpaces); /** * Removes the given fog IDs from the fog cache, then sends all fog IDs in the cache to the client. * * @param fogNameSpaces the fog IDs to remove. If empty, all fog IDs will be removed. + * @deprecated Use {@link CameraData#removeFog(String...)} instead. */ + @Deprecated void removeFog(String... fogNameSpaces); /** * Returns an immutable copy of all fog affects currently applied to this client. + * + * @deprecated Use {@link CameraData#fogEffects()} instead. */ + @Deprecated @NonNull Set fogEffects(); } diff --git a/api/src/main/java/org/geysermc/geyser/api/entity/EntityData.java b/api/src/main/java/org/geysermc/geyser/api/entity/EntityData.java new file mode 100644 index 000000000..90b3fc821 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/entity/EntityData.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2019-2023 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.api.entity; + +import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.geyser.api.connection.GeyserConnection; +import org.geysermc.geyser.api.entity.type.GeyserEntity; +import org.geysermc.geyser.api.entity.type.player.GeyserPlayerEntity; + +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +/** + * This class holds all the methods that relate to entities. + * Can be accessed through {@link GeyserConnection#entities()}. + */ +public interface EntityData { + + /** + * Returns a {@link GeyserEntity} to e.g. make them play an emote. + * + * @param javaId the Java entity ID to look up + * @return a {@link GeyserEntity} if present in this connection's entity tracker + */ + @NonNull CompletableFuture<@Nullable GeyserEntity> entityByJavaId(@NonNegative int javaId); + + /** + * Displays a player entity as emoting to this client. + * + * @param emoter the player entity emoting + * @param emoteId the emote ID to send to this client + */ + void showEmote(@NonNull GeyserPlayerEntity emoter, @NonNull String emoteId); + + /** + * Gets the {@link GeyserPlayerEntity} of this connection. + * + * @return the {@link GeyserPlayerEntity} of this connection + */ + @NonNull GeyserPlayerEntity playerEntity(); + + /** + * (Un)locks the client's movement inputs, so that they cannot move. + * To ensure that movement is only unlocked when all locks are released, you must supply + * a UUID with this method, and use the same UUID to unlock the camera. + * + * @param lock whether to lock the movement + * @param owner the owner of the lock + * @return if the movement is locked after this method call + */ + boolean lockMovement(boolean lock, @NonNull UUID owner); + + /** + * Returns whether the client's movement is currently locked. + * + * @return whether the movement is locked + */ + boolean isMovementLocked(); +} diff --git a/api/src/main/java/org/geysermc/geyser/api/entity/type/player/GeyserPlayerEntity.java b/api/src/main/java/org/geysermc/geyser/api/entity/type/player/GeyserPlayerEntity.java index da2e28609..bba4dbf3e 100644 --- a/api/src/main/java/org/geysermc/geyser/api/entity/type/player/GeyserPlayerEntity.java +++ b/api/src/main/java/org/geysermc/geyser/api/entity/type/player/GeyserPlayerEntity.java @@ -25,7 +25,15 @@ package org.geysermc.geyser.api.entity.type.player; +import org.cloudburstmc.math.vector.Vector3f; import org.geysermc.geyser.api.entity.type.GeyserEntity; public interface GeyserPlayerEntity extends GeyserEntity { + + /** + * Gets the position of the player. + * + * @return the position of the player. + */ + Vector3f position(); } diff --git a/core/src/main/java/org/geysermc/geyser/entity/GeyserEntityData.java b/core/src/main/java/org/geysermc/geyser/entity/GeyserEntityData.java new file mode 100644 index 000000000..c9ef7a2dd --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/entity/GeyserEntityData.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2019-2023 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.entity; + +import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.cloudburstmc.protocol.bedrock.packet.EmotePacket; +import org.geysermc.geyser.api.entity.EntityData; +import org.geysermc.geyser.api.entity.type.GeyserEntity; +import org.geysermc.geyser.api.entity.type.player.GeyserPlayerEntity; +import org.geysermc.geyser.entity.type.Entity; +import org.geysermc.geyser.session.GeyserSession; + +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +public class GeyserEntityData implements EntityData { + + private final GeyserSession session; + + private final Set movementLockOwners = new HashSet<>(); + + public GeyserEntityData(GeyserSession session) { + this.session = session; + } + + @Override + public @NonNull CompletableFuture<@Nullable GeyserEntity> entityByJavaId(@NonNegative int javaId) { + CompletableFuture future = new CompletableFuture<>(); + session.ensureInEventLoop(() -> future.complete(session.getEntityCache().getEntityByJavaId(javaId))); + return future; + } + + @Override + public void showEmote(@NonNull GeyserPlayerEntity emoter, @NonNull String emoteId) { + Objects.requireNonNull(emoter, "emoter must not be null!"); + Entity entity = (Entity) emoter; + if (entity.getSession() != session) { + throw new IllegalStateException("Given entity must be from this session!"); + } + + EmotePacket packet = new EmotePacket(); + packet.setRuntimeEntityId(entity.getGeyserId()); + packet.setXuid(""); + packet.setPlatformId(""); // BDS sends empty + packet.setEmoteId(emoteId); + session.sendUpstreamPacket(packet); + } + + @Override + public @NonNull GeyserPlayerEntity playerEntity() { + return session.getPlayerEntity(); + } + + @Override + public boolean lockMovement(boolean lock, @NonNull UUID owner) { + Objects.requireNonNull(owner, "owner must not be null!"); + if (lock) { + movementLockOwners.add(owner); + } else { + movementLockOwners.remove(owner); + } + + session.lockInputs(session.camera().isCameraLocked(), isMovementLocked()); + return isMovementLocked(); + } + + @Override + public boolean isMovementLocked() { + return !movementLockOwners.isEmpty(); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java index 7504db1b1..37e408502 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java @@ -39,12 +39,20 @@ import net.kyori.adventure.text.Component; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; -import org.cloudburstmc.protocol.bedrock.data.*; +import org.cloudburstmc.protocol.bedrock.data.Ability; +import org.cloudburstmc.protocol.bedrock.data.AbilityLayer; +import org.cloudburstmc.protocol.bedrock.data.AttributeData; +import org.cloudburstmc.protocol.bedrock.data.GameType; +import org.cloudburstmc.protocol.bedrock.data.PlayerPermission; import org.cloudburstmc.protocol.bedrock.data.command.CommandPermission; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.data.entity.EntityLinkData; -import org.cloudburstmc.protocol.bedrock.packet.*; +import org.cloudburstmc.protocol.bedrock.packet.AddPlayerPacket; +import org.cloudburstmc.protocol.bedrock.packet.MovePlayerPacket; +import org.cloudburstmc.protocol.bedrock.packet.SetEntityDataPacket; +import org.cloudburstmc.protocol.bedrock.packet.SetEntityLinkPacket; +import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket; import org.geysermc.geyser.api.entity.type.player.GeyserPlayerEntity; import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.type.Entity; @@ -433,4 +441,9 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity { public UUID getTabListUuid() { return getUuid(); } + + @Override + public Vector3f position() { + return this.position.clone(); + } } diff --git a/core/src/main/java/org/geysermc/geyser/impl/camera/CameraDefinitions.java b/core/src/main/java/org/geysermc/geyser/impl/camera/CameraDefinitions.java new file mode 100644 index 000000000..80564bdf3 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/impl/camera/CameraDefinitions.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2019-2024 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.impl.camera; + +import org.cloudburstmc.protocol.bedrock.data.camera.CameraAudioListener; +import org.cloudburstmc.protocol.bedrock.data.camera.CameraPreset; +import org.cloudburstmc.protocol.common.DefinitionRegistry; +import org.cloudburstmc.protocol.common.NamedDefinition; +import org.cloudburstmc.protocol.common.SimpleDefinitionRegistry; +import org.cloudburstmc.protocol.common.util.OptionalBoolean; +import org.geysermc.geyser.api.bedrock.camera.CameraPerspective; + +import java.util.List; + +public class CameraDefinitions { + + public static final DefinitionRegistry CAMERA_DEFINITIONS; + + public static final List CAMERA_PRESETS; + + static { + CAMERA_PRESETS = List.of( + new CameraPreset(CameraPerspective.FIRST_PERSON.id(), "", null, null, null, null, OptionalBoolean.empty()), + new CameraPreset(CameraPerspective.FREE.id(), "", null, null, null, null, OptionalBoolean.empty()), + new CameraPreset(CameraPerspective.THIRD_PERSON.id(), "", null, null, null, null, OptionalBoolean.empty()), + new CameraPreset(CameraPerspective.THIRD_PERSON_FRONT.id(), "", null, null, null, null, OptionalBoolean.empty()), + new CameraPreset("geyser:free_audio", "minecraft:free", null, null, null, CameraAudioListener.PLAYER, OptionalBoolean.of(false)), + new CameraPreset("geyser:free_effects", "minecraft:free", null, null, null, CameraAudioListener.CAMERA, OptionalBoolean.of(true)), + new CameraPreset("geyser:free_audio_effects", "minecraft:free", null, null, null, CameraAudioListener.PLAYER, OptionalBoolean.of(true))); + + SimpleDefinitionRegistry.Builder builder = SimpleDefinitionRegistry.builder(); + for (int i = 0; i < CAMERA_PRESETS.size(); i++) { + builder.add(CameraDefinition.of(CAMERA_PRESETS.get(i).getIdentifier(), i)); + } + CAMERA_DEFINITIONS = builder.build(); + } + + public static NamedDefinition getById(int id) { + return CAMERA_DEFINITIONS.getDefinition(id); + } + + public static NamedDefinition getByFunctionality(boolean audio, boolean effects) { + if (!audio && !effects) { + return getById(1); // FREE + } + if (audio) { + if (effects) { + return getById(6); // FREE_AUDIO_EFFECTS + } else { + return getById(4); // FREE_AUDIO + } + } else { + return getById(5); // FREE_EFFECTS + } + } + + public record CameraDefinition(String identifier, int runtimeId) implements NamedDefinition { + + @Override + public String getIdentifier() { + return identifier; + } + + @Override + public int getRuntimeId() { + return runtimeId; + } + + public static CameraDefinition of(String identifier, int runtimeId) { + return new CameraDefinition(identifier, runtimeId); + } + } +} diff --git a/core/src/main/java/org/geysermc/geyser/impl/camera/GeyserCameraData.java b/core/src/main/java/org/geysermc/geyser/impl/camera/GeyserCameraData.java new file mode 100644 index 000000000..28c881eba --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/impl/camera/GeyserCameraData.java @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2019-2024 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.impl.camera; + +import lombok.Getter; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.cloudburstmc.math.vector.Vector2f; +import org.cloudburstmc.math.vector.Vector3f; +import org.cloudburstmc.protocol.bedrock.data.CameraShakeAction; +import org.cloudburstmc.protocol.bedrock.data.CameraShakeType; +import org.cloudburstmc.protocol.bedrock.data.camera.CameraEase; +import org.cloudburstmc.protocol.bedrock.data.camera.CameraFadeInstruction; +import org.cloudburstmc.protocol.bedrock.data.camera.CameraSetInstruction; +import org.cloudburstmc.protocol.bedrock.packet.CameraInstructionPacket; +import org.cloudburstmc.protocol.bedrock.packet.CameraShakePacket; +import org.cloudburstmc.protocol.bedrock.packet.PlayerFogPacket; +import org.geysermc.geyser.api.bedrock.camera.CameraEaseType; +import org.geysermc.geyser.api.bedrock.camera.CameraData; +import org.geysermc.geyser.api.bedrock.camera.CameraFade; +import org.geysermc.geyser.api.bedrock.camera.CameraPerspective; +import org.geysermc.geyser.api.bedrock.camera.CameraPosition; +import org.geysermc.geyser.api.bedrock.camera.CameraShake; +import org.geysermc.geyser.session.GeyserSession; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; + +public class GeyserCameraData implements CameraData { + + private final GeyserSession session; + + @Getter + private CameraPerspective cameraPerspective; + + /** + * All fog effects that are currently applied to the client. + */ + private final Set appliedFog = new HashSet<>(); + + private final Set cameraLockOwners = new HashSet<>(); + + public GeyserCameraData(GeyserSession session) { + this.session = session; + } + + @Override + public void clearCameraInstructions() { + this.cameraPerspective = null; + CameraInstructionPacket packet = new CameraInstructionPacket(); + packet.setClear(true); + session.sendUpstreamPacket(packet); + } + + @Override + public void forceCameraPerspective(@NonNull CameraPerspective perspective) { + Objects.requireNonNull(perspective, "perspective cannot be null!"); + + if (perspective == cameraPerspective) { + return; // nothing to do + } + + this.cameraPerspective = perspective; + CameraInstructionPacket packet = new CameraInstructionPacket(); + CameraSetInstruction setInstruction = new CameraSetInstruction(); + + if (perspective == CameraPerspective.FREE) { + throw new IllegalArgumentException("Cannot force a stationary camera (CameraPerspective#FREE) on the player!" + + "Send a CameraPosition with an exact position instead"); + } + + setInstruction.setPreset(CameraDefinitions.getById(perspective.ordinal())); + packet.setSetInstruction(setInstruction); + session.sendUpstreamPacket(packet); + } + + @Override + public @Nullable CameraPerspective forcedCameraPerspective() { + return this.cameraPerspective; + } + + @Override + public void sendCameraFade(@NonNull CameraFade fade) { + Objects.requireNonNull(fade, "fade cannot be null!"); + CameraFadeInstruction fadeInstruction = new CameraFadeInstruction(); + fadeInstruction.setColor(fade.color()); + fadeInstruction.setTimeData( + new CameraFadeInstruction.TimeData( + fade.fadeInSeconds(), + fade.fadeHoldSeconds(), + fade.fadeOutSeconds() + ) + ); + + CameraInstructionPacket packet = new CameraInstructionPacket(); + packet.setFadeInstruction(fadeInstruction); + session.sendUpstreamPacket(packet); + } + + @Override + public void sendCameraPosition(@NonNull CameraPosition movement) { + Objects.requireNonNull(movement, "movement cannot be null!"); + this.cameraPerspective = CameraPerspective.FREE; // Movements only work with the free preset + CameraSetInstruction setInstruction = new CameraSetInstruction(); + + CameraEaseType easeType = movement.easeType(); + if (easeType != null) { + setInstruction.setEase(new CameraSetInstruction.EaseData( + CameraEase.fromName(easeType.id()), + movement.easeSeconds() + )); + } + + Vector3f facingPosition = movement.facingPosition(); + if (facingPosition != null) { + setInstruction.setFacing(facingPosition); + } + + setInstruction.setPos(movement.position()); + setInstruction.setRot(Vector2f.from(movement.rotationX(), movement.rotationY())); + setInstruction.setPreset(CameraDefinitions.getByFunctionality(movement.playerPositionForAudio(), movement.renderPlayerEffects())); + + CameraInstructionPacket packet = new CameraInstructionPacket(); + packet.setSetInstruction(setInstruction); + + // If present, also send the fade + CameraFade fade = movement.cameraFade(); + if (fade != null) { + CameraFadeInstruction fadeInstruction = new CameraFadeInstruction(); + fadeInstruction.setColor(fade.color()); + fadeInstruction.setTimeData( + new CameraFadeInstruction.TimeData( + fade.fadeInSeconds(), + fade.fadeHoldSeconds(), + fade.fadeOutSeconds() + ) + ); + packet.setFadeInstruction(fadeInstruction); + } + session.sendUpstreamPacket(packet); + } + + @Override + public void shakeCamera(float intensity, float duration, @NonNull CameraShake type) { + Objects.requireNonNull(type, "camera shake type must be non null!"); + CameraShakePacket packet = new CameraShakePacket(); + packet.setIntensity(intensity); + packet.setDuration(duration); + packet.setShakeType(type == CameraShake.POSITIONAL ? CameraShakeType.POSITIONAL : CameraShakeType.ROTATIONAL); + packet.setShakeAction(CameraShakeAction.ADD); + session.sendUpstreamPacket(packet); + } + + @Override + public void stopCameraShake() { + CameraShakePacket packet = new CameraShakePacket(); + // CameraShakeAction.STOP removes all types regardless of the given type, but regardless it can't be null + packet.setShakeType(CameraShakeType.POSITIONAL); + packet.setShakeAction(CameraShakeAction.STOP); + session.sendUpstreamPacket(packet); + } + + @Override + public void sendFog(String... fogNameSpaces) { + Collections.addAll(this.appliedFog, fogNameSpaces); + + PlayerFogPacket packet = new PlayerFogPacket(); + packet.getFogStack().addAll(this.appliedFog); + session.sendUpstreamPacket(packet); + } + + @Override + public void removeFog(String... fogNameSpaces) { + if (fogNameSpaces.length == 0) { + this.appliedFog.clear(); + } else { + for (String id : fogNameSpaces) { + this.appliedFog.remove(id); + } + } + PlayerFogPacket packet = new PlayerFogPacket(); + packet.getFogStack().addAll(this.appliedFog); + session.sendUpstreamPacket(packet); + } + + @Override + public @NonNull Set fogEffects() { + // Use a copy so that sendFog/removeFog can be called while iterating the returned set (avoid CME) + return Set.copyOf(this.appliedFog); + } + + @Override + public boolean lockCamera(boolean lock, @NonNull UUID owner) { + Objects.requireNonNull(owner, "owner cannot be null!"); + if (lock) { + this.cameraLockOwners.add(owner); + } else { + this.cameraLockOwners.remove(owner); + } + + session.lockInputs(isCameraLocked(), session.entities().isMovementLocked()); + return isCameraLocked(); + } + + @Override + public boolean isCameraLocked() { + return !this.cameraLockOwners.isEmpty(); + } +} \ No newline at end of file diff --git a/core/src/main/java/org/geysermc/geyser/impl/camera/GeyserCameraFade.java b/core/src/main/java/org/geysermc/geyser/impl/camera/GeyserCameraFade.java new file mode 100644 index 000000000..648e70c81 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/impl/camera/GeyserCameraFade.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2019-2024 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.impl.camera; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.common.value.qual.IntRange; +import org.geysermc.geyser.api.bedrock.camera.CameraFade; + +import java.awt.Color; +import java.util.Objects; + +public record GeyserCameraFade( + Color color, + float fadeInSeconds, + float fadeHoldSeconds, + float fadeOutSeconds + +) implements CameraFade { + public static class Builder implements CameraFade.Builder { + private Color color; + private float fadeInSeconds; + private float fadeHoldSeconds; + private float fadeOutSeconds; + + @Override + public CameraFade.Builder color(@NonNull Color color) { + Objects.requireNonNull(color, "color cannot be null!"); + this.color = color; + return this; + } + + @Override + public CameraFade.Builder fadeInSeconds(@IntRange(from = 0, to = 10) float fadeInSeconds) { + if (fadeInSeconds < 0f) { + throw new IllegalArgumentException("Fade in seconds must be at least 0 seconds"); + } + + if (fadeInSeconds > 10f) { + throw new IllegalArgumentException("Fade in seconds must be at most 10 seconds"); + } + this.fadeInSeconds = fadeInSeconds; + return this; + } + + @Override + public CameraFade.Builder fadeHoldSeconds(@IntRange(from = 0, to = 10) float fadeHoldSeconds) { + if (fadeHoldSeconds < 0f) { + throw new IllegalArgumentException("Fade hold seconds must be at least 0 seconds"); + } + + if (fadeHoldSeconds > 10f) { + throw new IllegalArgumentException("Fade hold seconds must be at most 10 seconds"); + } + this.fadeHoldSeconds = fadeHoldSeconds; + return this; + } + + @Override + public CameraFade.Builder fadeOutSeconds(@IntRange(from = 0, to = 10) float fadeOutSeconds) { + if (fadeOutSeconds < 0f) { + throw new IllegalArgumentException("Fade out seconds must be at least 0 seconds"); + } + + if (fadeOutSeconds > 10f) { + throw new IllegalArgumentException("Fade out seconds must be at most 10 seconds"); + } + this.fadeOutSeconds = fadeOutSeconds; + return this; + } + + @Override + public CameraFade build() { + Objects.requireNonNull(color, "color must be non null!"); + if (fadeInSeconds + fadeHoldSeconds + fadeOutSeconds < 0.5f) { + throw new IllegalArgumentException("Total fade time (in, hold, out) must be at least 0.5 seconds"); + } + + return new GeyserCameraFade(color, fadeInSeconds, fadeHoldSeconds, fadeOutSeconds); + } + } +} diff --git a/core/src/main/java/org/geysermc/geyser/impl/camera/GeyserCameraPosition.java b/core/src/main/java/org/geysermc/geyser/impl/camera/GeyserCameraPosition.java new file mode 100644 index 000000000..13b382465 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/impl/camera/GeyserCameraPosition.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2019-2024 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.impl.camera; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.common.value.qual.IntRange; +import org.cloudburstmc.math.vector.Vector3f; +import org.geysermc.geyser.api.bedrock.camera.CameraEaseType; +import org.geysermc.geyser.api.bedrock.camera.CameraFade; +import org.geysermc.geyser.api.bedrock.camera.CameraPosition; + +import java.util.Objects; + +public record GeyserCameraPosition(CameraFade cameraFade, + boolean renderPlayerEffects, + boolean playerPositionForAudio, + CameraEaseType easeType, + float easeSeconds, + Vector3f position, + @IntRange(from = -90, to = 90) int rotationX, + int rotationY, + Vector3f facingPosition +) implements CameraPosition { + + public static class Builder implements CameraPosition.Builder { + private CameraFade cameraFade; + private boolean renderPlayerEffects; + private boolean playerPositionForAudio; + private CameraEaseType easeType; + private float easeSeconds; + private Vector3f position; + private @IntRange(from = -90, to = 90) int rotationX; + private int rotationY; + private Vector3f facingPosition; + + @Override + public CameraPosition.Builder cameraFade(@Nullable CameraFade cameraFade) { + this.cameraFade = cameraFade; + return this; + } + + @Override + public CameraPosition.Builder renderPlayerEffects(boolean renderPlayerEffects) { + this.renderPlayerEffects = renderPlayerEffects; + return this; + } + + @Override + public CameraPosition.Builder playerPositionForAudio(boolean playerPositionForAudio) { + this.playerPositionForAudio = playerPositionForAudio; + return this; + } + + @Override + public CameraPosition.Builder easeType(@Nullable CameraEaseType easeType) { + this.easeType = easeType; + return this; + } + + @Override + public CameraPosition.Builder easeSeconds(float easeSeconds) { + if (easeSeconds < 0) { + throw new IllegalArgumentException("Camera ease duration cannot be negative!"); + } + this.easeSeconds = easeSeconds; + return this; + } + + @Override + public CameraPosition.Builder position(@NonNull Vector3f position) { + Objects.requireNonNull(position, "camera position cannot be null!"); + this.position = position; + return this; + } + + @Override + public CameraPosition.Builder rotationX(int rotationX) { + if (rotationX < -90 || rotationX > 90) { + throw new IllegalArgumentException("x-axis rotation needs to be between -90 and 90 degrees."); + } + this.rotationX = rotationX; + return this; + } + + @Override + public CameraPosition.Builder rotationY(int rotationY) { + this.rotationY = rotationY; + return this; + } + + @Override + public CameraPosition.Builder facingPosition(@Nullable Vector3f facingPosition) { + this.facingPosition = facingPosition; + return this; + } + + @Override + public CameraPosition build() { + if (easeSeconds > 0 && easeType == null) { + throw new IllegalArgumentException("Camera ease type cannot be null if ease duration is greater than 0"); + } + + Objects.requireNonNull(position, "camera position must be non null!"); + return new GeyserCameraPosition(cameraFade, renderPlayerEffects, playerPositionForAudio, easeType, easeSeconds, position, rotationX, rotationY, facingPosition); + } + } +} diff --git a/core/src/main/java/org/geysermc/geyser/item/GeyserCustomItemData.java b/core/src/main/java/org/geysermc/geyser/item/GeyserCustomItemData.java index c86c370bb..2906a9be3 100644 --- a/core/src/main/java/org/geysermc/geyser/item/GeyserCustomItemData.java +++ b/core/src/main/java/org/geysermc/geyser/item/GeyserCustomItemData.java @@ -115,7 +115,7 @@ public class GeyserCustomItemData implements CustomItemData { return tags; } - public static class CustomItemDataBuilder implements Builder { + public static class Builder implements CustomItemData.Builder { protected String name = null; protected CustomItemOptions customItemOptions = null; diff --git a/core/src/main/java/org/geysermc/geyser/item/GeyserCustomItemOptions.java b/core/src/main/java/org/geysermc/geyser/item/GeyserCustomItemOptions.java index 1434c49d9..966035743 100644 --- a/core/src/main/java/org/geysermc/geyser/item/GeyserCustomItemOptions.java +++ b/core/src/main/java/org/geysermc/geyser/item/GeyserCustomItemOptions.java @@ -37,7 +37,7 @@ public record GeyserCustomItemOptions(TriState unbreakable, boolean defaultItem) implements CustomItemOptions { @SuppressWarnings("OptionalUsedAsFieldOrParameterType") - public static class CustomItemOptionsBuilder implements CustomItemOptions.Builder { + public static class Builder implements CustomItemOptions.Builder { private TriState unbreakable = TriState.NOT_SET; private OptionalInt customModelData = OptionalInt.empty(); private OptionalInt damagePredicate = OptionalInt.empty(); diff --git a/core/src/main/java/org/geysermc/geyser/item/GeyserNonVanillaCustomItemData.java b/core/src/main/java/org/geysermc/geyser/item/GeyserNonVanillaCustomItemData.java index 52b0ee7d0..bb4e60589 100644 --- a/core/src/main/java/org/geysermc/geyser/item/GeyserNonVanillaCustomItemData.java +++ b/core/src/main/java/org/geysermc/geyser/item/GeyserNonVanillaCustomItemData.java @@ -59,7 +59,7 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i private final boolean canAlwaysEat; private final boolean isChargeable; - public GeyserNonVanillaCustomItemData(NonVanillaCustomItemDataBuilder builder) { + public GeyserNonVanillaCustomItemData(Builder builder) { super(builder.name, builder.customItemOptions, builder.displayName, builder.icon, builder.allowOffhand, builder.displayHandheld, builder.textureSize, builder.renderOffsets, builder.tags); @@ -168,7 +168,7 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i return isChargeable; } - public static class NonVanillaCustomItemDataBuilder extends GeyserCustomItemData.CustomItemDataBuilder implements NonVanillaCustomItemData.Builder { + public static class Builder extends GeyserCustomItemData.Builder implements NonVanillaCustomItemData.Builder { private String identifier = null; private int javaId = -1; @@ -197,49 +197,49 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i private boolean chargeable = false; @Override - public NonVanillaCustomItemData.Builder name(@NonNull String name) { - return (NonVanillaCustomItemData.Builder) super.name(name); + public Builder name(@NonNull String name) { + return (Builder) super.name(name); } @Override - public NonVanillaCustomItemData.Builder customItemOptions(@NonNull CustomItemOptions customItemOptions) { + public Builder customItemOptions(@NonNull CustomItemOptions customItemOptions) { //Do nothing, as that value won't be read return this; } @Override - public NonVanillaCustomItemData.Builder allowOffhand(boolean allowOffhand) { - return (NonVanillaCustomItemData.Builder) super.allowOffhand(allowOffhand); + public Builder allowOffhand(boolean allowOffhand) { + return (Builder) super.allowOffhand(allowOffhand); } @Override - public NonVanillaCustomItemData.Builder displayHandheld(boolean displayHandheld) { - return (NonVanillaCustomItemData.Builder) super.displayHandheld(displayHandheld); + public Builder displayHandheld(boolean displayHandheld) { + return (Builder) super.displayHandheld(displayHandheld); } @Override - public NonVanillaCustomItemData.Builder displayName(@NonNull String displayName) { - return (NonVanillaCustomItemData.Builder) super.displayName(displayName); + public Builder displayName(@NonNull String displayName) { + return (Builder) super.displayName(displayName); } @Override - public NonVanillaCustomItemData.Builder icon(@NonNull String icon) { - return (NonVanillaCustomItemData.Builder) super.icon(icon); + public Builder icon(@NonNull String icon) { + return (Builder) super.icon(icon); } @Override - public NonVanillaCustomItemData.Builder textureSize(int textureSize) { - return (NonVanillaCustomItemData.Builder) super.textureSize(textureSize); + public Builder textureSize(int textureSize) { + return (Builder) super.textureSize(textureSize); } @Override - public NonVanillaCustomItemData.Builder renderOffsets(CustomRenderOffsets renderOffsets) { - return (NonVanillaCustomItemData.Builder) super.renderOffsets(renderOffsets); + public Builder renderOffsets(CustomRenderOffsets renderOffsets) { + return (Builder) super.renderOffsets(renderOffsets); } @Override - public NonVanillaCustomItemData.Builder tags(@Nullable Set tags) { - return (NonVanillaCustomItemData.Builder) super.tags(tags); + public Builder tags(@Nullable Set tags) { + return (Builder) super.tags(tags); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockComponents.java b/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockComponents.java index e401567e2..1fa863d55 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockComponents.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockComponents.java @@ -62,7 +62,7 @@ public class GeyserCustomBlockComponents implements CustomBlockComponents { boolean placeAir; Set tags; - private GeyserCustomBlockComponents(CustomBlockComponentsBuilder builder) { + private GeyserCustomBlockComponents(Builder builder) { this.selectionBox = builder.selectionBox; this.collisionBox = builder.collisionBox; this.displayName = builder.displayName; @@ -157,7 +157,7 @@ public class GeyserCustomBlockComponents implements CustomBlockComponents { return tags; } - public static class CustomBlockComponentsBuilder implements Builder { + public static class Builder implements CustomBlockComponents.Builder { protected BoxComponent selectionBox; protected BoxComponent collisionBox; protected String displayName; diff --git a/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockData.java b/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockData.java index dd58ebcb7..d717e33c5 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockData.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockData.java @@ -54,7 +54,7 @@ public class GeyserCustomBlockData implements CustomBlockData { private final Map defaultProperties; - GeyserCustomBlockData(CustomBlockDataBuilder builder) { + GeyserCustomBlockData(Builder builder) { this.name = builder.name; if (name == null) { throw new IllegalStateException("Name must be set"); @@ -141,10 +141,10 @@ public class GeyserCustomBlockData implements CustomBlockData { @Override public CustomBlockState.@NonNull Builder blockStateBuilder() { - return new GeyserCustomBlockState.CustomBlockStateBuilder(this); + return new GeyserCustomBlockState.Builder(this); } - public static class CustomBlockDataBuilder implements Builder { + public static class Builder implements CustomBlockData.Builder { private String name; private boolean includedInCreativeInventory; private CreativeCategory creativeCategory; diff --git a/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockState.java b/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockState.java index d147ffedc..b9a8fe5a2 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockState.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockState.java @@ -64,7 +64,7 @@ public class GeyserCustomBlockState implements CustomBlockState { } @RequiredArgsConstructor - public static class CustomBlockStateBuilder implements CustomBlockState.Builder { + public static class Builder implements CustomBlockState.Builder { private final CustomBlockData blockData; private final Object2ObjectMap properties = new Object2ObjectOpenHashMap<>(); diff --git a/core/src/main/java/org/geysermc/geyser/level/block/GeyserGeometryComponent.java b/core/src/main/java/org/geysermc/geyser/level/block/GeyserGeometryComponent.java index c23fc87a2..1e2d13ae6 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/GeyserGeometryComponent.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/GeyserGeometryComponent.java @@ -37,7 +37,7 @@ public class GeyserGeometryComponent implements GeometryComponent { private final String identifier; private final Map boneVisibility; - GeyserGeometryComponent(GeometryComponentBuilder builder) { + GeyserGeometryComponent(Builder builder) { this.identifier = builder.identifier; this.boneVisibility = builder.boneVisibility; } @@ -52,18 +52,18 @@ public class GeyserGeometryComponent implements GeometryComponent { return boneVisibility; } - public static class GeometryComponentBuilder implements Builder { + public static class Builder implements GeometryComponent.Builder { private String identifier; private Map boneVisibility; @Override - public GeometryComponent.Builder identifier(@NonNull String identifier) { + public Builder identifier(@NonNull String identifier) { this.identifier = identifier; return this; } @Override - public GeometryComponent.Builder boneVisibility(@Nullable Map boneVisibility) { + public Builder boneVisibility(@Nullable Map boneVisibility) { this.boneVisibility = boneVisibility; return this; } diff --git a/core/src/main/java/org/geysermc/geyser/level/block/GeyserJavaBlockState.java b/core/src/main/java/org/geysermc/geyser/level/block/GeyserJavaBlockState.java index 5604a543e..8028a4355 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/GeyserJavaBlockState.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/GeyserJavaBlockState.java @@ -18,7 +18,7 @@ public class GeyserJavaBlockState implements JavaBlockState { String pistonBehavior; boolean hasBlockEntity; - private GeyserJavaBlockState(JavaBlockStateBuilder builder) { + private GeyserJavaBlockState(Builder builder) { this.identifier = builder.identifier; this.javaId = builder.javaId; this.stateGroupId = builder.stateGroupId; @@ -81,7 +81,7 @@ public class GeyserJavaBlockState implements JavaBlockState { return hasBlockEntity; } - public static class JavaBlockStateBuilder implements Builder { + public static class Builder implements JavaBlockState.Builder { private String identifier; private int javaId; private int stateGroupId; diff --git a/core/src/main/java/org/geysermc/geyser/level/block/GeyserMaterialInstance.java b/core/src/main/java/org/geysermc/geyser/level/block/GeyserMaterialInstance.java index 527b8fe79..acc16bf58 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/GeyserMaterialInstance.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/GeyserMaterialInstance.java @@ -36,7 +36,7 @@ public class GeyserMaterialInstance implements MaterialInstance { private final boolean faceDimming; private final boolean ambientOcclusion; - GeyserMaterialInstance(MaterialInstanceBuilder builder) { + GeyserMaterialInstance(Builder builder) { this.texture = builder.texture; this.renderMethod = builder.renderMethod; this.faceDimming = builder.faceDimming; @@ -63,7 +63,7 @@ public class GeyserMaterialInstance implements MaterialInstance { return ambientOcclusion; } - public static class MaterialInstanceBuilder implements Builder { + public static class Builder implements MaterialInstance.Builder { private String texture; private String renderMethod; private boolean faceDimming; diff --git a/core/src/main/java/org/geysermc/geyser/level/block/GeyserNonVanillaCustomBlockData.java b/core/src/main/java/org/geysermc/geyser/level/block/GeyserNonVanillaCustomBlockData.java index 8b5056a6f..1f557d0b0 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/GeyserNonVanillaCustomBlockData.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/GeyserNonVanillaCustomBlockData.java @@ -37,7 +37,7 @@ import java.util.List; public class GeyserNonVanillaCustomBlockData extends GeyserCustomBlockData implements NonVanillaCustomBlockData { private final String namespace; - GeyserNonVanillaCustomBlockData(NonVanillaCustomBlockDataBuilder builder) { + GeyserNonVanillaCustomBlockData(Builder builder) { super(builder); this.namespace = builder.namespace; @@ -56,58 +56,58 @@ public class GeyserNonVanillaCustomBlockData extends GeyserCustomBlockData imple return this.namespace; } - public static class NonVanillaCustomBlockDataBuilder extends CustomBlockDataBuilder implements NonVanillaCustomBlockData.Builder { + public static class Builder extends GeyserCustomBlockData.Builder implements NonVanillaCustomBlockData.Builder { private String namespace; @Override - public NonVanillaCustomBlockDataBuilder namespace(@NonNull String namespace) { + public Builder namespace(@NonNull String namespace) { this.namespace = namespace; return this; } @Override - public NonVanillaCustomBlockDataBuilder name(@NonNull String name) { - return (NonVanillaCustomBlockDataBuilder) super.name(name); + public Builder name(@NonNull String name) { + return (Builder) super.name(name); } @Override - public NonVanillaCustomBlockDataBuilder includedInCreativeInventory(boolean includedInCreativeInventory) { - return (NonVanillaCustomBlockDataBuilder) super.includedInCreativeInventory(includedInCreativeInventory); + public Builder includedInCreativeInventory(boolean includedInCreativeInventory) { + return (Builder) super.includedInCreativeInventory(includedInCreativeInventory); } @Override - public NonVanillaCustomBlockDataBuilder creativeCategory(@Nullable CreativeCategory creativeCategories) { - return (NonVanillaCustomBlockDataBuilder) super.creativeCategory(creativeCategories); + public Builder creativeCategory(@Nullable CreativeCategory creativeCategories) { + return (Builder) super.creativeCategory(creativeCategories); } @Override - public NonVanillaCustomBlockDataBuilder creativeGroup(@Nullable String creativeGroup) { - return (NonVanillaCustomBlockDataBuilder) super.creativeGroup(creativeGroup); + public Builder creativeGroup(@Nullable String creativeGroup) { + return (Builder) super.creativeGroup(creativeGroup); } @Override - public NonVanillaCustomBlockDataBuilder components(@NonNull CustomBlockComponents components) { - return (NonVanillaCustomBlockDataBuilder) super.components(components); + public Builder components(@NonNull CustomBlockComponents components) { + return (Builder) super.components(components); } @Override - public NonVanillaCustomBlockDataBuilder booleanProperty(@NonNull String propertyName) { - return (NonVanillaCustomBlockDataBuilder) super.booleanProperty(propertyName); + public Builder booleanProperty(@NonNull String propertyName) { + return (Builder) super.booleanProperty(propertyName); } @Override - public NonVanillaCustomBlockDataBuilder intProperty(@NonNull String propertyName, List values) { - return (NonVanillaCustomBlockDataBuilder) super.intProperty(propertyName, values); + public Builder intProperty(@NonNull String propertyName, List values) { + return (Builder) super.intProperty(propertyName, values); } @Override - public NonVanillaCustomBlockDataBuilder stringProperty(@NonNull String propertyName, List values) { - return (NonVanillaCustomBlockDataBuilder) super.stringProperty(propertyName, values); + public Builder stringProperty(@NonNull String propertyName, List values) { + return (Builder) super.stringProperty(propertyName, values); } @Override - public NonVanillaCustomBlockDataBuilder permutations(@NonNull List permutations) { - return (NonVanillaCustomBlockDataBuilder) super.permutations(permutations); + public Builder permutations(@NonNull List permutations) { + return (Builder) super.permutations(permutations); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/network/LoggingPacketHandler.java b/core/src/main/java/org/geysermc/geyser/network/LoggingPacketHandler.java index cf794261b..0cfcc3d46 100644 --- a/core/src/main/java/org/geysermc/geyser/network/LoggingPacketHandler.java +++ b/core/src/main/java/org/geysermc/geyser/network/LoggingPacketHandler.java @@ -100,6 +100,16 @@ public class LoggingPacketHandler implements BedrockPacketHandler { return defaultHandler(packet); } + @Override + public PacketSignal handle(CameraPresetsPacket packet) { + return defaultHandler(packet); + } + + @Override + public PacketSignal handle(CameraInstructionPacket packet) { + return defaultHandler(packet); + } + @Override public PacketSignal handle(CommandBlockUpdatePacket packet) { return defaultHandler(packet); diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/ProviderRegistryLoader.java b/core/src/main/java/org/geysermc/geyser/registry/loader/ProviderRegistryLoader.java index 13d7a4d77..4b159438c 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/loader/ProviderRegistryLoader.java +++ b/core/src/main/java/org/geysermc/geyser/registry/loader/ProviderRegistryLoader.java @@ -25,6 +25,8 @@ package org.geysermc.geyser.registry.loader; +import org.geysermc.geyser.api.bedrock.camera.CameraFade; +import org.geysermc.geyser.api.bedrock.camera.CameraPosition; import org.geysermc.geyser.api.block.custom.CustomBlockData; import org.geysermc.geyser.api.block.custom.NonVanillaCustomBlockData; import org.geysermc.geyser.api.block.custom.component.CustomBlockComponents; @@ -38,6 +40,8 @@ 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.api.pack.PathPackCodec; +import org.geysermc.geyser.impl.camera.GeyserCameraFade; +import org.geysermc.geyser.impl.camera.GeyserCameraPosition; import org.geysermc.geyser.command.GeyserCommandManager; import org.geysermc.geyser.event.GeyserEventRegistrar; import org.geysermc.geyser.item.GeyserCustomItemData; @@ -65,20 +69,24 @@ public class ProviderRegistryLoader implements RegistryLoader, Prov // misc providers.put(Command.Builder.class, args -> new GeyserCommandManager.CommandBuilder<>((Extension) args[0])); - providers.put(CustomBlockComponents.Builder.class, args -> new GeyserCustomBlockComponents.CustomBlockComponentsBuilder()); - providers.put(CustomBlockData.Builder.class, args -> new GeyserCustomBlockData.CustomBlockDataBuilder()); - providers.put(JavaBlockState.Builder.class, args -> new GeyserJavaBlockState.JavaBlockStateBuilder()); - providers.put(NonVanillaCustomBlockData.Builder.class, args -> new GeyserNonVanillaCustomBlockData.NonVanillaCustomBlockDataBuilder()); - providers.put(MaterialInstance.Builder.class, args -> new GeyserMaterialInstance.MaterialInstanceBuilder()); - providers.put(GeometryComponent.Builder.class, args -> new GeyserGeometryComponent.GeometryComponentBuilder()); + providers.put(CustomBlockComponents.Builder.class, args -> new GeyserCustomBlockComponents.Builder()); + providers.put(CustomBlockData.Builder.class, args -> new GeyserCustomBlockData.Builder()); + providers.put(JavaBlockState.Builder.class, args -> new GeyserJavaBlockState.Builder()); + providers.put(NonVanillaCustomBlockData.Builder.class, args -> new GeyserNonVanillaCustomBlockData.Builder()); + providers.put(MaterialInstance.Builder.class, args -> new GeyserMaterialInstance.Builder()); + providers.put(GeometryComponent.Builder.class, args -> new GeyserGeometryComponent.Builder()); providers.put(EventRegistrar.class, args -> new GeyserEventRegistrar(args[0])); providers.put(PathPackCodec.class, args -> new GeyserPathPackCodec((Path) args[0])); // items - providers.put(CustomItemData.Builder.class, args -> new GeyserCustomItemData.CustomItemDataBuilder()); - providers.put(CustomItemOptions.Builder.class, args -> new GeyserCustomItemOptions.CustomItemOptionsBuilder()); - providers.put(NonVanillaCustomItemData.Builder.class, args -> new GeyserNonVanillaCustomItemData.NonVanillaCustomItemDataBuilder()); + providers.put(CustomItemData.Builder.class, args -> new GeyserCustomItemData.Builder()); + providers.put(CustomItemOptions.Builder.class, args -> new GeyserCustomItemOptions.Builder()); + providers.put(NonVanillaCustomItemData.Builder.class, args -> new GeyserNonVanillaCustomItemData.Builder()); + + // cameras + providers.put(CameraFade.Builder.class, args -> new GeyserCameraFade.Builder()); + providers.put(CameraPosition.Builder.class, args -> new GeyserCameraPosition.Builder()); return providers; } diff --git a/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java b/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java index 1a498c3fa..0bc55c7b1 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java +++ b/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java @@ -35,17 +35,22 @@ import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.block.custom.CustomBlockData; import org.geysermc.geyser.api.block.custom.CustomBlockPermutation; import org.geysermc.geyser.api.block.custom.CustomBlockState; -import org.geysermc.geyser.api.block.custom.component.*; +import org.geysermc.geyser.api.block.custom.component.BoxComponent; +import org.geysermc.geyser.api.block.custom.component.CustomBlockComponents; +import org.geysermc.geyser.api.block.custom.component.GeometryComponent; +import org.geysermc.geyser.api.block.custom.component.MaterialInstance; +import org.geysermc.geyser.api.block.custom.component.PlacementConditions; import org.geysermc.geyser.api.block.custom.component.PlacementConditions.BlockFilterType; import org.geysermc.geyser.api.block.custom.component.PlacementConditions.Face; +import org.geysermc.geyser.api.block.custom.component.TransformationComponent; import org.geysermc.geyser.api.item.custom.CustomItemData; import org.geysermc.geyser.api.item.custom.CustomItemOptions; import org.geysermc.geyser.api.util.CreativeCategory; import org.geysermc.geyser.item.exception.InvalidCustomMappingsFileException; -import org.geysermc.geyser.level.block.GeyserCustomBlockComponents.CustomBlockComponentsBuilder; -import org.geysermc.geyser.level.block.GeyserCustomBlockData.CustomBlockDataBuilder; -import org.geysermc.geyser.level.block.GeyserGeometryComponent.GeometryComponentBuilder; -import org.geysermc.geyser.level.block.GeyserMaterialInstance.MaterialInstanceBuilder; +import org.geysermc.geyser.level.block.GeyserCustomBlockComponents; +import org.geysermc.geyser.level.block.GeyserCustomBlockData; +import org.geysermc.geyser.level.block.GeyserGeometryComponent; +import org.geysermc.geyser.level.block.GeyserMaterialInstance; import org.geysermc.geyser.level.physics.BoundingBox; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.mappings.util.CustomBlockComponentsMapping; @@ -57,7 +62,14 @@ import org.geysermc.geyser.util.BlockUtils; import org.geysermc.geyser.util.MathUtils; import java.nio.file.Path; -import java.util.*; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.function.BiConsumer; import java.util.function.Function; import java.util.function.Predicate; @@ -248,7 +260,7 @@ public class MappingsReader_v1 extends MappingsReader { boolean onlyOverrideStates = node.has("only_override_states") && node.get("only_override_states").asBoolean(); // Create the data for the overall block - CustomBlockData.Builder customBlockDataBuilder = new CustomBlockDataBuilder() + CustomBlockData.Builder customBlockDataBuilder = new GeyserCustomBlockData.Builder() .name(name) .includedInCreativeInventory(includedInCreativeInventory) .creativeCategory(creativeCategory) @@ -360,7 +372,7 @@ public class MappingsReader_v1 extends MappingsReader { int id = BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(stateKey, -1); BoxComponent boxComponent = createBoxComponent(id); BoxComponent extendedBoxComponent = createExtendedBoxComponent(id); - CustomBlockComponents.Builder builder = new CustomBlockComponentsBuilder() + CustomBlockComponents.Builder builder = new GeyserCustomBlockComponents.Builder() .collisionBox(boxComponent) .selectionBox(boxComponent); @@ -392,12 +404,12 @@ public class MappingsReader_v1 extends MappingsReader { if (node.has("geometry")) { if (node.get("geometry").isTextual()) { - builder.geometry(new GeometryComponentBuilder() + builder.geometry(new GeyserGeometryComponent.Builder() .identifier(node.get("geometry").asText()) .build()); } else { JsonNode geometry = node.get("geometry"); - GeometryComponentBuilder geometryBuilder = new GeometryComponentBuilder(); + GeometryComponent.Builder geometryBuilder = new GeyserGeometryComponent.Builder(); if (geometry.has("identifier")) { geometryBuilder.identifier(geometry.get("identifier").asText()); } @@ -654,7 +666,7 @@ public class MappingsReader_v1 extends MappingsReader { ambientOcclusion = node.get("ambient_occlusion").asBoolean(); } - return new MaterialInstanceBuilder() + return new GeyserMaterialInstance.Builder() .texture(texture) .renderMethod(renderMethod) .faceDimming(faceDimming) diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java index e4f45ac85..2a9948f45 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java @@ -23,11 +23,11 @@ import org.geysermc.geyser.api.block.custom.property.CustomBlockProperty; import org.geysermc.geyser.api.block.custom.property.PropertyType; import org.geysermc.geyser.api.event.lifecycle.GeyserDefineCustomBlocksEvent; import org.geysermc.geyser.api.util.CreativeCategory; +import org.geysermc.geyser.level.block.GeyserCustomBlockComponents; +import org.geysermc.geyser.level.block.GeyserCustomBlockData; import org.geysermc.geyser.level.block.GeyserCustomBlockState; -import org.geysermc.geyser.level.block.GeyserCustomBlockComponents.CustomBlockComponentsBuilder; -import org.geysermc.geyser.level.block.GeyserCustomBlockData.CustomBlockDataBuilder; -import org.geysermc.geyser.level.block.GeyserGeometryComponent.GeometryComponentBuilder; -import org.geysermc.geyser.level.block.GeyserMaterialInstance.MaterialInstanceBuilder; +import org.geysermc.geyser.level.block.GeyserGeometryComponent; +import org.geysermc.geyser.level.block.GeyserMaterialInstance; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.mappings.MappingsConfigReader; import org.geysermc.geyser.registry.type.CustomSkull; @@ -479,20 +479,20 @@ public class CustomBlockRegistryPopulator { } private static CustomBlockData createExtendedCollisionBlock(BoxComponent boxComponent, int extendedCollisionBlock) { - return new CustomBlockDataBuilder() + return new GeyserCustomBlockData.Builder() .name("extended_collision_" + extendedCollisionBlock) .components( - new CustomBlockComponentsBuilder() + new GeyserCustomBlockComponents.Builder() .collisionBox(boxComponent) .selectionBox(BoxComponent.emptyBox()) - .materialInstance("*", new MaterialInstanceBuilder() + .materialInstance("*", new GeyserMaterialInstance.Builder() .texture("glass") .renderMethod("alpha_test") .faceDimming(false) .ambientOcclusion(false) .build()) .lightDampening(0) - .geometry(new GeometryComponentBuilder() + .geometry(new GeyserGeometryComponent.Builder() .identifier("geometry.invisible") .build()) .build()) diff --git a/core/src/main/java/org/geysermc/geyser/registry/type/CustomSkull.java b/core/src/main/java/org/geysermc/geyser/registry/type/CustomSkull.java index 5fe8a0edf..9e85f30ff 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/type/CustomSkull.java +++ b/core/src/main/java/org/geysermc/geyser/registry/type/CustomSkull.java @@ -34,8 +34,8 @@ import org.geysermc.geyser.api.block.custom.component.CustomBlockComponents; import org.geysermc.geyser.api.block.custom.component.TransformationComponent; import org.geysermc.geyser.level.block.GeyserCustomBlockComponents; import org.geysermc.geyser.level.block.GeyserCustomBlockData; -import org.geysermc.geyser.level.block.GeyserGeometryComponent.GeometryComponentBuilder; -import org.geysermc.geyser.level.block.GeyserMaterialInstance.MaterialInstanceBuilder; +import org.geysermc.geyser.level.block.GeyserGeometryComponent; +import org.geysermc.geyser.level.block.GeyserMaterialInstance; import java.util.ArrayList; import java.util.List; @@ -65,9 +65,9 @@ public class CustomSkull { public CustomSkull(String skinHash) { this.skinHash = skinHash; - CustomBlockComponents components = new GeyserCustomBlockComponents.CustomBlockComponentsBuilder() + CustomBlockComponents components = new GeyserCustomBlockComponents.Builder() .destructibleByMining(1.5f) - .materialInstance("*", new MaterialInstanceBuilder() + .materialInstance("*", new GeyserMaterialInstance.Builder() .texture("geyser." + skinHash + "_player_skin") .renderMethod("alpha_test") .faceDimming(true) @@ -82,7 +82,7 @@ public class CustomSkull { addFloorPermutations(permutations); addWallPermutations(permutations); - customBlockData = new GeyserCustomBlockData.CustomBlockDataBuilder() + customBlockData = new GeyserCustomBlockData.Builder() .name("player_skull_" + skinHash) .components(components) .intProperty(BITS_A_PROPERTY, IntStream.rangeClosed(0, 6).boxed().toList()) // This gives us exactly 21 block states @@ -114,8 +114,8 @@ public class CustomSkull { } private void addDefaultPermutation(List permutations) { - CustomBlockComponents components = new GeyserCustomBlockComponents.CustomBlockComponentsBuilder() - .geometry(new GeometryComponentBuilder() + CustomBlockComponents components = new GeyserCustomBlockComponents.Builder() + .geometry(new GeyserGeometryComponent.Builder() .identifier("geometry.geyser.player_skull_hand") .build()) .transformation(new TransformationComponent(0, 180, 0)) @@ -131,10 +131,10 @@ public class CustomSkull { for (int quadrant = 0; quadrant < 4; quadrant++) { for (int i = 0; i < 4; i++) { int floorRotation = 4 * quadrant + i; - CustomBlockComponents components = new GeyserCustomBlockComponents.CustomBlockComponentsBuilder() + CustomBlockComponents components = new GeyserCustomBlockComponents.Builder() .selectionBox(FLOOR_BOX) .collisionBox(FLOOR_BOX) - .geometry(new GeometryComponentBuilder() + .geometry(new GeyserGeometryComponent.Builder() .identifier("geometry.geyser.player_skull_floor_" + quadrantNames[i]) .build()) .transformation(new TransformationComponent(0, ROTATIONS[quadrant], 0)) @@ -150,10 +150,10 @@ public class CustomSkull { private void addWallPermutations(List permutations) { for (int i = 0; i < 4; i++) { - CustomBlockComponents components = new GeyserCustomBlockComponents.CustomBlockComponentsBuilder() + CustomBlockComponents components = new GeyserCustomBlockComponents.Builder() .selectionBox(WALL_BOX) .collisionBox(WALL_BOX) - .geometry(new GeometryComponentBuilder() + .geometry(new GeyserGeometryComponent.Builder() .identifier("geometry.geyser.player_skull_wall") .build()) .transformation(new TransformationComponent(0, ROTATIONS[i], 0)) diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 5501e990e..d40b07939 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -101,8 +101,10 @@ import org.geysermc.floodgate.crypto.FloodgateCipher; import org.geysermc.floodgate.util.BedrockData; import org.geysermc.geyser.Constants; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.bedrock.camera.CameraData; import org.geysermc.geyser.api.bedrock.camera.CameraShake; import org.geysermc.geyser.api.connection.GeyserConnection; +import org.geysermc.geyser.api.entity.EntityData; import org.geysermc.geyser.api.entity.type.GeyserEntity; import org.geysermc.geyser.api.entity.type.player.GeyserPlayerEntity; import org.geysermc.geyser.api.event.bedrock.SessionDisconnectEvent; @@ -110,10 +112,13 @@ import org.geysermc.geyser.api.event.bedrock.SessionLoginEvent; import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.api.network.RemoteServer; import org.geysermc.geyser.api.util.PlatformType; +import org.geysermc.geyser.impl.camera.CameraDefinitions; +import org.geysermc.geyser.impl.camera.GeyserCameraData; import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.configuration.EmoteOffhandWorkaroundOption; import org.geysermc.geyser.configuration.GeyserConfiguration; import org.geysermc.geyser.entity.EntityDefinitions; +import org.geysermc.geyser.entity.GeyserEntityData; import org.geysermc.geyser.entity.attribute.GeyserAttributeType; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.ItemFrameEntity; @@ -151,7 +156,16 @@ import java.net.ConnectException; import java.net.InetSocketAddress; import java.nio.charset.StandardCharsets; import java.time.Instant; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.BitSet; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.Set; +import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ScheduledFuture; @@ -550,11 +564,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { @Setter private boolean waitingForStatistics = false; - /** - * All fog effects that are currently applied to the client. - */ - private final Set appliedFog = new HashSet<>(); - private final Set emotes; /** @@ -586,6 +595,10 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { */ private final Queue keepAliveCache = new ConcurrentLinkedQueue<>(); + private final GeyserCameraData cameraData; + + private final GeyserEntityData entityData; + private MinecraftProtocol protocol; public GeyserSession(GeyserImpl geyser, BedrockServerSession bedrockServerSession, EventLoop eventLoop) { @@ -607,6 +620,8 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { this.skullCache = new SkullCache(this); this.tagCache = new TagCache(); this.worldCache = new WorldCache(this); + this.cameraData = new GeyserCameraData(this); + this.entityData = new GeyserEntityData(this); this.worldBorder = new WorldBorder(this); @@ -667,6 +682,10 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { entityPacket.setIdentifiers(Registries.BEDROCK_ENTITY_IDENTIFIERS.get()); upstream.sendPacket(entityPacket); + CameraPresetsPacket cameraPresetsPacket = new CameraPresetsPacket(); + cameraPresetsPacket.getPresets().addAll(CameraDefinitions.CAMERA_PRESETS); + upstream.sendPacket(cameraPresetsPacket); + CreativeContentPacket creativePacket = new CreativeContentPacket(); creativePacket.setContents(this.itemMappings.getCreativeItems()); upstream.sendPacket(creativePacket); @@ -1182,12 +1201,12 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { // Set the mood if (shouldShowFog && !isInWorldBorderWarningArea) { isInWorldBorderWarningArea = true; - sendFog("minecraft:fog_crimson_forest"); + camera().sendFog("minecraft:fog_crimson_forest"); } } if (!shouldShowFog && isInWorldBorderWarningArea) { // Clear fog as we are outside the world border now - removeFog("minecraft:fog_crimson_forest"); + camera().removeFog("minecraft:fog_crimson_forest"); isInWorldBorderWarningArea = false; } @@ -1480,6 +1499,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { private void startGame() { this.upstream.getCodecHelper().setItemDefinitions(this.itemMappings); this.upstream.getCodecHelper().setBlockDefinitions((DefinitionRegistry) this.blockMappings); //FIXME + this.upstream.getCodecHelper().setCameraPresetDefinitions(CameraDefinitions.CAMERA_DEFINITIONS); StartGamePacket startGamePacket = new StartGamePacket(); startGamePacket.setUniqueEntityId(playerEntity.getGeyserId()); @@ -1980,72 +2000,66 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { @Override public @NonNull CompletableFuture<@Nullable GeyserEntity> entityByJavaId(@NonNegative int javaId) { - CompletableFuture future = new CompletableFuture<>(); - ensureInEventLoop(() -> future.complete(this.entityCache.getEntityByJavaId(javaId))); - return future; + return entities().entityByJavaId(javaId); } @Override public void showEmote(@NonNull GeyserPlayerEntity emoter, @NonNull String emoteId) { - Entity entity = (Entity) emoter; - if (entity.getSession() != this) { - throw new IllegalStateException("Given entity must be from this session!"); + entities().showEmote(emoter, emoteId); + } + + public void lockInputs(boolean camera, boolean movement) { + UpdateClientInputLocksPacket packet = new UpdateClientInputLocksPacket(); + final int cameraOffset = 1 << 1; + final int movementOffset = 1 << 2; + + int result = 0; + if (camera) { + result |= cameraOffset; + } + if (movement) { + result |= movementOffset; } - EmotePacket packet = new EmotePacket(); - packet.setRuntimeEntityId(entity.getGeyserId()); - packet.setXuid(""); - packet.setPlatformId(""); // BDS sends empty - packet.setEmoteId(emoteId); + packet.setLockComponentData(result); + packet.setServerPosition(this.playerEntity.getPosition()); + sendUpstreamPacket(packet); } + @Override + public @NonNull CameraData camera() { + return this.cameraData; + } + + @Override + public @NonNull EntityData entities() { + return this.entityData; + } + @Override public void shakeCamera(float intensity, float duration, @NonNull CameraShake type) { - CameraShakePacket packet = new CameraShakePacket(); - packet.setIntensity(intensity); - packet.setDuration(duration); - packet.setShakeType(type == CameraShake.POSITIONAL ? CameraShakeType.POSITIONAL : CameraShakeType.ROTATIONAL); - packet.setShakeAction(CameraShakeAction.ADD); - sendUpstreamPacket(packet); + this.cameraData.shakeCamera(intensity, duration, type); } @Override public void stopCameraShake() { - CameraShakePacket packet = new CameraShakePacket(); - // CameraShakeAction.STOP removes all types regardless of the given type, but regardless it can't be null - packet.setShakeType(CameraShakeType.POSITIONAL); - packet.setShakeAction(CameraShakeAction.STOP); - sendUpstreamPacket(packet); + this.cameraData.stopCameraShake(); } @Override public void sendFog(String... fogNameSpaces) { - Collections.addAll(this.appliedFog, fogNameSpaces); - - PlayerFogPacket packet = new PlayerFogPacket(); - packet.getFogStack().addAll(this.appliedFog); - sendUpstreamPacket(packet); + this.cameraData.sendFog(fogNameSpaces); } @Override public void removeFog(String... fogNameSpaces) { - if (fogNameSpaces.length == 0) { - this.appliedFog.clear(); - } else { - for (String id : fogNameSpaces) { - this.appliedFog.remove(id); - } - } - PlayerFogPacket packet = new PlayerFogPacket(); - packet.getFogStack().addAll(this.appliedFog); - sendUpstreamPacket(packet); + this.cameraData.removeFog(fogNameSpaces); } @Override public @NonNull Set fogEffects() { - // Use a copy so that sendFog/removeFog can be called while iterating the returned set (avoid CME) - return Set.copyOf(this.appliedFog); + return this.cameraData.fogEffects(); } public void addCommandEnum(String name, String enums) { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java index 377f1d2cf..23c19e84f 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java @@ -139,7 +139,7 @@ public class JavaLoginTranslator extends PacketTranslator Date: Fri, 2 Feb 2024 23:25:50 +0800 Subject: [PATCH 179/344] =?UTF-8?q?Use=20multiple=20channels=20at=20startu?= =?UTF-8?q?p,=20fix=20the=20occasional=20issue=20of=20all=20pla=E2=80=A6?= =?UTF-8?q?=20(#4329)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Use multiple channels at startup, fix the occasional issue of all players getting disconnected. * Standardized shutdown periods and refactored network handlers for improved consistency. * tiny fix * Let's use the system property --------- Co-authored-by: chris --- .../geyser/network/netty/Bootstraps.java | 130 ++++++++++++++++++ .../geyser/network/netty/GeyserServer.java | 61 ++++---- .../network/netty/handler/RakPingHandler.java | 2 +- 3 files changed, 168 insertions(+), 25 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/network/netty/Bootstraps.java diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/Bootstraps.java b/core/src/main/java/org/geysermc/geyser/network/netty/Bootstraps.java new file mode 100644 index 000000000..9ffc45650 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/network/netty/Bootstraps.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2019-2023 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.network.netty; + +import io.netty.bootstrap.AbstractBootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.epoll.Native; +import io.netty.channel.unix.UnixChannelOption; +import lombok.experimental.UtilityClass; + +import java.util.Optional; +import java.util.concurrent.CompletableFuture; + +@SuppressWarnings("OptionalUsedAsFieldOrParameterType") +@UtilityClass +public final class Bootstraps { + private static final Optional KERNEL_VERSION; + + // The REUSEPORT_AVAILABLE socket option is available starting from kernel version 3.9. + // This option allows multiple sockets to listen on the same IP address and port without conflict. + private static final int[] REUSEPORT_VERSION = new int[]{3, 9, 0}; + private static final boolean REUSEPORT_AVAILABLE; + + static { + String kernelVersion; + try { + kernelVersion = Native.KERNEL_VERSION; + } catch (Throwable e) { + kernelVersion = null; + } + if (kernelVersion != null && kernelVersion.contains("-")) { + int index = kernelVersion.indexOf('-'); + if (index > -1) { + kernelVersion = kernelVersion.substring(0, index); + } + int[] kernelVer = fromString(kernelVersion); + KERNEL_VERSION = Optional.of(kernelVer); + REUSEPORT_AVAILABLE = checkVersion(kernelVer, 0); + } else { + KERNEL_VERSION = Optional.empty(); + REUSEPORT_AVAILABLE = false; + } + } + + public static Optional getKernelVersion() { + return KERNEL_VERSION; + } + + public static boolean isReusePortAvailable() { + return REUSEPORT_AVAILABLE; + } + + @SuppressWarnings({"rawtypes, unchecked"}) + public static void setupBootstrap(AbstractBootstrap bootstrap) { + if (REUSEPORT_AVAILABLE) { + bootstrap.option(UnixChannelOption.SO_REUSEPORT, true); + } + } + + private static int[] fromString(String ver) { + String[] parts = ver.split("\\."); + if (parts.length < 2) { + throw new IllegalArgumentException("At least 2 version numbers required"); + } + + return new int[]{ + Integer.parseInt(parts[0]), + Integer.parseInt(parts[1]), + parts.length == 2 ? 0 : Integer.parseInt(parts[2]) + }; + } + + private static boolean checkVersion(int[] ver, int i) { + if (ver[i] > REUSEPORT_VERSION[i]) { + return true; + } else if (ver[i] == REUSEPORT_VERSION[i]) { + if (ver.length == (i + 1)) { + return true; + } else { + return checkVersion(ver, i + 1); + } + } + return false; + } + + public static CompletableFuture allOf(ChannelFuture... futures) { + if (futures == null || futures.length == 0) { + return CompletableFuture.completedFuture(null); + } + @SuppressWarnings("unchecked") + CompletableFuture[] completableFutures = new CompletableFuture[futures.length]; + for (int i = 0; i < futures.length; i++) { + ChannelFuture channelFuture = futures[i]; + CompletableFuture completableFuture = new CompletableFuture<>(); + channelFuture.addListener(future -> { + if (future.cause() != null) { + completableFuture.completeExceptionally(future.cause()); + } + completableFuture.complete(channelFuture.channel()); + }); + completableFutures[i] = completableFuture; + } + + return CompletableFuture.allOf(completableFutures); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java b/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java index 401a7f2cf..ea1dcb509 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java @@ -94,13 +94,16 @@ public final class GeyserServer { private final GeyserImpl geyser; private EventLoopGroup group; + // Split childGroup may improve IO + private EventLoopGroup childGroup; private final ServerBootstrap bootstrap; private EventLoopGroup playerGroup; @Getter private final ExpiringMap proxiedAddresses; + private final int listenCount; - private ChannelFuture bootstrapFuture; + private ChannelFuture[] bootstrapFutures; /** * The port to broadcast in the pong. This can be different from the port the server is bound to, e.g. due to port forwarding. @@ -109,9 +112,14 @@ public final class GeyserServer { public GeyserServer(GeyserImpl geyser, int threadCount) { this.geyser = geyser; - this.group = TRANSPORT.eventLoopGroupFactory().apply(threadCount); + this.listenCount = Bootstraps.isReusePortAvailable() ? Integer.getInteger("Geyser.ListenCount", 2) : 1; + GeyserImpl.getInstance().getLogger().debug("Listen thread count: " + listenCount); + this.group = TRANSPORT.eventLoopGroupFactory().apply(listenCount); + this.childGroup = TRANSPORT.eventLoopGroupFactory().apply(threadCount); - this.bootstrap = this.createBootstrap(this.group); + this.bootstrap = this.createBootstrap(); + // setup SO_REUSEPORT if exists + Bootstraps.setupBootstrap(this.bootstrap); if (this.geyser.getConfig().getBedrock().isEnableProxyProtocol()) { this.proxiedAddresses = ExpiringMap.builder() @@ -130,46 +138,51 @@ public final class GeyserServer { } public CompletableFuture bind(InetSocketAddress address) { - CompletableFuture future = new CompletableFuture<>(); - this.bootstrapFuture = this.bootstrap.bind(address).addListener(bindResult -> { - if (bindResult.cause() != null) { - future.completeExceptionally(bindResult.cause()); - return; - } - future.complete(null); - }); + bootstrapFutures = new ChannelFuture[listenCount]; + for (int i = 0; i < listenCount; i++) { + ChannelFuture future = bootstrap.bind(address); + addHandlers(future); + bootstrapFutures[i] = future; + } - Channel channel = this.bootstrapFuture.channel(); + return Bootstraps.allOf(bootstrapFutures); + } + private void addHandlers(ChannelFuture future) { + Channel channel = future.channel(); // Add our ping handler channel.pipeline() .addFirst(RakConnectionRequestHandler.NAME, new RakConnectionRequestHandler(this)) .addAfter(RakServerOfflineHandler.NAME, RakPingHandler.NAME, new RakPingHandler(this)); - + // Add proxy handler if (this.geyser.getConfig().getBedrock().isEnableProxyProtocol()) { channel.pipeline().addFirst("proxy-protocol-decoder", new ProxyServerHandler()); } - - return future; } public void shutdown() { try { - Future future1 = this.group.shutdownGracefully(SHUTDOWN_QUIET_PERIOD_MS, SHUTDOWN_TIMEOUT_MS, TimeUnit.MILLISECONDS); + Future futureChildGroup = this.childGroup.shutdownGracefully(SHUTDOWN_QUIET_PERIOD_MS, SHUTDOWN_TIMEOUT_MS, TimeUnit.MILLISECONDS); + this.childGroup = null; + Future futureGroup = this.group.shutdownGracefully(SHUTDOWN_QUIET_PERIOD_MS, SHUTDOWN_TIMEOUT_MS, TimeUnit.MILLISECONDS); this.group = null; - Future future2 = this.playerGroup.shutdownGracefully(SHUTDOWN_QUIET_PERIOD_MS, SHUTDOWN_TIMEOUT_MS, TimeUnit.MILLISECONDS); + Future futurePlayerGroup = this.playerGroup.shutdownGracefully(SHUTDOWN_QUIET_PERIOD_MS, SHUTDOWN_TIMEOUT_MS, TimeUnit.MILLISECONDS); this.playerGroup = null; - future1.sync(); - future2.sync(); + + futureChildGroup.sync(); + futureGroup.sync(); + futurePlayerGroup.sync(); SkinProvider.shutdown(); } catch (InterruptedException e) { GeyserImpl.getInstance().getLogger().severe("Exception in shutdown process", e); } - this.bootstrapFuture.channel().closeFuture().syncUninterruptibly(); + for (ChannelFuture f : bootstrapFutures) { + f.channel().closeFuture().syncUninterruptibly(); + } } - private ServerBootstrap createBootstrap(EventLoopGroup group) { + private ServerBootstrap createBootstrap() { if (this.geyser.getConfig().isDebugMode()) { this.geyser.getLogger().debug("EventLoop type: " + TRANSPORT.datagramChannel()); if (TRANSPORT.datagramChannel() == NioDatagramChannel.class) { @@ -188,7 +201,7 @@ public final class GeyserServer { this.geyser.getLogger().debug("Setting MTU to " + this.geyser.getConfig().getMtu()); return new ServerBootstrap() .channelFactory(RakChannelFactory.server(TRANSPORT.datagramChannel())) - .group(group) + .group(group, childGroup) .option(RakChannelOption.RAK_HANDLE_PING, true) .option(RakChannelOption.RAK_MAX_MTU, this.geyser.getConfig().getMtu()) .childHandler(serverInitializer); @@ -224,7 +237,7 @@ public final class GeyserServer { return true; } - public BedrockPong onQuery(InetSocketAddress inetSocketAddress) { + public BedrockPong onQuery(Channel channel, InetSocketAddress inetSocketAddress) { if (geyser.getConfig().isDebugMode() && PRINT_DEBUG_PINGS) { String ip; if (geyser.getConfig().isLogPlayerIpAddresses()) { @@ -257,7 +270,7 @@ public final class GeyserServer { .version(GameProtocol.DEFAULT_BEDROCK_CODEC.getMinecraftVersion()) // Required to not be empty as of 1.16.210.59. Can only contain . and numbers. .ipv4Port(this.broadcastPort) .ipv6Port(this.broadcastPort) - .serverId(bootstrapFuture.channel().config().getOption(RakChannelOption.RAK_GUID)); + .serverId(channel.config().getOption(RakChannelOption.RAK_GUID)); if (config.isPassthroughMotd() && pingInfo != null && pingInfo.getDescription() != null) { String[] motd = MessageTranslator.convertMessageLenient(pingInfo.getDescription()).split("\n"); diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/handler/RakPingHandler.java b/core/src/main/java/org/geysermc/geyser/network/netty/handler/RakPingHandler.java index e63bf9dd2..62b9c6d12 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/handler/RakPingHandler.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/handler/RakPingHandler.java @@ -45,7 +45,7 @@ public class RakPingHandler extends SimpleChannelInboundHandler { protected void channelRead0(ChannelHandlerContext ctx, RakPing msg) { long guid = ctx.channel().config().getOption(RakChannelOption.RAK_GUID); - RakPong pong = msg.reply(guid, this.server.onQuery(msg.getSender()).toByteBuf()); + RakPong pong = msg.reply(guid, this.server.onQuery(ctx.channel(), msg.getSender()).toByteBuf()); ctx.writeAndFlush(pong); } } From 19a3dc3c4b2f7aa22c9325c32acb22f69f8baaf0 Mon Sep 17 00:00:00 2001 From: chris Date: Tue, 6 Feb 2024 20:11:17 +0100 Subject: [PATCH 180/344] Support Bedrock 1.20.60 (#4415) * Start on 1.20.60 support * fix dimension switching * Fix custom item icons... thanks mojang * fix custom blocks/custom skulls breaking all block mappings * - replace 10000 with static final variable * fix: creative items not being found * versioned custom item registration * fix compression level setting * show 1.20.61 as supported --- .../geysermc/geyser/network/GameProtocol.java | 12 +- .../geyser/network/UpstreamPacketHandler.java | 12 +- .../populator/BlockRegistryPopulator.java | 5 + .../registry/populator/Conversion630_649.java | 40 + .../CreativeItemRegistryPopulator.java | 1 + .../CustomBlockRegistryPopulator.java | 34 +- .../CustomItemRegistryPopulator.java | 36 +- .../CustomSkullRegistryPopulator.java | 2 +- .../populator/ItemRegistryPopulator.java | 34 +- .../JavaLevelChunkWithLightTranslator.java | 2 + .../org/geysermc/geyser/util/ChunkUtils.java | 1 + .../bedrock/block_palette.1_20_60.nbt | Bin 0 -> 124510 bytes .../bedrock/creative_items.1_20_60.json | 5787 ++++++++++++++++ .../bedrock/runtime_item_states.1_20_60.json | 5998 +++++++++++++++++ gradle/libs.versions.toml | 6 +- 15 files changed, 11929 insertions(+), 41 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/registry/populator/Conversion630_649.java create mode 100644 core/src/main/resources/bedrock/block_palette.1_20_60.nbt create mode 100644 core/src/main/resources/bedrock/creative_items.1_20_60.json create mode 100644 core/src/main/resources/bedrock/runtime_item_states.1_20_60.json diff --git a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java index 42cce607b..a03a36ad2 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java @@ -31,6 +31,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; import org.cloudburstmc.protocol.bedrock.codec.v622.Bedrock_v622; import org.cloudburstmc.protocol.bedrock.codec.v630.Bedrock_v630; +import org.cloudburstmc.protocol.bedrock.codec.v649.Bedrock_v649; import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec; import org.geysermc.geyser.session.GeyserSession; @@ -46,7 +47,7 @@ public final class GameProtocol { * Default Bedrock codec that should act as a fallback. Should represent the latest available * release of the game that Geyser supports. */ - public static final BedrockCodec DEFAULT_BEDROCK_CODEC = Bedrock_v630.CODEC; + public static final BedrockCodec DEFAULT_BEDROCK_CODEC = Bedrock_v649.CODEC; /** * A list of all supported Bedrock versions that can join Geyser @@ -63,9 +64,12 @@ public final class GameProtocol { SUPPORTED_BEDROCK_CODECS.add(Bedrock_v622.CODEC.toBuilder() .minecraftVersion("1.20.40/1.20.41") .build()); - SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC.toBuilder() + SUPPORTED_BEDROCK_CODECS.add(Bedrock_v630.CODEC.toBuilder() .minecraftVersion("1.20.50/1.20.51") .build()); + SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC.toBuilder() + .minecraftVersion("1.20.60/1.20.61") + .build()); } /** @@ -88,6 +92,10 @@ public final class GameProtocol { return session.getUpstream().getProtocolVersion() < Bedrock_v630.CODEC.getProtocolVersion(); } + public static boolean is1_20_60orHigher(int protocolVersion) { + return protocolVersion >= Bedrock_v649.CODEC.getProtocolVersion(); + } + /** * Gets the {@link PacketCodec} for Minecraft: Java Edition. * diff --git a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java index 7a22b8a42..df5eb36f7 100644 --- a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java +++ b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java @@ -33,6 +33,9 @@ import org.cloudburstmc.protocol.bedrock.codec.v622.Bedrock_v622; import org.cloudburstmc.protocol.bedrock.data.ExperimentData; import org.cloudburstmc.protocol.bedrock.data.PacketCompressionAlgorithm; import org.cloudburstmc.protocol.bedrock.data.ResourcePackType; +import org.cloudburstmc.protocol.bedrock.netty.codec.compression.CompressionStrategy; +import org.cloudburstmc.protocol.bedrock.netty.codec.compression.SimpleCompressionStrategy; +import org.cloudburstmc.protocol.bedrock.netty.codec.compression.ZlibCompression; import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket; import org.cloudburstmc.protocol.bedrock.packet.LoginPacket; import org.cloudburstmc.protocol.bedrock.packet.ModalFormResponsePacket; @@ -48,6 +51,7 @@ import org.cloudburstmc.protocol.bedrock.packet.ResourcePackStackPacket; import org.cloudburstmc.protocol.bedrock.packet.ResourcePacksInfoPacket; import org.cloudburstmc.protocol.bedrock.packet.SetTitlePacket; import org.cloudburstmc.protocol.common.PacketSignal; +import org.cloudburstmc.protocol.common.util.Zlib; import org.geysermc.geyser.Constants; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.network.AuthType; @@ -77,11 +81,16 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { private boolean networkSettingsRequested = false; private final Deque packsToSent = new ArrayDeque<>(); + private final CompressionStrategy compressionStrategy; private SessionLoadResourcePacksEventImpl resourcePackLoadEvent; public UpstreamPacketHandler(GeyserImpl geyser, GeyserSession session) { super(geyser, session); + + ZlibCompression compression = new ZlibCompression(Zlib.RAW); + compression.setLevel(this.geyser.getConfig().getBedrock().getCompressionLevel()); + this.compressionStrategy = new SimpleCompressionStrategy(compression); } private PacketSignal translateAndDefault(BedrockPacket packet) { @@ -149,9 +158,8 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { responsePacket.setCompressionAlgorithm(algorithm); responsePacket.setCompressionThreshold(512); session.sendUpstreamPacketImmediately(responsePacket); + session.getUpstream().getSession().getPeer().setCompression(compressionStrategy); - session.getUpstream().getSession().setCompression(algorithm); - session.getUpstream().getSession().setCompressionLevel(this.geyser.getConfig().getBedrock().getCompressionLevel()); networkSettingsRequested = true; return PacketSignal.HANDLED; } 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 415e61ac2..8aa16fe48 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 @@ -41,6 +41,7 @@ import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; import org.cloudburstmc.protocol.bedrock.codec.v622.Bedrock_v622; import org.cloudburstmc.protocol.bedrock.codec.v630.Bedrock_v630; +import org.cloudburstmc.protocol.bedrock.codec.v649.Bedrock_v649; import org.cloudburstmc.protocol.bedrock.data.BlockPropertyData; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.geysermc.geyser.GeyserImpl; @@ -118,6 +119,8 @@ public final class BlockRegistryPopulator { var blockMappers = ImmutableMap., Remapper>builder() .put(ObjectIntPair.of("1_20_40", Bedrock_v622.CODEC.getProtocolVersion()), Conversion630_622::remapBlock) .put(ObjectIntPair.of("1_20_50", Bedrock_v630.CODEC.getProtocolVersion()), tag -> tag) + // Only changes in 1.20.60 are hard_stained_glass (an EDU only block) + .put(ObjectIntPair.of("1_20_60", Bedrock_v649.CODEC.getProtocolVersion()), tag -> tag) .build(); // We can keep this strong as nothing should be garbage collected @@ -139,6 +142,7 @@ public final class BlockRegistryPopulator { builder.remove("version"); // Remove all nbt tags which are not needed for differentiating states builder.remove("name_hash"); // Quick workaround - was added in 1.19.20 builder.remove("network_id"); // Added in 1.19.80 - ???? + builder.remove("block_id"); // Added in 1.20.60 //TODO verify this can be just removed //noinspection UnstableApiUsage builder.putCompound("states", statesInterner.intern((NbtMap) builder.remove("states"))); vanillaBlockStates.set(i, builder.build()); @@ -154,6 +158,7 @@ public final class BlockRegistryPopulator { List customExtBlockStates = new ArrayList<>(); int[] remappedVanillaIds = new int[0]; if (BlockRegistries.CUSTOM_BLOCKS.get().length != 0) { + CustomBlockRegistryPopulator.BLOCK_ID.set(CustomBlockRegistryPopulator.START_OFFSET); for (CustomBlockData customBlock : BlockRegistries.CUSTOM_BLOCKS.get()) { customBlockProperties.add(CustomBlockRegistryPopulator.generateBlockPropertyData(customBlock, protocolVersion)); CustomBlockRegistryPopulator.generateCustomBlockStates(customBlock, customBlockStates, customExtBlockStates); diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion630_649.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion630_649.java new file mode 100644 index 000000000..ed66322ff --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion630_649.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2019-2024 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 org.geysermc.geyser.item.type.Item; +import org.geysermc.geyser.registry.type.GeyserMappingItem; + + +public class Conversion630_649 { + + static GeyserMappingItem remapItem(@SuppressWarnings("unused") Item item, GeyserMappingItem mapping) { + if (mapping.getBedrockIdentifier().equalsIgnoreCase("minecraft:scute")) { + return mapping.withBedrockIdentifier("minecraft:turtle_scute"); + } + return mapping; + } +} 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 index d27a2ed49..c536d739c 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/CreativeItemRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/CreativeItemRegistryPopulator.java @@ -124,6 +124,7 @@ public class CreativeItemRegistryPopulator { builder.remove("name_hash"); builder.remove("network_id"); builder.remove("version"); + builder.remove("block_id"); blockDefinition = blockMappings.getDefinition(builder.build()); } catch (IOException e) { diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java index 2a9948f45..ea33450bf 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java @@ -28,12 +28,14 @@ import org.geysermc.geyser.level.block.GeyserCustomBlockData; import org.geysermc.geyser.level.block.GeyserCustomBlockState; import org.geysermc.geyser.level.block.GeyserGeometryComponent; import org.geysermc.geyser.level.block.GeyserMaterialInstance; +import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.mappings.MappingsConfigReader; import org.geysermc.geyser.registry.type.CustomSkull; import org.geysermc.geyser.util.MathUtils; import java.util.ArrayList; +import java.util.concurrent.atomic.AtomicInteger; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -41,6 +43,13 @@ import java.util.Map; import java.util.Set; public class CustomBlockRegistryPopulator { + + // Since 1.20.60, custom blocks need a block_id in their nbt tag + public static AtomicInteger BLOCK_ID = new AtomicInteger(); + + // Custom block id's start at 10000, and count up + public static final int START_OFFSET = 10000; + /** * The stage of population */ @@ -89,7 +98,7 @@ public class CustomBlockRegistryPopulator { GeyserImpl.getInstance().getEventBus().fire(new GeyserDefineCustomBlocksEvent() { @Override public void register(@NonNull CustomBlockData customBlockData) { - if (customBlockData.name().length() == 0) { + if (customBlockData.name().isEmpty()) { throw new IllegalArgumentException("Custom block name must have at least 1 character."); } if (!CUSTOM_BLOCK_NAMES.add(customBlockData.name())) { @@ -179,17 +188,17 @@ public class CustomBlockRegistryPopulator { }); BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.set(blockStateOverrides); - if (blockStateOverrides.size() != 0) { + if (!blockStateOverrides.isEmpty()) { GeyserImpl.getInstance().getLogger().info("Registered " + blockStateOverrides.size() + " custom block overrides."); } BlockRegistries.CUSTOM_BLOCK_ITEM_OVERRIDES.set(CUSTOM_BLOCK_ITEM_OVERRIDES); - if (CUSTOM_BLOCK_ITEM_OVERRIDES.size() != 0) { + if (!CUSTOM_BLOCK_ITEM_OVERRIDES.isEmpty()) { GeyserImpl.getInstance().getLogger().info("Registered " + CUSTOM_BLOCK_ITEM_OVERRIDES.size() + " custom block item overrides."); } BlockRegistries.EXTENDED_COLLISION_BOXES.set(extendedCollisionBoxes); - if (extendedCollisionBoxes.size() != 0) { + if (!extendedCollisionBoxes.isEmpty()) { GeyserImpl.getInstance().getLogger().info("Registered " + extendedCollisionBoxes.size() + " custom block extended collision boxes."); } } @@ -199,7 +208,7 @@ public class CustomBlockRegistryPopulator { */ private static void populateNonVanilla() { BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.set(NON_VANILLA_BLOCK_STATE_OVERRIDES); - if (NON_VANILLA_BLOCK_STATE_OVERRIDES.size() != 0) { + if (!NON_VANILLA_BLOCK_STATE_OVERRIDES.isEmpty()) { GeyserImpl.getInstance().getLogger().info("Registered " + NON_VANILLA_BLOCK_STATE_OVERRIDES.size() + " non-vanilla block overrides."); } } @@ -209,7 +218,7 @@ public class CustomBlockRegistryPopulator { */ private static void registration() { BlockRegistries.CUSTOM_BLOCKS.set(CUSTOM_BLOCKS.toArray(new CustomBlockData[0])); - if (CUSTOM_BLOCKS.size() != 0) { + if (!CUSTOM_BLOCKS.isEmpty()) { GeyserImpl.getInstance().getLogger().info("Registered " + CUSTOM_BLOCKS.size() + " custom blocks."); } } @@ -279,7 +288,7 @@ public class CustomBlockRegistryPopulator { CreativeCategory creativeCategory = customBlock.creativeCategory() != null ? customBlock.creativeCategory() : CreativeCategory.NONE; String creativeGroup = customBlock.creativeGroup() != null ? customBlock.creativeGroup() : ""; - NbtMap propertyTag = NbtMap.builder() + NbtMapBuilder propertyTag = NbtMap.builder() .putCompound("components", CustomBlockRegistryPopulator.convertComponents(customBlock.components(), protocolVersion)) // this is required or the client will crash // in the future, this can be used to replace items in the creative inventory @@ -292,9 +301,14 @@ public class CustomBlockRegistryPopulator { // meaning of this version is unknown, but it's required for tags to work and should probably be checked periodically .putInt("molangVersion", 1) .putList("permutations", NbtType.COMPOUND, permutations) - .putList("properties", NbtType.COMPOUND, properties) - .build(); - return new BlockPropertyData(customBlock.identifier(), propertyTag); + .putList("properties", NbtType.COMPOUND, properties); + + if (GameProtocol.is1_20_60orHigher(protocolVersion)) { + propertyTag.putCompound("vanilla_block_data", NbtMap.builder() + .putInt("block_id", BLOCK_ID.getAndIncrement()) + .build()); + } + return new BlockPropertyData(customBlock.identifier(), propertyTag.build()); } /** 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 6be1aac4c..e1d67399f 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 @@ -44,6 +44,7 @@ import org.geysermc.geyser.item.GeyserCustomMappingData; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.components.WearableSlot; import org.geysermc.geyser.item.type.Item; +import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.registry.mappings.MappingsConfigReader; import org.geysermc.geyser.registry.type.GeyserMappingItem; import org.geysermc.geyser.registry.type.ItemMapping; @@ -97,10 +98,10 @@ public class CustomItemRegistryPopulator { } } - public static GeyserCustomMappingData registerCustomItem(String customItemName, Item javaItem, GeyserMappingItem mapping, CustomItemData customItemData, int bedrockId) { + public static GeyserCustomMappingData registerCustomItem(String customItemName, Item javaItem, GeyserMappingItem mapping, CustomItemData customItemData, int bedrockId, int protocolVersion) { ItemDefinition itemDefinition = new SimpleItemDefinition(customItemName, bedrockId, true); - NbtMapBuilder builder = createComponentNbt(customItemData, javaItem, mapping, customItemName, bedrockId); + NbtMapBuilder builder = createComponentNbt(customItemData, javaItem, mapping, customItemName, bedrockId, protocolVersion); ComponentItemData componentItemData = new ComponentItemData(customItemName, builder.build()); return new GeyserCustomMappingData(componentItemData, itemDefinition, customItemName, bedrockId); @@ -124,7 +125,7 @@ public class CustomItemRegistryPopulator { return true; } - public static NonVanillaItemRegistration registerCustomItem(NonVanillaCustomItemData customItemData, int customItemId) { + public static NonVanillaItemRegistration registerCustomItem(NonVanillaCustomItemData customItemData, int customItemId, int protocolVersion) { String customIdentifier = customItemData.identifier(); Set repairMaterials = customItemData.repairMaterials(); @@ -152,14 +153,14 @@ public class CustomItemRegistryPopulator { .build(); NbtMapBuilder builder = createComponentNbt(customItemData, customItemData.identifier(), customItemId, - customItemData.creativeCategory(), customItemData.creativeGroup(), customItemData.isHat(), customItemData.displayHandheld()); + customItemData.creativeCategory(), customItemData.creativeGroup(), customItemData.isHat(), customItemData.displayHandheld(), protocolVersion); ComponentItemData componentItemData = new ComponentItemData(customIdentifier, builder.build()); return new NonVanillaItemRegistration(componentItemData, item, customItemMapping); } private static NbtMapBuilder createComponentNbt(CustomItemData customItemData, Item javaItem, GeyserMappingItem mapping, - String customItemName, int customItemId) { + String customItemName, int customItemId, int protocolVersion) { NbtMapBuilder builder = NbtMap.builder(); builder.putString("name", customItemName) .putInt("id", customItemId); @@ -167,7 +168,7 @@ public class CustomItemRegistryPopulator { NbtMapBuilder itemProperties = NbtMap.builder(); NbtMapBuilder componentBuilder = NbtMap.builder(); - setupBasicItemInfo(javaItem.maxDamage(), javaItem.maxStackSize(), mapping.getToolType() != null || customItemData.displayHandheld(), customItemData, itemProperties, componentBuilder); + setupBasicItemInfo(javaItem.maxDamage(), javaItem.maxStackSize(), mapping.getToolType() != null || customItemData.displayHandheld(), customItemData, itemProperties, componentBuilder, protocolVersion); boolean canDestroyInCreative = true; if (mapping.getToolType() != null) { // This is not using the isTool boolean because it is not just a render type here. @@ -210,7 +211,7 @@ public class CustomItemRegistryPopulator { @SuppressWarnings("OptionalUsedAsFieldOrParameterType") private static NbtMapBuilder createComponentNbt(NonVanillaCustomItemData customItemData, String customItemName, int customItemId, OptionalInt creativeCategory, - String creativeGroup, boolean isHat, boolean displayHandheld) { + String creativeGroup, boolean isHat, boolean displayHandheld, int protocolVersion) { NbtMapBuilder builder = NbtMap.builder(); builder.putString("name", customItemName) .putInt("id", customItemId); @@ -218,7 +219,7 @@ public class CustomItemRegistryPopulator { NbtMapBuilder itemProperties = NbtMap.builder(); NbtMapBuilder componentBuilder = NbtMap.builder(); - setupBasicItemInfo(customItemData.maxDamage(), customItemData.stackSize(), displayHandheld, customItemData, itemProperties, componentBuilder); + setupBasicItemInfo(customItemData.maxDamage(), customItemData.stackSize(), displayHandheld, customItemData, itemProperties, componentBuilder, protocolVersion); boolean canDestroyInCreative = true; if (customItemData.toolType() != null) { // This is not using the isTool boolean because it is not just a render type here. @@ -258,10 +259,21 @@ public class CustomItemRegistryPopulator { return builder; } - private static void setupBasicItemInfo(int maxDamage, int stackSize, boolean displayHandheld, CustomItemData customItemData, NbtMapBuilder itemProperties, NbtMapBuilder componentBuilder) { - itemProperties.putCompound("minecraft:icon", NbtMap.builder() - .putString("texture", customItemData.icon()) - .build()); + private static void setupBasicItemInfo(int maxDamage, int stackSize, boolean displayHandheld, CustomItemData customItemData, NbtMapBuilder itemProperties, NbtMapBuilder componentBuilder, int protocolVersion) { + NbtMap iconMap; + if (GameProtocol.is1_20_60orHigher(protocolVersion)) { + iconMap = NbtMap.builder() + .putCompound("textures", NbtMap.builder() + .putString("default", customItemData.icon()) + .build()) + .build(); + } else { + iconMap = NbtMap.builder() + .putString("texture", customItemData.icon()) + .build(); + } + itemProperties.putCompound("minecraft:icon", iconMap); + componentBuilder.putCompound("minecraft:display_name", NbtMap.builder().putString("value", customItemData.displayName()).build()); // Add a Geyser tag to the item, allowing Molang queries diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomSkullRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomSkullRegistryPopulator.java index 02d9a75ec..ec7243396 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomSkullRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomSkullRegistryPopulator.java @@ -130,7 +130,7 @@ public class CustomSkullRegistryPopulator { } }); - if (BlockRegistries.CUSTOM_SKULLS.get().size() != 0) { + if (!BlockRegistries.CUSTOM_SKULLS.get().isEmpty()) { GeyserImpl.getInstance().getLogger().info("Registered " + BlockRegistries.CUSTOM_SKULLS.get().size() + " custom skulls as custom blocks."); } } 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 bc2cf4a43..539452169 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 @@ -40,6 +40,7 @@ import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; import org.cloudburstmc.protocol.bedrock.codec.v622.Bedrock_v622; import org.cloudburstmc.protocol.bedrock.codec.v630.Bedrock_v630; +import org.cloudburstmc.protocol.bedrock.codec.v649.Bedrock_v649; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; @@ -59,6 +60,7 @@ import org.geysermc.geyser.inventory.item.StoredItemMappings; import org.geysermc.geyser.item.GeyserCustomMappingData; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.Item; +import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.type.*; @@ -89,6 +91,7 @@ public class ItemRegistryPopulator { List paletteVersions = new ArrayList<>(3); paletteVersions.add(new PaletteVersion("1_20_40", Bedrock_v622.CODEC.getProtocolVersion(), Collections.emptyMap(), Conversion630_622::remapItem)); paletteVersions.add(new PaletteVersion("1_20_50", Bedrock_v630.CODEC.getProtocolVersion())); + paletteVersions.add(new PaletteVersion("1_20_60", Bedrock_v649.CODEC.getProtocolVersion(), Collections.emptyMap(), Conversion630_649::remapItem)); GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap(); @@ -272,7 +275,7 @@ public class ItemRegistryPopulator { if (firstPass) { firstPass = false; - if (states.size() == 0) { + if (states.isEmpty()) { // No need to iterate and find all block states - this is the one, as there can't be any others bedrockBlock = bedrockBlockRuntimeId; break; @@ -288,7 +291,7 @@ public class ItemRegistryPopulator { requiredBlockStatesBuilder.remove(nbtEntry.getKey()); } } - if (requiredBlockStatesBuilder.size() == 0) { + if (requiredBlockStatesBuilder.isEmpty()) { // There are no required block states // E.G. there was only a direction property that is no longer in play // (States that are important include color for glass) @@ -420,7 +423,7 @@ public class ItemRegistryPopulator { } GeyserCustomMappingData customMapping = CustomItemRegistryPopulator.registerCustomItem( - customItemName, javaItem, mappingItem, customItem, customProtocolId + customItemName, javaItem, mappingItem, customItem, customProtocolId, palette.protocolVersion ); // ComponentItemData - used to register some custom properties componentItemData.add(customMapping.componentItemData()); @@ -495,7 +498,7 @@ public class ItemRegistryPopulator { .count(1) .build()); - registerFurnaceMinecart(nextFreeBedrockId++, componentItemData); + registerFurnaceMinecart(nextFreeBedrockId++, componentItemData, palette.protocolVersion); // Register any completely custom items given to us IntSet registeredJavaIds = new IntOpenHashSet(); // Used to check for duplicate item java ids @@ -508,7 +511,7 @@ public class ItemRegistryPopulator { } int customItemId = nextFreeBedrockId++; - NonVanillaItemRegistration registration = CustomItemRegistryPopulator.registerCustomItem(customItem, customItemId); + NonVanillaItemRegistration registration = CustomItemRegistryPopulator.registerCustomItem(customItem, customItemId, palette.protocolVersion); componentItemData.add(registration.componentItemData()); ItemMapping mapping = registration.mapping(); @@ -585,7 +588,7 @@ public class ItemRegistryPopulator { } } - private static void registerFurnaceMinecart(int nextFreeBedrockId, List componentItemData) { + private static void registerFurnaceMinecart(int nextFreeBedrockId, List componentItemData, int protocolVersion) { NbtMapBuilder builder = NbtMap.builder(); builder.putString("name", "geysermc:furnace_minecart") .putInt("id", nextFreeBedrockId); @@ -594,11 +597,20 @@ public class ItemRegistryPopulator { 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()); + // Not so conveniently, the way to set an icon changed in 1.20.60 + NbtMap iconMap; + if (GameProtocol.is1_20_60orHigher(protocolVersion)) { + iconMap = NbtMap.builder() + .putCompound("textures", NbtMap.builder() + .putString("default", "minecart_furnace") + .build()) + .build(); + } else { + iconMap = NbtMap.builder() + .putString("texture", "minecart_furnace") + .build(); + } + itemProperties.putCompound("minecraft:icon", iconMap); componentBuilder.putCompound("minecraft:display_name", NbtMap.builder().putString("value", "item.minecartFurnace.name").build()); // Indicate that the arm animation should play on rails 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 19c587bf8..8a35bbb5c 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 @@ -72,6 +72,7 @@ import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.util.BlockEntityUtils; import org.geysermc.geyser.util.ChunkUtils; +import org.geysermc.geyser.util.DimensionUtils; import java.io.IOException; import java.util.BitSet; @@ -522,6 +523,7 @@ public class JavaLevelChunkWithLightTranslator extends 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 S3Ddm$_?t%ZPkIIGv;P4hJo(K4 literal 0 HcmV?d00001 diff --git a/core/src/main/resources/bedrock/creative_items.1_20_60.json b/core/src/main/resources/bedrock/creative_items.1_20_60.json new file mode 100644 index 000000000..d4063030e --- /dev/null +++ b/core/src/main/resources/bedrock/creative_items.1_20_60.json @@ -0,0 +1,5787 @@ +{ + "items": [ + { + "id": "minecraft:oak_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQFAAAACAQAbmFtZRQAbWluZWNyYWZ0Om9ha19wbGFua3MECQBuYW1lX2hhc2ilMDLR92rQ4wMKAG5ldHdvcmtfaWS2MwAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:spruce_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTiAwAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9wbGFua3MECQBuYW1lX2hhc2iumBkmFGFE8gMKAG5ldHdvcmtfaWQZNQAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:birch_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTjAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX3BsYW5rcwQJAG5hbWVfaGFzaLrrAKJqV2WFAwoAbmV0d29ya19pZJQjAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:jungle_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTkAwAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9wbGFua3MECQBuYW1lX2hhc2iBM3k4T3FAugMKAG5ldHdvcmtfaWQwLgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:acacia_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTlAwAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9wbGFua3MECQBuYW1lX2hhc2g60edJxO5/aAMKAG5ldHdvcmtfaWSDHAAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:dark_oak_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTmAwAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX3BsYW5rcwQJAG5hbWVfaGFzaAr64wkQ9cA7AwoAbmV0d29ya19pZDMXAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:mangrove_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTlAgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX3BsYW5rcwQJAG5hbWVfaGFzaPvLtcEA0F8xAwoAbmV0d29ya19pZGgJAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:cherry_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAwAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9wbGFua3MECQBuYW1lX2hhc2hNIvVh/lVW7gMKAG5ldHdvcmtfaWSVNAAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:bamboo_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT9AgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19wbGFua3MECQBuYW1lX2hhc2gYnjNz7SCCjgMKAG5ldHdvcmtfaWTbJAAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:bamboo_mosaic", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT8AgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19tb3NhaWMECQBuYW1lX2hhc2izSEgiMKOp/AMKAG5ldHdvcmtfaWT0NgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:crimson_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTxAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fcGxhbmtzBAkAbmFtZV9oYXNoJc5IKqNXJnwDCgBuZXR3b3JrX2lkmyEAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:warped_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTyAQAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9wbGFua3MECQBuYW1lX2hhc2g3yGXEWhe6LgMKAG5ldHdvcmtfaWRLCQAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRFCgAACgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCwBjb2JibGVzdG9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRGCgAACgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEQBtb3NzeV9jb2JibGVzdG9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRHCgAACgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBwBncmFuaXRlCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRICgAACgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBwBkaW9yaXRlCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRJCgAACgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCABhbmRlc2l0ZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRKCgAACgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCQBzYW5kc3RvbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRRCgAACgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlDQByZWRfc2FuZHN0b25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRMCgAACgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCwBzdG9uZV9icmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRNCgAACgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEQBtb3NzeV9zdG9uZV9icmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRLCgAACgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBQBicmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWROCgAACgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlDABuZXRoZXJfYnJpY2sIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRSCgAACgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEAByZWRfbmV0aGVyX2JyaWNrCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRPCgAACgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCQBlbmRfYnJpY2sIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRQCgAACgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCgBwcmlzbWFyaW5lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:blackstone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQUAgAACAQAbmFtZRkAbWluZWNyYWZ0OmJsYWNrc3RvbmVfd2FsbAQJAG5hbWVfaGFzaMP8XppUSU1RAwoAbmV0d29ya19pZDsaAAAKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:polished_blackstone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQoAgAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfd2FsbAQJAG5hbWVfaGFzaP6SwV08YwzAAwoAbmV0d29ya19pZJsuAAAKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:polished_blackstone_brick_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQVAgAACAQAbmFtZSgAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfd2FsbAQJAG5hbWVfaGFzaBBIDZbHxiEzAwoAbmV0d29ya19pZHYJAAAKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:cobbled_deepslate_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR9AgAACAQAbmFtZSAAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3dhbGwECQBuYW1lX2hhc2iECY5oKxeT+gMKAG5ldHdvcmtfaWQwNgAACgYAc3RhdGVzCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:deepslate_tile_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3dhbGwECQBuYW1lX2hhc2jz7N+PeuEXgQMKAG5ldHdvcmtfaWSNIgAACgYAc3RhdGVzCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:polished_deepslate_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSBAgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV93YWxsBAkAbmFtZV9oYXNoHxjTdj9pevMDCgBuZXR3b3JrX2lkKDUAAAoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:deepslate_brick_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSJAgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja193YWxsBAkAbmFtZV9oYXNoEs3EQrjroyEDCgBuZXR3b3JrX2lkoQQAAAoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:mud_brick_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTgAgAACAQAbmFtZRgAbWluZWNyYWZ0Om11ZF9icmlja193YWxsBAkAbmFtZV9oYXNov9b98ATpUSwDCgBuZXR3b3JrX2lkfQgAAAoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:oak_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRVAAAACAQAbmFtZRMAbWluZWNyYWZ0Om9ha19mZW5jZQQJAG5hbWVfaGFzaGEmid7AaCWRAwoAbmV0d29ya19pZF0lAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:spruce_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRCAwAACAQAbmFtZRYAbWluZWNyYWZ0OnNwcnVjZV9mZW5jZQQJAG5hbWVfaGFzaPQCm+aX1ZQeAwoAbmV0d29ya19pZHcEAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:birch_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ/AwAACAQAbmFtZRUAbWluZWNyYWZ0OmJpcmNoX2ZlbmNlBAkAbmFtZV9oYXNo6CJ2ATpANfgDCgBuZXR3b3JrX2lkIzYAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:jungle_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRBAwAACAQAbmFtZRYAbWluZWNyYWZ0Omp1bmdsZV9mZW5jZQQJAG5hbWVfaGFzaOX4cD9uAmsdAwoAbmV0d29ya19pZHAEAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:acacia_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ+AwAACAQAbmFtZRYAbWluZWNyYWZ0OmFjYWNpYV9mZW5jZQQJAG5hbWVfaGFzaGjn+RlKVDH6AwoAbmV0d29ya19pZC42AAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:dark_oak_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRAAwAACAQAbmFtZRgAbWluZWNyYWZ0OmRhcmtfb2FrX2ZlbmNlBAkAbmFtZV9oYXNoGPj0gCgM0c0DCgBuZXR3b3JrX2lkNTAAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:mangrove_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTqAgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hbmdyb3ZlX2ZlbmNlBAkAbmFtZV9oYXNowwAd7tPu9bsDCgBuZXR3b3JrX2lkQi4AAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:cherry_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQTAwAACAQAbmFtZRYAbWluZWNyYWZ0OmNoZXJyeV9mZW5jZQQJAG5hbWVfaGFzaFmtUfHfTxcxAwoAbmV0d29ya19pZGcJAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:bamboo_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQCAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJhbWJvb19mZW5jZQQJAG5hbWVfaGFzaCKRbxfXsfkiAwoAbmV0d29ya19pZF0FAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:nether_brick_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRxAAAACAQAbmFtZRwAbWluZWNyYWZ0Om5ldGhlcl9icmlja19mZW5jZQQJAG5hbWVfaGFzaA6030ngawxcAwoAbmV0d29ya19pZLUbAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:crimson_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT/AQAACAQAbmFtZRcAbWluZWNyYWZ0OmNyaW1zb25fZmVuY2UECQBuYW1lX2hhc2jhUhKv1HGj9AMKAG5ldHdvcmtfaWTcNQAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:warped_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQAAgAACAQAbmFtZRYAbWluZWNyYWZ0OndhcnBlZF9mZW5jZQQJAG5hbWVfaGFzaJfb3/YuKmOWAwoAbmV0d29ya19pZG0nAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRrAAAACAQAbmFtZRQAbWluZWNyYWZ0OmZlbmNlX2dhdGUECQBuYW1lX2hhc2hTxpjEDmRzAwMKAG5ldHdvcmtfaWRVAAAACgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:spruce_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS3AAAACAQAbmFtZRsAbWluZWNyYWZ0OnNwcnVjZV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoanTVB84HRbkDCgBuZXR3b3JrX2lkEC4AAAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:birch_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS4AAAACAQAbmFtZRoAbWluZWNyYWZ0OmJpcmNoX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2jmfPklI8azSwMKAG5ldHdvcmtfaWQkGAAACgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:jungle_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS5AAAACAQAbmFtZRsAbWluZWNyYWZ0Omp1bmdsZV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNobYVQkfBomIcDCgBuZXR3b3JrX2lkuCMAAAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:acacia_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS7AAAACAQAbmFtZRsAbWluZWNyYWZ0OmFjYWNpYV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoZnrLUx/XSekDCgBuZXR3b3JrX2lk5jMAAAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:dark_oak_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS6AAAACAQAbmFtZR0AbWluZWNyYWZ0OmRhcmtfb2FrX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2j2PTvdJJHcVQMKAG5ldHdvcmtfaWQxGwAACgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:mangrove_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTrAgAACAQAbmFtZR0AbWluZWNyYWZ0Om1hbmdyb3ZlX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2i/kOhBKiI/dAMKAG5ldHdvcmtfaWReHQAACgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:cherry_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQUAwAACAQAbmFtZRsAbWluZWNyYWZ0OmNoZXJyeV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoKWLgCk0z+PsDCgBuZXR3b3JrX2lk3TYAAAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:bamboo_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAwAACAQAbmFtZRsAbWluZWNyYWZ0OmJhbWJvb19mZW5jZV9nYXRlBAkAbmFtZV9oYXNopH1JrUgwdIADCgBuZXR3b3JrX2lkdCIAAAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:crimson_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQBAgAACAQAbmFtZRwAbWluZWNyYWZ0OmNyaW1zb25fZmVuY2VfZ2F0ZQQJAG5hbWVfaGFzaHE3Gfd0Z2d2AwoAbmV0d29ya19pZCIfAAAKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQsAaW5fd2FsbF9iaXQAAQgAb3Blbl9iaXQAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:warped_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQCAgAACAQAbmFtZRsAbWluZWNyYWZ0OndhcnBlZF9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoy0oIBjDIG4kDCgBuZXR3b3JrX2lk3iMAAAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:normal_stone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSzAQAACAQAbmFtZR0AbWluZWNyYWZ0Om5vcm1hbF9zdG9uZV9zdGFpcnMECQBuYW1lX2hhc2hAEktZZOkGIwMKAG5ldHdvcmtfaWReBQAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:stone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRDAAAACAQAbmFtZRYAbWluZWNyYWZ0OnN0b25lX3N0YWlycwQJAG5hbWVfaGFzaNRjqVC5GRVDAwoAbmV0d29ya19pZNQXAAAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:mossy_cobblestone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSyAQAACAQAbmFtZSIAbWluZWNyYWZ0Om1vc3N5X2NvYmJsZXN0b25lX3N0YWlycwQJAG5hbWVfaGFzaMVSTq5z9n1RAwoAbmV0d29ya19pZN0aAAAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:oak_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ1AAAACAQAbmFtZRQAbWluZWNyYWZ0Om9ha19zdGFpcnMECQBuYW1lX2hhc2jk/HFzdXy0FQMKAG5ldHdvcmtfaWTSAgAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:spruce_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSGAAAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9zdGFpcnMECQBuYW1lX2hhc2iznygw7uBPBQMKAG5ldHdvcmtfaWSMAAAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:birch_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSHAAAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX3N0YWlycwQJAG5hbWVfaGFzaPfhbL619a3GAwoAbmV0d29ya19pZL8vAAAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:jungle_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSIAAAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9zdGFpcnMECQBuYW1lX2hhc2jodJsHUbOVxQMKAG5ldHdvcmtfaWSYLwAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:acacia_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSjAAAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9zdGFpcnMECQBuYW1lX2hhc2h3x1NmD43IqQMKAG5ldHdvcmtfaWRULAAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:dark_oak_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSkAAAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX3N0YWlycwQJAG5hbWVfaGFzaMfwkbYPbNmAAwoAbmV0d29ya19pZIUiAAAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:mangrove_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTnAgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX3N0YWlycwQJAG5hbWVfaGFzaNpUDY+uGMpyAwoAbmV0d29ya19pZDQdAAAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:cherry_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQcAwAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9zdGFpcnMECQBuYW1lX2hhc2jMtr0v9JY4zwMKAG5ldHdvcmtfaWRkMAAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:bamboo_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT/AgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19zdGFpcnMECQBuYW1lX2hhc2jFOzWL8PalKwMKAG5ldHdvcmtfaWRvCAAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:bamboo_mosaic_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQKAwAACAQAbmFtZR4AbWluZWNyYWZ0OmJhbWJvb19tb3NhaWNfc3RhaXJzBAkAbmFtZV9oYXNoNLPiveSHPaoDCgBuZXR3b3JrX2lkXCwAAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:stone_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRtAAAACAQAbmFtZRwAbWluZWNyYWZ0OnN0b25lX2JyaWNrX3N0YWlycwQJAG5hbWVfaGFzaN6tQViRo5cwAwoAbmV0d29ya19pZFcJAAAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:mossy_stone_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSuAQAACAQAbmFtZSIAbWluZWNyYWZ0Om1vc3N5X3N0b25lX2JyaWNrX3N0YWlycwQJAG5hbWVfaGFzaIB/Zv5YBPuYAwoAbmV0d29ya19pZCwpAAAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:sandstone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSAAAAACAQAbmFtZRoAbWluZWNyYWZ0OnNhbmRzdG9uZV9zdGFpcnMECQBuYW1lX2hhc2hOyA0BoYUOPQMKAG5ldHdvcmtfaWRUFwAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:smooth_sandstone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSwAQAACAQAbmFtZSEAbWluZWNyYWZ0OnNtb290aF9zYW5kc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNoB+CuCd8Ruz8DCgBuZXR3b3JrX2lkghcAAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:red_sandstone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS0AAAACAQAbmFtZR4AbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNoPs0LpHPL24YDCgBuZXR3b3JrX2lkqSMAAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:smooth_red_sandstone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAQAACAQAbmFtZSUAbWluZWNyYWZ0OnNtb290aF9yZWRfc2FuZHN0b25lX3N0YWlycwQJAG5hbWVfaGFzaBvjtQv5pf+MAwoAbmV0d29ya19pZJIkAAAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:granite_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAQAACAQAbmFtZRgAbWluZWNyYWZ0OmdyYW5pdGVfc3RhaXJzBAkAbmFtZV9oYXNoGzpvtoqKQjgDCgBuZXR3b3JrX2lkjxUAAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:polished_granite_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSrAQAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2dyYW5pdGVfc3RhaXJzBAkAbmFtZV9oYXNo3PvbSfEQklIDCgBuZXR3b3JrX2lkGRsAAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:diorite_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSpAQAACAQAbmFtZRgAbWluZWNyYWZ0OmRpb3JpdGVfc3RhaXJzBAkAbmFtZV9oYXNoi73T8VQuZmcDCgBuZXR3b3JrX2lkShwAAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:polished_diorite_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSsAQAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2Rpb3JpdGVfc3RhaXJzBAkAbmFtZV9oYXNoFKRJd5Wk5L0DCgBuZXR3b3JrX2lkii4AAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:andesite_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSqAQAACAQAbmFtZRkAbWluZWNyYWZ0OmFuZGVzaXRlX3N0YWlycwQJAG5hbWVfaGFzaO5w2FKBw76EAwoAbmV0d29ya19pZIwjAAAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:polished_andesite_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWStAQAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2FuZGVzaXRlX3N0YWlycwQJAG5hbWVfaGFzaNcZZ/zmLInIAwoAbmV0d29ya19pZNsvAAAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRsAAAACAQAbmFtZRYAbWluZWNyYWZ0OmJyaWNrX3N0YWlycwQJAG5hbWVfaGFzaMyt+cRDk5O2AwoAbmV0d29ya19pZMgtAAAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:nether_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRyAAAACAQAbmFtZR0AbWluZWNyYWZ0Om5ldGhlcl9icmlja19zdGFpcnMECQBuYW1lX2hhc2jRqIoOXgifBAMKAG5ldHdvcmtfaWRzAAAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:red_nether_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS3AQAACAQAbmFtZSEAbWluZWNyYWZ0OnJlZF9uZXRoZXJfYnJpY2tfc3RhaXJzBAkAbmFtZV9oYXNogQvosSbcj7kDCgBuZXR3b3JrX2lkIi4AAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:end_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSxAQAACAQAbmFtZRoAbWluZWNyYWZ0OmVuZF9icmlja19zdGFpcnMECQBuYW1lX2hhc2hmlAk+QhsUsQMKAG5ldHdvcmtfaWQKLQAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:quartz_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWScAAAACAQAbmFtZRcAbWluZWNyYWZ0OnF1YXJ0el9zdGFpcnMECQBuYW1lX2hhc2hmvpvOqGi6egMKAG5ldHdvcmtfaWTEHwAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:smooth_quartz_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS4AQAACAQAbmFtZR4AbWluZWNyYWZ0OnNtb290aF9xdWFydHpfc3RhaXJzBAkAbmFtZV9oYXNoNZZ9rX0qZOsDCgBuZXR3b3JrX2lkWDQAAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:purpur_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTLAAAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnB1cl9zdGFpcnMECQBuYW1lX2hhc2ifwDxeezXD7gMKAG5ldHdvcmtfaWSZNAAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:prismarine_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQBAQAACAQAbmFtZRsAbWluZWNyYWZ0OnByaXNtYXJpbmVfc3RhaXJzBAkAbmFtZV9oYXNooTHSZ+IrYtcDCgBuZXR3b3JrX2lkkTIAAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:dark_prismarine_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQCAQAACAQAbmFtZSAAbWluZWNyYWZ0OmRhcmtfcHJpc21hcmluZV9zdGFpcnMECQBuYW1lX2hhc2hIciLmam4o4AMKAG5ldHdvcmtfaWRBMwAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:prismarine_bricks_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAQAACAQAbmFtZSIAbWluZWNyYWZ0OnByaXNtYXJpbmVfYnJpY2tzX3N0YWlycwQJAG5hbWVfaGFzaNIjq1oBlZMMAwoAbmV0d29ya19pZHECAAAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:crimson_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT9AQAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fc3RhaXJzBAkAbmFtZV9oYXNoZJqIzCBpCq4DCgBuZXR3b3JrX2lknywAAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:warped_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT+AQAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9zdGFpcnMECQBuYW1lX2hhc2hOkY27jLD4RQMKAG5ldHdvcmtfaWThFwAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:blackstone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQTAgAACAQAbmFtZRsAbWluZWNyYWZ0OmJsYWNrc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNokdoUb76p9McDCgBuZXR3b3JrX2lk0C8AAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:polished_blackstone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQjAgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNolCFtFIE8MmADCgBuZXR3b3JrX2lk3hsAAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:polished_blackstone_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQSAgAACAQAbmFtZSoAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfc3RhaXJzBAkAbmFtZV9oYXNonks6UlfpOmkDCgBuZXR3b3JrX2lkphwAAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAgAACAQAbmFtZRsAbWluZWNyYWZ0OmN1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoHfoAXYq5G3MDCgBuZXR3b3JrX2lkPR0AAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:exposed_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAgAACAQAbmFtZSMAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcl9zdGFpcnMECQBuYW1lX2hhc2howneQGtZ9cgMKAG5ldHdvcmtfaWQsHQAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:weathered_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAgAACAQAbmFtZSUAbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyX3N0YWlycwQJAG5hbWVfaGFzaP+R5loXxrVgAwoAbmV0d29ya19pZOYbAAAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:oxidized_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRkAgAACAQAbmFtZSQAbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNo6Jeoq5rsPxsDCgBuZXR3b3JrX2lkSgQAAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:waxed_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRlAgAACAQAbmFtZSEAbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoh07CQj0/SR8DCgBuZXR3b3JrX2lkegQAAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:waxed_exposed_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRmAgAACAQAbmFtZSkAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcl9zdGFpcnMECQBuYW1lX2hhc2guVct1ilmxTwMKAG5ldHdvcmtfaWQeGgAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:waxed_weathered_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRnAgAACAQAbmFtZSsAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyX3N0YWlycwQJAG5hbWVfaGFzaPXC8Sz/phCpAwoAbmV0d29ya19pZEMsAAAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:waxed_oxidized_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS/AgAACAQAbmFtZSoAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoaqGdkuhxVZUDCgBuZXR3b3JrX2lkQCcAAAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:cobbled_deepslate_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR8AgAACAQAbmFtZSIAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3N0YWlycwQJAG5hbWVfaGFzaPIfa+TpyJcIAwoAbmV0d29ya19pZDUCAAAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:deepslate_tile_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3N0YWlycwQJAG5hbWVfaGFzaGFRFzB72mN2AwoAbmV0d29ya19pZBofAAAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:polished_deepslate_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSAAgAACAQAbmFtZSMAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV9zdGFpcnMECQBuYW1lX2hhc2iNCYxVik9sGAMKAG5ldHdvcmtfaWQNBAAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:deepslate_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSIAgAACAQAbmFtZSAAbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja19zdGFpcnMECQBuYW1lX2hhc2hIasOahEf83wMKAG5ldHdvcmtfaWQ5MwAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:mud_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTfAgAACAQAbmFtZRoAbWluZWNyYWZ0Om11ZF9icmlja19zdGFpcnMECQBuYW1lX2hhc2gt3qxK1NWajAMKAG5ldHdvcmtfaWR6JAAACgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:wooden_door" + }, + { + "id": "minecraft:spruce_door" + }, + { + "id": "minecraft:birch_door" + }, + { + "id": "minecraft:jungle_door" + }, + { + "id": "minecraft:acacia_door" + }, + { + "id": "minecraft:dark_oak_door" + }, + { + "id": "minecraft:mangrove_door" + }, + { + "id": "minecraft:cherry_door" + }, + { + "id": "minecraft:bamboo_door" + }, + { + "id": "minecraft:iron_door" + }, + { + "id": "minecraft:crimson_door" + }, + { + "id": "minecraft:warped_door" + }, + { + "id": "minecraft:trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRgAAAACAQAbmFtZRIAbWluZWNyYWZ0OnRyYXBkb29yBAkAbmFtZV9oYXNotYiAJGtN0xADCgBuZXR3b3JrX2lkkQIAAAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:spruce_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSUAQAACAQAbmFtZRkAbWluZWNyYWZ0OnNwcnVjZV90cmFwZG9vcgQJAG5hbWVfaGFzaOwlfbgBkUW4AwoAbmV0d29ya19pZO8tAAAKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:birch_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSRAQAACAQAbmFtZRgAbWluZWNyYWZ0OmJpcmNoX3RyYXBkb29yBAkAbmFtZV9oYXNoSLtLweOLJ7wDCgBuZXR3b3JrX2lkVC4AAAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:jungle_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSTAQAACAQAbmFtZRkAbWluZWNyYWZ0Omp1bmdsZV90cmFwZG9vcgQJAG5hbWVfaGFzaDP/TnM9wyCIAwoAbmV0d29ya19pZMsjAAAKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:acacia_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSQAQAACAQAbmFtZRkAbWluZWNyYWZ0OmFjYWNpYV90cmFwZG9vcgQJAG5hbWVfaGFzaMj8xi3vmEKOAwoAbmV0d29ya19pZLskAAAKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:dark_oak_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSSAQAACAQAbmFtZRsAbWluZWNyYWZ0OmRhcmtfb2FrX3RyYXBkb29yBAkAbmFtZV9oYXNomB2GGJQ2aOMDCgBuZXR3b3JrX2lkizMAAAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:mangrove_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTvAgAACAQAbmFtZRsAbWluZWNyYWZ0Om1hbmdyb3ZlX3RyYXBkb29yBAkAbmFtZV9oYXNooV3kQsQUUmkDCgBuZXR3b3JrX2lkrhwAAAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:cherry_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQeAwAACAQAbmFtZRkAbWluZWNyYWZ0OmNoZXJyeV90cmFwZG9vcgQJAG5hbWVfaGFzaH/PefpfdHgtAwoAbmV0d29ya19pZDEJAAAKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:bamboo_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQHAwAACAQAbmFtZRkAbWluZWNyYWZ0OmJhbWJvb190cmFwZG9vcgQJAG5hbWVfaGFzaJrEOpsTwtKCAwoAbmV0d29ya19pZE4jAAAKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:iron_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSnAAAACAQAbmFtZRcAbWluZWNyYWZ0Omlyb25fdHJhcGRvb3IECQBuYW1lX2hhc2gwA+IumsEiGQMKAG5ldHdvcmtfaWQqBAAACgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAEPAHVwc2lkZV9kb3duX2JpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:crimson_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT1AQAACAQAbmFtZRoAbWluZWNyYWZ0OmNyaW1zb25fdHJhcGRvb3IECQBuYW1lX2hhc2jHXufTnwUkYgMKAG5ldHdvcmtfaWQHHAAACgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAEPAHVwc2lkZV9kb3duX2JpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:warped_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT2AQAACAQAbmFtZRkAbWluZWNyYWZ0OndhcnBlZF90cmFwZG9vcgQJAG5hbWVfaGFzaA20wG/+vkd6AwoAbmV0d29ya19pZJIfAAAKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:iron_bars", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRlAAAACAQAbmFtZRMAbWluZWNyYWZ0Omlyb25fYmFycwQJAG5hbWVfaGFzaPuefWSNAe56AwoAbmV0d29ya19pZOcfAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQUAAAACAQAbmFtZQ8AbWluZWNyYWZ0OmdsYXNzBAkAbmFtZV9oYXNowGJByfWff6gDCgBuZXR3b3JrX2lkQCwAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:white_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTxAAAACAQAbmFtZR0AbWluZWNyYWZ0OndoaXRlX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2iHubqoMbu9fAMKAG5ldHdvcmtfaWSdIQAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:light_gray_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSnAwAACAQAbmFtZSIAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaKKa+LrRsHQhAwoAbmV0d29ya19pZJ4EAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:gray_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSmAwAACAQAbmFtZRwAbWluZWNyYWZ0OmdyYXlfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaIETy7Y/HZREAwoAbmV0d29ya19pZN0XAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:black_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSuAwAACAQAbmFtZR0AbWluZWNyYWZ0OmJsYWNrX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2iV6BCwpfDMmwMKAG5ldHdvcmtfaWRZKQAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:brown_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSrAwAACAQAbmFtZR0AbWluZWNyYWZ0OmJyb3duX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2igsEiq5np8JgMKAG5ldHdvcmtfaWTxBgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:red_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWStAwAACAQAbmFtZRsAbWluZWNyYWZ0OnJlZF9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNoCa2J12/lQoIDCgBuZXR3b3JrX2lkPSMAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:orange_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSgAwAACAQAbmFtZR4AbWluZWNyYWZ0Om9yYW5nZV9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNozgjAuvzhxGsDCgBuZXR3b3JrX2lk8RwAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:yellow_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSjAwAACAQAbmFtZR4AbWluZWNyYWZ0OnllbGxvd19zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNo7EbHMd5WVugDCgBuZXR3b3JrX2lk5DMAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:lime_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSkAwAACAQAbmFtZRwAbWluZWNyYWZ0OmxpbWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaBtZA1nZtwcFAwoAbmV0d29ya19pZH4AAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:green_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSsAwAACAQAbmFtZR0AbWluZWNyYWZ0OmdyZWVuX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2h91ptDgbehWwMKAG5ldHdvcmtfaWS0GwAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:cyan_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAwAACAQAbmFtZRwAbWluZWNyYWZ0OmN5YW5fc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaBkIYQ8nQLqbAwoAbmV0d29ya19pZFgpAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:light_blue_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSiAwAACAQAbmFtZSIAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaLt05n1G0fiSAwoAbmV0d29ya19pZIYlAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:blue_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSqAwAACAQAbmFtZRwAbWluZWNyYWZ0OmJsdWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaPhLocSfzduRAwoAbmV0d29ya19pZGIlAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:purple_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSpAwAACAQAbmFtZR4AbWluZWNyYWZ0OnB1cnBsZV9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNoJk0DhRO0szUDCgBuZXR3b3JrX2lkPQoAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:magenta_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAwAACAQAbmFtZR8AbWluZWNyYWZ0Om1hZ2VudGFfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaFEDeFiJj3zSAwoAbmV0d29ya19pZGgyAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:pink_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAwAACAQAbmFtZRwAbWluZWNyYWZ0OnBpbmtfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaDijTX87ywxhAwoAbmV0d29ya19pZPYbAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:tinted_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRNAgAACAQAbmFtZRYAbWluZWNyYWZ0OnRpbnRlZF9nbGFzcwQJAG5hbWVfaGFzaAFZWSamk6KdAwoAbmV0d29ya19pZNkpAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRmAAAACAQAbmFtZRQAbWluZWNyYWZ0OmdsYXNzX3BhbmUECQBuYW1lX2hhc2gRSBHwNMQ4gQMKAG5ldHdvcmtfaWQvIwAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:white_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSgAAAACAQAbmFtZSIAbWluZWNyYWZ0OndoaXRlX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaHgxQmgJVtRrAwoAbmV0d29ya19pZPIcAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:light_gray_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSJAwAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNon0aQw9lNkSEDCgBuZXR3b3JrX2lkoAQAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:gray_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSIAwAACAQAbmFtZSEAbWluZWNyYWZ0OmdyYXlfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNors74IIw+2MMDCgBuZXR3b3JrX2lkTi8AAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:black_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSQAwAACAQAbmFtZSIAbWluZWNyYWZ0OmJsYWNrX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaOK/5ZRRd+M1AwoAbmV0d29ya19pZEQKAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:brown_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSNAwAACAQAbmFtZSIAbWluZWNyYWZ0OmJyb3duX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaLHeGJyRFTIWAwoAbmV0d29ya19pZN4CAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:red_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSPAwAACAQAbmFtZSAAbWluZWNyYWZ0OnJlZF9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2gGr4x6JheAywMKAG5ldHdvcmtfaWQtMAAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:orange_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSCAwAACAQAbmFtZSMAbWluZWNyYWZ0Om9yYW5nZV9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2hbHxPD2gEbEAMKAG5ldHdvcmtfaWSIAgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:yellow_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAwAACAQAbmFtZSMAbWluZWNyYWZ0OnllbGxvd19zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2g9tl4aOCyZBwMKAG5ldHdvcmtfaWQxAgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:lime_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSGAwAACAQAbmFtZSEAbWluZWNyYWZ0OmxpbWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNo3CtUyLwoGegDCgBuZXR3b3JrX2lk4jMAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:green_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSOAwAACAQAbmFtZSIAbWluZWNyYWZ0OmdyZWVuX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaJo6YP7IMy9SAwoAbmV0d29ya19pZBgbAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:cyan_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSKAwAACAQAbmFtZSEAbWluZWNyYWZ0OmN5YW5fc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoti97c6QrbLQDCgBuZXR3b3JrX2lkmy0AAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:light_blue_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAwAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNovDg/gQle104DCgBuZXR3b3JrX2lkDBoAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:blue_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSMAwAACAQAbmFtZSEAbWluZWNyYWZ0OmJsdWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoGc57tiexbQMDCgBuZXR3b3JrX2lkVAAAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:purple_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAwAACAQAbmFtZSMAbWluZWNyYWZ0OnB1cnBsZV9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2hDJHYdd0FdfQMKAG5ldHdvcmtfaWSeIQAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:magenta_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAwAACAQAbmFtZSQAbWluZWNyYWZ0Om1hZ2VudGFfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNo3pcOw5bs5XoDCgBuZXR3b3JrX2lk5h8AAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:pink_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSHAwAACAQAbmFtZSEAbWluZWNyYWZ0OnBpbmtfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoWRhSACMWgswDCgBuZXR3b3JrX2lkMjAAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:ladder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRBAAAACAQAbmFtZRAAbWluZWNyYWZ0OmxhZGRlcgQJAG5hbWVfaGFzaKBhqheJVOz+AwoAbmV0d29ya19pZPo2AAAKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:scaffolding", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSkAQAACAQAbmFtZRUAbWluZWNyYWZ0OnNjYWZmb2xkaW5nBAkAbmFtZV9oYXNoYrkevrqcljwDCgBuZXR3b3JrX2lkRBcAAAoGAHN0YXRlcwMJAHN0YWJpbGl0eQAAAAABDwBzdGFiaWxpdHlfY2hlY2sAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAAAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWSeGwAACgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQwAc21vb3RoX3N0b25lAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:stone_block_slab4", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkqSUAAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNAUAc3RvbmUAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAAAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWShGwAACgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQsAY29iYmxlc3RvbmUAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkjCUAAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhEAbW9zc3lfY29iYmxlc3RvbmUAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:wooden_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSeAAAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lkZiMAAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20ICQB3b29kX3R5cGUDAG9hawADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:wooden_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSeAAAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lkZyMAAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20ICQB3b29kX3R5cGUGAHNwcnVjZQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:wooden_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSeAAAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lkaCMAAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20ICQB3b29kX3R5cGUFAGJpcmNoAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:wooden_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSeAAAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lkaSMAAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20ICQB3b29kX3R5cGUGAGp1bmdsZQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:wooden_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSeAAAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lkaiMAAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20ICQB3b29kX3R5cGUGAGFjYWNpYQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:wooden_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSeAAAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lkayMAAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20ICQB3b29kX3R5cGUIAGRhcmtfb2FrAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:mangrove_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWToAgAACAQAbmFtZRcAbWluZWNyYWZ0Om1hbmdyb3ZlX3NsYWIECQBuYW1lX2hhc2jYCcmhJPeNMwMKAG5ldHdvcmtfaWQYCgAACgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:cherry_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQaAwAACAQAbmFtZRUAbWluZWNyYWZ0OmNoZXJyeV9zbGFiBAkAbmFtZV9oYXNoTt0MmVn/mqoDCgBuZXR3b3JrX2lkZSwAAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:bamboo_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQAAwAACAQAbmFtZRUAbWluZWNyYWZ0OmJhbWJvb19zbGFiBAkAbmFtZV9oYXNoo1xuFqINeLYDCgBuZXR3b3JrX2lkxS0AAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:bamboo_mosaic_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQLAwAACAQAbmFtZRwAbWluZWNyYWZ0OmJhbWJvb19tb3NhaWNfc2xhYgQJAG5hbWVfaGFzaNbVRBZ/ChI3AwoAbmV0d29ya19pZCkTAAAKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAAAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWSjGwAACgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQsAc3RvbmVfYnJpY2sAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:stone_block_slab4", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkpyUAAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNBEAbW9zc3lfc3RvbmVfYnJpY2sAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAAAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWSfGwAACgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQkAc2FuZHN0b25lAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:stone_block_slab4", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkqiUAAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNA0AY3V0X3NhbmRzdG9uZQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkjSUAAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAc21vb3RoX3NhbmRzdG9uZQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkhyUAAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMg0AcmVkX3NhbmRzdG9uZQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:stone_block_slab4", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkqyUAAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNBEAY3V0X3JlZF9zYW5kc3RvbmUAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkmCUAAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxQAc21vb3RoX3JlZF9zYW5kc3RvbmUAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lknSUAAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMwcAZ3Jhbml0ZQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkniUAAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxAAcG9saXNoZWRfZ3Jhbml0ZQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkmyUAAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMwcAZGlvcml0ZQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lknCUAAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxAAcG9saXNoZWRfZGlvcml0ZQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkmiUAAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMwgAYW5kZXNpdGUAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkmSUAAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxEAcG9saXNoZWRfYW5kZXNpdGUAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAAAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWSiGwAACgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQUAYnJpY2sAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAAAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWSlGwAACgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQwAbmV0aGVyX2JyaWNrAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkjiUAAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAcmVkX25ldGhlcl9icmljawADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lklyUAAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMw8AZW5kX3N0b25lX2JyaWNrAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAAAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWSkGwAACgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQYAcXVhcnR6AAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:stone_block_slab4", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkqCUAAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNA0Ac21vb3RoX3F1YXJ0egADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkiCUAAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMgYAcHVycHVyAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkiSUAAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAcHJpc21hcmluZV9yb3VnaAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkiiUAAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMg8AcHJpc21hcmluZV9kYXJrAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkiyUAAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAcHJpc21hcmluZV9icmljawADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:crimson_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQHAgAACAQAbmFtZRYAbWluZWNyYWZ0OmNyaW1zb25fc2xhYgQJAG5hbWVfaGFzaKZ+EfP0ZYOZAwoAbmV0d29ya19pZEApAAAKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:warped_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQIAgAACAQAbmFtZRUAbWluZWNyYWZ0OndhcnBlZF9zbGFiBAkAbmFtZV9oYXNo/AT0e/Z9W7UDCgBuZXR3b3JrX2lkoC0AAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:blackstone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQZAgAACAQAbmFtZRkAbWluZWNyYWZ0OmJsYWNrc3RvbmVfc2xhYgQJAG5hbWVfaGFzaF/DD4ZUlNgtAwoAbmV0d29ya19pZEEJAAAKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:polished_blackstone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQkAgAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfc2xhYgQJAG5hbWVfaGFzaDYnuUs86EWfAwoAbmV0d29ya19pZIUrAAAKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:polished_blackstone_brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQbAgAACAQAbmFtZSgAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfc2xhYgQJAG5hbWVfaGFzaKySLqvHc4xXAwoAbmV0d29ya19pZEsbAAAKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRoAgAACAQAbmFtZRkAbWluZWNyYWZ0OmN1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaDsNpb2qs4iBAwoAbmV0d29ya19pZDEjAAAKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:exposed_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRpAgAACAQAbmFtZSEAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcl9zbGFiBAkAbmFtZV9oYXNoahQ5OwIQb7kDCgBuZXR3b3JrX2lkIC4AAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:weathered_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRqAgAACAQAbmFtZSMAbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyX3NsYWIECQBuYW1lX2hhc2hBIuGIOVVXogMKAG5ldHdvcmtfaWS0KwAACgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:oxidized_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRrAgAACAQAbmFtZSIAbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaOptj9ycfpaDAwoAbmV0d29ya19pZHIjAAAKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:waxed_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRsAgAACAQAbmFtZR8AbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaAlx6DZOCTHzAwoAbmV0d29ya19pZCY1AAAKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:waxed_exposed_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRtAgAACAQAbmFtZScAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcl9zbGFiBAkAbmFtZV9oYXNo3KqS5OnhtRIDCgBuZXR3b3JrX2lkpQIAAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:waxed_weathered_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRuAgAACAQAbmFtZSkAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyX3NsYWIECQBuYW1lX2hhc2gzZ1oX0HCFtwMKAG5ldHdvcmtfaWToLQAACgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:waxed_oxidized_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTAAgAACAQAbmFtZSgAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaMjjTnLu1KcqAwoAbmV0d29ya19pZL0HAAAKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:cobbled_deepslate_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR7AgAACAQAbmFtZSAAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3NsYWIECQBuYW1lX2hhc2gwJIVWK1TM2QMKAG5ldHdvcmtfaWTLMgAACgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:polished_deepslate_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR/AgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV9zbGFiBAkAbmFtZV9oYXNoC/Adiz8k6RYDCgBuZXR3b3JrX2lk5wIAAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:deepslate_tile_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3NsYWIECQBuYW1lX2hhc2hPydV6emzIXAMKAG5ldHdvcmtfaWS2GwAACgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:deepslate_brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSHAgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja19zbGFiBAkAbmFtZV9oYXNoSv62V7iw10UDCgBuZXR3b3JrX2lk3xcAAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:mud_brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTdAgAACAQAbmFtZRgAbWluZWNyYWZ0Om11ZF9icmlja19zbGFiBAkAbmFtZV9oYXNoq/tGBQWkv08DCgBuZXR3b3JrX2lkJxoAAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:brick_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQtAAAACAQAbmFtZRUAbWluZWNyYWZ0OmJyaWNrX2Jsb2NrBAkAbmFtZV9oYXNo5Qc2E005S3oDCgBuZXR3b3JrX2lksh8AAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:chiseled_nether_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQtAgAACAQAbmFtZSAAbWluZWNyYWZ0OmNoaXNlbGVkX25ldGhlcl9icmlja3MECQBuYW1lX2hhc2g31SBPTcUK1QMKAG5ldHdvcmtfaWR7MgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:cracked_nether_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQuAgAACAQAbmFtZR8AbWluZWNyYWZ0OmNyYWNrZWRfbmV0aGVyX2JyaWNrcwQJAG5hbWVfaGFzaAdC6eKzXT5tAwoAbmV0d29ya19pZPMcAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:quartz_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQvAgAACAQAbmFtZRcAbWluZWNyYWZ0OnF1YXJ0el9icmlja3MECQBuYW1lX2hhc2jSZO590dd8sAMKAG5ldHdvcmtfaWTrLAAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:stonebrick", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAAAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWTqLQAACgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQcAZGVmYXVsdAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:stonebrick", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAAAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWTrLQAACgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQUAbW9zc3kAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:stonebrick", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAAAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWTsLQAACgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQcAY3JhY2tlZAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:stonebrick", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAAAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWTtLQAACgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQgAY2hpc2VsZWQAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:end_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTOAAAACAQAbmFtZRQAbWluZWNyYWZ0OmVuZF9icmlja3MECQBuYW1lX2hhc2hIUFfxNLZaFgMKAG5ldHdvcmtfaWTfAgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:prismarine", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAAAACAQAbmFtZRQAbWluZWNyYWZ0OnByaXNtYXJpbmUECQBuYW1lX2hhc2jcnQCHi9CspQMKAG5ldHdvcmtfaWThKwAACgYAc3RhdGVzCBUAcHJpc21hcmluZV9ibG9ja190eXBlBgBicmlja3MAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:polished_blackstone_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQRAgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tzBAkAbmFtZV9oYXNoIHgsgIdzKXcDCgBuZXR3b3JrX2lkNR8AAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:cracked_polished_blackstone_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQXAgAACAQAbmFtZSwAbWluZWNyYWZ0OmNyYWNrZWRfcG9saXNoZWRfYmxhY2tzdG9uZV9icmlja3MECQBuYW1lX2hhc2jQIO1GQDk80AMKAG5ldHdvcmtfaWRGMgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:gilded_blackstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAgAACAQAbmFtZRsAbWluZWNyYWZ0OmdpbGRlZF9ibGFja3N0b25lBAkAbmFtZV9oYXNoNoWt1ocG0HEDCgBuZXR3b3JrX2lkKR0AAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:chiseled_polished_blackstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQWAgAACAQAbmFtZSYAbWluZWNyYWZ0OmNoaXNlbGVkX3BvbGlzaGVkX2JsYWNrc3RvbmUECQBuYW1lX2hhc2gzFa+kEjCJgAMKAG5ldHdvcmtfaWSEIgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:deepslate_tiles", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSCAgAACAQAbmFtZRkAbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlcwQJAG5hbWVfaGFzaGcLLx3NXAFvAwoAbmV0d29ya19pZBEdAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:cracked_deepslate_tiles", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSYAgAACAQAbmFtZSEAbWluZWNyYWZ0OmNyYWNrZWRfZGVlcHNsYXRlX3RpbGVzBAkAbmFtZV9oYXNo9zWgkFuMM1QDCgBuZXR3b3JrX2lkJBsAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:deepslate_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSGAgAACAQAbmFtZRoAbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja3MECQBuYW1lX2hhc2gucvFmPdZxigMKAG5ldHdvcmtfaWQ/JAAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:cracked_deepslate_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSZAgAACAQAbmFtZSIAbWluZWNyYWZ0OmNyYWNrZWRfZGVlcHNsYXRlX2JyaWNrcwQJAG5hbWVfaGFzaN40aqhh9WqHAwoAbmV0d29ya19pZLcjAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:chiseled_deepslate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSKAgAACAQAbmFtZRwAbWluZWNyYWZ0OmNoaXNlbGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaEU7/uRG8HSBAwoAbmV0d29ya19pZDAjAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:cobblestone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQEAAAACAQAbmFtZRUAbWluZWNyYWZ0OmNvYmJsZXN0b25lBAkAbmFtZV9oYXNoPoK7mGlSUz4DCgBuZXR3b3JrX2lkcxcAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:mossy_cobblestone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQwAAAACAQAbmFtZRsAbWluZWNyYWZ0Om1vc3N5X2NvYmJsZXN0b25lBAkAbmFtZV9oYXNoGJ67FCbkChMDCgBuZXR3b3JrX2lkqAIAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:cobbled_deepslate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR6AgAACAQAbmFtZRsAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlBAkAbmFtZV9oYXNoLUz9Y/ywmLwDCgBuZXR3b3JrX2lkaS4AAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:smooth_stone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AQAACAQAbmFtZRYAbWluZWNyYWZ0OnNtb290aF9zdG9uZQQJAG5hbWVfaGFzaMwf87/JaTNvAwoAbmV0d29ya19pZBIdAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAAAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZJ0XAAAKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGUHAGRlZmF1bHQAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAAAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZJ4XAAAKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGULAGhlaXJvZ2x5cGhzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAAAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZJ8XAAAKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGUDAGN1dAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAAAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZKAXAAAKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGUGAHNtb290aAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:red_sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSzAAAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWQLLgAACgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlBwBkZWZhdWx0AAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:red_sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSzAAAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWQMLgAACgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlCwBoZWlyb2dseXBocwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:red_sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSzAAAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWQNLgAACgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlAwBjdXQAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:red_sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSzAAAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWQOLgAACgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlBgBzbW9vdGgAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:coal_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWStAAAACAQAbmFtZRQAbWluZWNyYWZ0OmNvYWxfYmxvY2sECQBuYW1lX2hhc2jH8QQP3t5PiAMKAG5ldHdvcmtfaWTcIwAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:dried_kelp_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSKAQAACAQAbmFtZRoAbWluZWNyYWZ0OmRyaWVkX2tlbHBfYmxvY2sECQBuYW1lX2hhc2iRoucexkrl8wMKAG5ldHdvcmtfaWTKNQAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:gold_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQpAAAACAQAbmFtZRQAbWluZWNyYWZ0OmdvbGRfYmxvY2sECQBuYW1lX2hhc2iYLshvjtXzFwMKAG5ldHdvcmtfaWQKAwAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:iron_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQqAAAACAQAbmFtZRQAbWluZWNyYWZ0Omlyb25fYmxvY2sECQBuYW1lX2hhc2jYINmJQbvV/gMKAG5ldHdvcmtfaWT5NgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:copper_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRTAgAACAQAbmFtZRYAbWluZWNyYWZ0OmNvcHBlcl9ibG9jawQJAG5hbWVfaGFzaDVxnehsGaZ1AwoAbmV0d29ya19pZBgfAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:exposed_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRUAgAACAQAbmFtZRgAbWluZWNyYWZ0OmV4cG9zZWRfY29wcGVyBAkAbmFtZV9oYXNoQH3Fukmu3CEDCgBuZXR3b3JrX2lkRgUAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:weathered_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRVAgAACAQAbmFtZRoAbWluZWNyYWZ0OndlYXRoZXJlZF9jb3BwZXIECQBuYW1lX2hhc2hJCQXbvobv+gMKAG5ldHdvcmtfaWTVNgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:oxidized_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRWAgAACAQAbmFtZRkAbWluZWNyYWZ0Om94aWRpemVkX2NvcHBlcgQJAG5hbWVfaGFzaMDtJqR0G5Y7AwoAbmV0d29ya19pZDEXAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:waxed_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRXAgAACAQAbmFtZRYAbWluZWNyYWZ0OndheGVkX2NvcHBlcgQJAG5hbWVfaGFzaPF+FG6Eh5fsAwoAbmV0d29ya19pZIA0AAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:waxed_exposed_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRYAgAACAQAbmFtZR4AbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY29wcGVyBAkAbmFtZV9oYXNoig8IOc+SCikDCgBuZXR3b3JrX2lkrwcAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:waxed_weathered_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRZAgAACAQAbmFtZSAAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jb3BwZXIECQBuYW1lX2hhc2gjtPq8MOdvKgMKAG5ldHdvcmtfaWS8BwAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:waxed_oxidized_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS9AgAACAQAbmFtZR8AbWluZWNyYWZ0OndheGVkX294aWRpemVkX2NvcHBlcgQJAG5hbWVfaGFzaMaORhsO+LzjAwoAbmV0d29ya19pZLUzAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRaAgAACAQAbmFtZRQAbWluZWNyYWZ0OmN1dF9jb3BwZXIECQBuYW1lX2hhc2hAfN3NGax3eAMKAG5ldHdvcmtfaWQ+HwAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:exposed_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRbAgAACAQAbmFtZRwAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcgQJAG5hbWVfaGFzaA85G3yv/w6pAwoAbmV0d29ya19pZEIsAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:weathered_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRcAgAACAQAbmFtZR4AbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyBAkAbmFtZV9oYXNoVgRV0fBaz88DCgBuZXR3b3JrX2lkNTIAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:oxidized_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRdAgAACAQAbmFtZR0AbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2iP8WmFWOkriwMKAG5ldHdvcmtfaWRNJAAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:waxed_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWReAgAACAQAbmFtZRoAbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2jumiwOZIqv2AMKAG5ldHdvcmtfaWS6MgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:waxed_exposed_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRfAgAACAQAbmFtZSIAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcgQJAG5hbWVfaGFzaPE/OfK6IoVMAwoAbmV0d29ya19pZEQYAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:waxed_weathered_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRgAgAACAQAbmFtZSQAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyBAkAbmFtZV9oYXNoCA1xDp11bnwDCgBuZXR3b3JrX2lknCEAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:waxed_oxidized_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS+AgAACAQAbmFtZSMAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2i1pZAsZYHLDAMKAG5ldHdvcmtfaWR5AgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:emerald_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAAAACAQAbmFtZRcAbWluZWNyYWZ0OmVtZXJhbGRfYmxvY2sECQBuYW1lX2hhc2hK6QunqJznNAMKAG5ldHdvcmtfaWQkCgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:diamond_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ5AAAACAQAbmFtZRcAbWluZWNyYWZ0OmRpYW1vbmRfYmxvY2sECQBuYW1lX2hhc2iGKrxuvkytFQMKAG5ldHdvcmtfaWTRAgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:lapis_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQWAAAACAQAbmFtZRUAbWluZWNyYWZ0OmxhcGlzX2Jsb2NrBAkAbmFtZV9oYXNoDZ44xdb2zVoDCgBuZXR3b3JrX2lkrhsAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:raw_iron_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTCAgAACAQAbmFtZRgAbWluZWNyYWZ0OnJhd19pcm9uX2Jsb2NrBAkAbmFtZV9oYXNo9XyzNIQXxvwDCgBuZXR3b3JrX2lk9jYAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:raw_copper_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTDAgAACAQAbmFtZRoAbWluZWNyYWZ0OnJhd19jb3BwZXJfYmxvY2sECQBuYW1lX2hhc2hw1KG0TNUGgwMKAG5ldHdvcmtfaWRlIwAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:raw_gold_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTEAgAACAQAbmFtZRgAbWluZWNyYWZ0OnJhd19nb2xkX2Jsb2NrBAkAbmFtZV9oYXNo6YuwuLwfOBwDCgBuZXR3b3JrX2lkVAQAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:quartz_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAAAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZMgXAAAKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQcAZGVmYXVsdAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:quartz_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAAAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZMoXAAAKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQUAbGluZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:quartz_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAAAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZMkXAAAKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQgAY2hpc2VsZWQICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:quartz_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAAAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZMsXAAAKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQYAc21vb3RoCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:prismarine", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAAAACAQAbmFtZRQAbWluZWNyYWZ0OnByaXNtYXJpbmUECQBuYW1lX2hhc2jcnQCHi9CspQMKAG5ldHdvcmtfaWTfKwAACgYAc3RhdGVzCBUAcHJpc21hcmluZV9ibG9ja190eXBlBwBkZWZhdWx0AAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:prismarine", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAAAACAQAbmFtZRQAbWluZWNyYWZ0OnByaXNtYXJpbmUECQBuYW1lX2hhc2jcnQCHi9CspQMKAG5ldHdvcmtfaWTgKwAACgYAc3RhdGVzCBUAcHJpc21hcmluZV9ibG9ja190eXBlBABkYXJrAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:slime", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAAAACAQAbmFtZQ8AbWluZWNyYWZ0OnNsaW1lBAkAbmFtZV9oYXNoHJiEEJx+JlkDCgBuZXR3b3JrX2lkdhsAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:honey_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTbAQAACAQAbmFtZRUAbWluZWNyYWZ0OmhvbmV5X2Jsb2NrBAkAbmFtZV9oYXNo9zLYSUlelywDCgBuZXR3b3JrX2lkHwkAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:honeycomb_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTcAQAACAQAbmFtZRkAbWluZWNyYWZ0OmhvbmV5Y29tYl9ibG9jawQJAG5hbWVfaGFzaASIPuOCYd1oAwoAbmV0d29ya19pZKUcAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:hay_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSqAAAACAQAbmFtZRMAbWluZWNyYWZ0OmhheV9ibG9jawQJAG5hbWVfaGFzaIB2VxKxX8EpAwoAbmV0d29ya19pZLAHAAAKBgBzdGF0ZXMDCgBkZXByZWNhdGVkAAAAAAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:bone_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTYAAAACAQAbmFtZRQAbWluZWNyYWZ0OmJvbmVfYmxvY2sECQBuYW1lX2hhc2i4ZX576W9AWgMKAG5ldHdvcmtfaWR3GwAACgYAc3RhdGVzAwoAZGVwcmVjYXRlZAAAAAAICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:nether_brick", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRwAAAACAQAbmFtZRYAbWluZWNyYWZ0Om5ldGhlcl9icmljawQJAG5hbWVfaGFzaMxcRiheU+nXAwoAbmV0d29ya19pZKUyAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:red_nether_brick", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTXAAAACAQAbmFtZRoAbWluZWNyYWZ0OnJlZF9uZXRoZXJfYnJpY2sECQBuYW1lX2hhc2j8pRO4LfoECAMKAG5ldHdvcmtfaWQ0AgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:netherite_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQNAgAACAQAbmFtZRkAbWluZWNyYWZ0Om5ldGhlcml0ZV9ibG9jawQJAG5hbWVfaGFzaMghh6Zib/ZKAwoAbmV0d29ya19pZCEYAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:lodestone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTdAQAACAQAbmFtZRMAbWluZWNyYWZ0OmxvZGVzdG9uZQQJAG5hbWVfaGFzaJ2gmHOTlXv8AwoAbmV0d29ya19pZPM2AAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:white_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQjAAAACAQAbmFtZRQAbWluZWNyYWZ0OndoaXRlX3dvb2wECQBuYW1lX2hhc2jRWB7vaIEDiQMKAG5ldHdvcmtfaWTdIwAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:light_gray_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQnAwAACAQAbmFtZRkAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfd29vbAQJAG5hbWVfaGFzaOpdQ1a2v4b3AwoAbmV0d29ya19pZAo2AAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:gray_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQoAwAACAQAbmFtZRMAbWluZWNyYWZ0OmdyYXlfd29vbAQJAG5hbWVfaGFzaLsc1Lp1xdIOAwoAbmV0d29ya19pZIcCAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:black_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQpAwAACAQAbmFtZRQAbWluZWNyYWZ0OmJsYWNrX3dvb2wECQBuYW1lX2hhc2hP2HC6o0X4HAMKAG5ldHdvcmtfaWRXBAAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:brown_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQqAwAACAQAbmFtZRQAbWluZWNyYWZ0OmJyb3duX3dvb2wECQBuYW1lX2hhc2ig5IW89PrREwMKAG5ldHdvcmtfaWS9AgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:red_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQrAwAACAQAbmFtZRIAbWluZWNyYWZ0OnJlZF93b29sBAkAbmFtZV9oYXNoY4TBDq+mFgUDCgBuZXR3b3JrX2lkfwAAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:orange_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAwAACAQAbmFtZRUAbWluZWNyYWZ0Om9yYW5nZV93b29sBAkAbmFtZV9oYXNoFstfrTZfSCgDCgBuZXR3b3JrX2lknAcAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:yellow_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQtAwAACAQAbmFtZRUAbWluZWNyYWZ0OnllbGxvd193b29sBAkAbmFtZV9oYXNoTFyus2RHegcDCgBuZXR3b3JrX2lkKgIAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:lime_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQuAwAACAQAbmFtZRMAbWluZWNyYWZ0OmxpbWVfd29vbAQJAG5hbWVfaGFzaNVnnzKiMxmeAwoAbmV0d29ya19pZHorAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:green_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQvAwAACAQAbmFtZRQAbWluZWNyYWZ0OmdyZWVuX3dvb2wECQBuYW1lX2hhc2i3mElRYHIcSQMKAG5ldHdvcmtfaWTtFwAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:cyan_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQwAwAACAQAbmFtZRMAbWluZWNyYWZ0OmN5YW5fd29vbAQJAG5hbWVfaGFzaBNDfvHn8dqFAwoAbmV0d29ya19pZKEjAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:light_blue_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQxAwAACAQAbmFtZRkAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfd29vbAQJAG5hbWVfaGFzaLWFAUfyxFPNAwoAbmV0d29ya19pZDMwAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:blue_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQyAwAACAQAbmFtZRMAbWluZWNyYWZ0OmJsdWVfd29vbAQJAG5hbWVfaGFzaLjHyxxbTWCLAwoAbmV0d29ya19pZE4kAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:purple_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQzAwAACAQAbmFtZRUAbWluZWNyYWZ0OnB1cnBsZV93b29sBAkAbmFtZV9oYXNojvFtqzjAf/4DCgBuZXR3b3JrX2lk+DYAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:magenta_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ0AwAACAQAbmFtZRYAbWluZWNyYWZ0Om1hZ2VudGFfd29vbAQJAG5hbWVfaGFzaGuOHvf+Pd4yAwoAbmV0d29ya19pZG8JAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:pink_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ1AwAACAQAbmFtZRMAbWluZWNyYWZ0OnBpbmtfd29vbAQJAG5hbWVfaGFzaPiVA2pFeoFLAwoAbmV0d29ya19pZCIYAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:white_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSrAAAACAQAbmFtZRYAbWluZWNyYWZ0OndoaXRlX2NhcnBldAQJAG5hbWVfaGFzaNeMHTI1fWPXAwoAbmV0d29ya19pZJkyAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:light_gray_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRbAwAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY2FycGV0BAkAbmFtZV9oYXNoHPw6ArBAsP0DCgBuZXR3b3JrX2lk9zYAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:gray_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRaAwAACAQAbmFtZRUAbWluZWNyYWZ0OmdyYXlfY2FycGV0BAkAbmFtZV9oYXNoZVR0OI+1VRADCgBuZXR3b3JrX2lkigIAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:black_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJsYWNrX2NhcnBldAQJAG5hbWVfaGFzaOk7LP9NptyhAwoAbmV0d29ya19pZKErAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:brown_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRfAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJyb3duX2NhcnBldAQJAG5hbWVfaGFzaNaXFyOsAvIvAwoAbmV0d29ya19pZFIJAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:red_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAwAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9jYXJwZXQECQBuYW1lX2hhc2i9eSKBf6SO3wMKAG5ldHdvcmtfaWQ3MwAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:orange_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRUAwAACAQAbmFtZRcAbWluZWNyYWZ0Om9yYW5nZV9jYXJwZXQECQBuYW1lX2hhc2hIUkO4HlAdygMKAG5ldHdvcmtfaWQKMAAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:yellow_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRXAwAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19jYXJwZXQECQBuYW1lX2hhc2hSDKX3scCamwMKAG5ldHdvcmtfaWRXKQAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:lime_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRYAwAACAQAbmFtZRUAbWluZWNyYWZ0OmxpbWVfY2FycGV0BAkAbmFtZV9oYXNo+6KFOpzsib4DCgBuZXR3b3JrX2lklS4AAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:green_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRgAwAACAQAbmFtZRYAbWluZWNyYWZ0OmdyZWVuX2NhcnBldAQJAG5hbWVfaGFzaCHPMP9ltqFJAwoAbmV0d29ya19pZO4XAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:cyan_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRcAwAACAQAbmFtZRUAbWluZWNyYWZ0OmN5YW5fY2FycGV0BAkAbmFtZV9oYXNobXf62dQBJj8DCgBuZXR3b3JrX2lkdhcAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:light_blue_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRWAwAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY2FycGV0BAkAbmFtZV9oYXNo20l4oktdZ3sDCgBuZXR3b3JrX2lk6R8AAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:blue_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWReAwAACAQAbmFtZRUAbWluZWNyYWZ0OmJsdWVfY2FycGV0BAkAbmFtZV9oYXNo3p3lsW0eQwsDCgBuZXR3b3JrX2lkVQIAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:purple_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRdAwAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnBsZV9jYXJwZXQECQBuYW1lX2hhc2jwIA9pW/qp7QMKAG5ldHdvcmtfaWSRNAAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:magenta_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRVAwAACAQAbmFtZRgAbWluZWNyYWZ0Om1hZ2VudGFfY2FycGV0BAkAbmFtZV9oYXNoFXT36YNNZhMDCgBuZXR3b3JrX2lkrAIAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:pink_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRZAwAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfY2FycGV0BAkAbmFtZV9oYXNoHll72oqk+OoDCgBuZXR3b3JrX2lkVzQAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:white_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTtAAAACAQAbmFtZR8AbWluZWNyYWZ0OndoaXRlX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaFUk9iXVjwV8AwoAbmV0d29ya19pZGohAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:light_gray_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTLAwAACAQAbmFtZSQAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNo7EUk30hmUtYDCgBuZXR3b3JrX2lkiTIAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:gray_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTKAwAACAQAbmFtZR4AbWluZWNyYWZ0OmdyYXlfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoW77af6WihdwDCgBuZXR3b3JrX2lkATMAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:black_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTSAwAACAQAbmFtZR8AbWluZWNyYWZ0OmJsYWNrX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaAfWYp0xtgcfAwoAbmV0d29ya19pZHkEAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:brown_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTPAwAACAQAbmFtZR8AbWluZWNyYWZ0OmJyb3duX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaB74EeiLO46XAwoAbmV0d29ya19pZJMnAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:red_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTRAwAACAQAbmFtZR0AbWluZWNyYWZ0OnJlZF9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2gjFut6Z/VH1gMKAG5ldHdvcmtfaWSIMgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:orange_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTEAwAACAQAbmFtZSAAbWluZWNyYWZ0Om9yYW5nZV9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2gADDj2IJiw+gMKAG5ldHdvcmtfaWTSNgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:yellow_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTHAwAACAQAbmFtZSAAbWluZWNyYWZ0OnllbGxvd19jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2iy6qKNn3ob5wMKAG5ldHdvcmtfaWTdMwAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:lime_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTIAwAACAQAbmFtZR4AbWluZWNyYWZ0OmxpbWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNo4dYIPslbXPUDCgBuZXR3b3JrX2lk3jUAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:green_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTQAwAACAQAbmFtZR8AbWluZWNyYWZ0OmdyZWVuX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaM/c9x2aJh3HAwoAbmV0d29ya19pZM0vAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:cyan_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTMAwAACAQAbmFtZR4AbWluZWNyYWZ0OmN5YW5fY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNok+xKAe7XXjoDCgBuZXR3b3JrX2lkGhcAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:light_blue_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTGAwAACAQAbmFtZSQAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNogScpIQceyAEDCgBuZXR3b3JrX2lkPgAAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:blue_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTOAwAACAQAbmFtZR4AbWluZWNyYWZ0OmJsdWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoFp7mmeL86r0DCgBuZXR3b3JrX2lkki4AAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:purple_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTNAwAACAQAbmFtZSAAbWluZWNyYWZ0OnB1cnBsZV9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2iYcVU04hoStwMKAG5ldHdvcmtfaWThLQAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:magenta_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTFAwAACAQAbmFtZSEAbWluZWNyYWZ0Om1hZ2VudGFfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoy/70q6VPsWgDCgBuZXR3b3JrX2lkhBwAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:pink_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAwAACAQAbmFtZR4AbWluZWNyYWZ0OnBpbmtfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoVikSAf8DwV0DCgBuZXR3b3JrX2lkuBsAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:white_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTsAAAACAQAbmFtZRgAbWluZWNyYWZ0OndoaXRlX2NvbmNyZXRlBAkAbmFtZV9oYXNo6zAp7lsLlvkDCgBuZXR3b3JrX2lkJzYAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:light_gray_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR6AwAACAQAbmFtZR0AbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY29uY3JldGUECQBuYW1lX2hhc2hEtet5wuDIKAMKAG5ldHdvcmtfaWSmBwAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:gray_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR5AwAACAQAbmFtZRcAbWluZWNyYWZ0OmdyYXlfY29uY3JldGUECQBuYW1lX2hhc2j92INnb0a83AMKAG5ldHdvcmtfaWQCMwAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:black_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSBAwAACAQAbmFtZRgAbWluZWNyYWZ0OmJsYWNrX2NvbmNyZXRlBAkAbmFtZV9oYXNo2X7NDIQmZ70DCgBuZXR3b3JrX2lkgi4AAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:brown_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR+AwAACAQAbmFtZRgAbWluZWNyYWZ0OmJyb3duX2NvbmNyZXRlBAkAbmFtZV9oYXNoeka02BwXf6oDCgBuZXR3b3JrX2lkZCwAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:red_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSAAwAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZF9jb25jcmV0ZQQJAG5hbWVfaGFzaPWmNowLGubqAwoAbmV0d29ya19pZFY0AAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:orange_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRzAwAACAQAbmFtZRkAbWluZWNyYWZ0Om9yYW5nZV9jb25jcmV0ZQQJAG5hbWVfaGFzaAgE8XmaAi6+AwoAbmV0d29ya19pZJMuAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:yellow_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR2AwAACAQAbmFtZRkAbWluZWNyYWZ0OnllbGxvd19jb25jcmV0ZQQJAG5hbWVfaGFzaE6ONfJPBd0+AwoAbmV0d29ya19pZHUXAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:lime_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR3AwAACAQAbmFtZRcAbWluZWNyYWZ0OmxpbWVfY29uY3JldGUECQBuYW1lX2hhc2gnd8JW6wmJcAMKAG5ldHdvcmtfaWQlHQAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:green_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR/AwAACAQAbmFtZRgAbWluZWNyYWZ0OmdyZWVuX2NvbmNyZXRlBAkAbmFtZV9oYXNokbFxRKchQZkDCgBuZXR3b3JrX2lkPSkAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:cyan_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR7AwAACAQAbmFtZRcAbWluZWNyYWZ0OmN5YW5fY29uY3JldGUECQBuYW1lX2hhc2hFRrWJ33qj1wMKAG5ldHdvcmtfaWSaMgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:light_blue_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR1AwAACAQAbmFtZR0AbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY29uY3JldGUECQBuYW1lX2hhc2gHAe0kl0SE4AMKAG5ldHdvcmtfaWRKMwAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:blue_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR9AwAACAQAbmFtZRcAbWluZWNyYWZ0OmJsdWVfY29uY3JldGUECQBuYW1lX2hhc2hiay301nnj1wMKAG5ldHdvcmtfaWSkMgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:purple_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR8AwAACAQAbmFtZRkAbWluZWNyYWZ0OnB1cnBsZV9jb25jcmV0ZQQJAG5hbWVfaGFzaHBHflsPIwdXAwoAbmV0d29ya19pZEYbAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:magenta_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR0AwAACAQAbmFtZRoAbWluZWNyYWZ0Om1hZ2VudGFfY29uY3JldGUECQBuYW1lX2hhc2gN7LuB/OvdZAMKAG5ldHdvcmtfaWQpHAAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:pink_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR4AwAACAQAbmFtZRcAbWluZWNyYWZ0OnBpbmtfY29uY3JldGUECQBuYW1lX2hhc2ii2G5F0u3SOAMKAG5ldHdvcmtfaWSXFQAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:clay", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRSAAAACAQAbmFtZQ4AbWluZWNyYWZ0OmNsYXkECQBuYW1lX2hhc2j/S6sKXRcpzwMKAG5ldHdvcmtfaWRjMAAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:hardened_clay", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSsAAAACAQAbmFtZRcAbWluZWNyYWZ0OmhhcmRlbmVkX2NsYXkECQBuYW1lX2hhc2jrnRwCJ0krJAMKAG5ldHdvcmtfaWRmBQAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:white_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSfAAAACAQAbmFtZRoAbWluZWNyYWZ0OndoaXRlX3RlcnJhY290dGEECQBuYW1lX2hhc2j3RSdgmnAIewMKAG5ldHdvcmtfaWToHwAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:light_gray_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTaAwAACAQAbmFtZR8AbWluZWNyYWZ0OmxpZ2h0X2dyYXlfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAz1Ri3wIxomAwoAbmV0d29ya19pZOwGAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:gray_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTZAwAACAQAbmFtZRkAbWluZWNyYWZ0OmdyYXlfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAXdSLAaNZ9vAwoAbmV0d29ya19pZBQdAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:black_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWThAwAACAQAbmFtZRoAbWluZWNyYWZ0OmJsYWNrX3RlcnJhY290dGEECQBuYW1lX2hhc2jxssdv5vlbpgMKAG5ldHdvcmtfaWT0KwAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:brown_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTeAwAACAQAbmFtZRoAbWluZWNyYWZ0OmJyb3duX3RlcnJhY290dGEECQBuYW1lX2hhc2gG4kPenmOF9gMKAG5ldHdvcmtfaWT4NQAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:red_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTgAwAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNo7fX56HXFejEDCgBuZXR3b3JrX2lkagkAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:orange_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTTAwAACAQAbmFtZRsAbWluZWNyYWZ0Om9yYW5nZV90ZXJyYWNvdHRhBAkAbmFtZV9oYXNo0Hjmql3sruMDCgBuZXR3b3JrX2lktDMAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:yellow_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTWAwAACAQAbmFtZRsAbWluZWNyYWZ0OnllbGxvd190ZXJyYWNvdHRhBAkAbmFtZV9oYXNoqkyKKrmA3VcDCgBuZXR3b3JrX2lkThsAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:lime_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTXAwAACAQAbmFtZRkAbWluZWNyYWZ0OmxpbWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaANjADFOF9v7AwoAbmV0d29ya19pZNw2AAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:green_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTfAwAACAQAbmFtZRoAbWluZWNyYWZ0OmdyZWVuX3RlcnJhY290dGEECQBuYW1lX2hhc2j5Ybq36yYwRQMKAG5ldHdvcmtfaWTeFwAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:cyan_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTbAwAACAQAbmFtZRkAbWluZWNyYWZ0OmN5YW5fdGVycmFjb3R0YQQJAG5hbWVfaGFzaN09COzMuHwAAwoAbmV0d29ya19pZAAAAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:light_blue_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTVAwAACAQAbmFtZR8AbWluZWNyYWZ0OmxpZ2h0X2JsdWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaOMytez7cOZiAwoAbmV0d29ya19pZBscAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:blue_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTdAwAACAQAbmFtZRkAbWluZWNyYWZ0OmJsdWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaF6inyTK5RpAAwoAbmV0d29ya19pZJwXAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:purple_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTcAwAACAQAbmFtZRsAbWluZWNyYWZ0OnB1cnBsZV90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoKF7YG61yTbEDCgBuZXR3b3JrX2lkEi0AAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:magenta_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTUAwAACAQAbmFtZRwAbWluZWNyYWZ0Om1hZ2VudGFfdGVycmFjb3R0YQQJAG5hbWVfaGFzaLWvtpAVtztyAwoAbmV0d29ya19pZCsdAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:pink_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTYAwAACAQAbmFtZRkAbWluZWNyYWZ0OnBpbmtfdGVycmFjb3R0YQQJAG5hbWVfaGFzaJ7mzvyzSQZTAwoAbmV0d29ya19pZCEbAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:white_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTcAAAACAQAbmFtZSEAbWluZWNyYWZ0OndoaXRlX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoiVzCdoHAJo0DCgBuZXR3b3JrX2lkrSQAAAoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:silver_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTkAAAACAQAbmFtZSIAbWluZWNyYWZ0OnNpbHZlcl9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAVsA0CnhzA4AwoAbmV0d29ya19pZIkVAAAKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:gray_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTjAAAACAQAbmFtZSAAbWluZWNyYWZ0OmdyYXlfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2jvLZt9u/lF/AMKAG5ldHdvcmtfaWTtNgAACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:black_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTrAAAACAQAbmFtZSEAbWluZWNyYWZ0OmJsYWNrX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoe8I4xAXbO5UDCgBuZXR3b3JrX2lkOicAAAoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:brown_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWToAAAACAQAbmFtZSEAbWluZWNyYWZ0OmJyb3duX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoSiNZOobbpjoDCgBuZXR3b3JrX2lkGxcAAAoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:red_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTqAAAACAQAbmFtZR8AbWluZWNyYWZ0OnJlZF9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaBdWFGLmCLFVAwoAbmV0d29ya19pZCsbAAAKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:orange_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTdAAAACAQAbmFtZSIAbWluZWNyYWZ0Om9yYW5nZV9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaMyJMrnPr7szAwoAbmV0d29ya19pZBoKAAAKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:yellow_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTgAAAACAQAbmFtZSIAbWluZWNyYWZ0OnllbGxvd19nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaN6NaIhf6m0uAwoAbmV0d29ya19pZEQJAAAKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:lime_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWThAAAACAQAbmFtZSAAbWluZWNyYWZ0OmxpbWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2iF3E68/rB2EAMKAG5ldHdvcmtfaWSLAgAACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:green_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTpAAAACAQAbmFtZSEAbWluZWNyYWZ0OmdyZWVuX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNow5mo8aQDFboDCgBuZXR3b3JrX2lkKi4AAAoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:cyan_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTlAAAACAQAbmFtZSAAbWluZWNyYWZ0OmN5YW5fZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2gnNB+cCFRJhwMKAG5ldHdvcmtfaWSxIwAACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:light_blue_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTfAAAACAQAbmFtZSYAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2gladnCDBKCigMKAG5ldHdvcmtfaWRGJAAACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:blue_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTnAAAACAQAbmFtZSAAbWluZWNyYWZ0OmJsdWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2giOZK+2nB1igMKAG5ldHdvcmtfaWRAJAAACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:purple_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTbAAAACAQAbmFtZSIAbWluZWNyYWZ0OnB1cnBsZV9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaIQU03txeAfHAwoAbmV0d29ya19pZMcvAAAKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:magenta_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTeAAAACAQAbmFtZSMAbWluZWNyYWZ0Om1hZ2VudGFfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2i/SNqDJbfjMgMKAG5ldHdvcmtfaWRwCQAACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:pink_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTiAAAACAQAbmFtZSAAbWluZWNyYWZ0OnBpbmtfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2hik8DVt4g+twMKAG5ldHdvcmtfaWTiLQAACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:purpur_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAAAACAQAbmFtZRYAbWluZWNyYWZ0OnB1cnB1cl9ibG9jawQJAG5hbWVfaGFzaAgLwnUZGlzsAwoAbmV0d29ya19pZGY0AAAKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQcAZGVmYXVsdAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:purpur_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAAAACAQAbmFtZRYAbWluZWNyYWZ0OnB1cnB1cl9ibG9jawQJAG5hbWVfaGFzaAgLwnUZGlzsAwoAbmV0d29ya19pZGg0AAAKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQUAbGluZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:packed_mud", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTcAgAACAQAbmFtZRQAbWluZWNyYWZ0OnBhY2tlZF9tdWQECQBuYW1lX2hhc2gHOMa121h4FgMKAG5ldHdvcmtfaWTiAgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:mud_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTaAgAACAQAbmFtZRQAbWluZWNyYWZ0Om11ZF9icmlja3MECQBuYW1lX2hhc2iDL/SVl/PewQMKAG5ldHdvcmtfaWRBLwAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:nether_wart_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTWAAAACAQAbmFtZRsAbWluZWNyYWZ0Om5ldGhlcl93YXJ0X2Jsb2NrBAkAbmFtZV9oYXNo9XGS4GNnlV4DCgBuZXR3b3JrX2lkuhsAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:warped_wart_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTiAQAACAQAbmFtZRsAbWluZWNyYWZ0OndhcnBlZF93YXJ0X2Jsb2NrBAkAbmFtZV9oYXNo9IqDS9yUPJoDCgBuZXR3b3JrX2lkRSkAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:shroomlight", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTlAQAACAQAbmFtZRUAbWluZWNyYWZ0OnNocm9vbWxpZ2h0BAkAbmFtZV9oYXNoZHCHcHX/HYADCgBuZXR3b3JrX2lkcyIAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:crimson_nylium", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTnAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fbnlsaXVtBAkAbmFtZV9oYXNoOr6DJYW2bFYDCgBuZXR3b3JrX2lkQxsAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:warped_nylium", + "block_state_b64": "CgAAAwgAYmxvY2tfaWToAQAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9ueWxpdW0ECQBuYW1lX2hhc2g0Zf89cfr3rwMKAG5ldHdvcmtfaWTpLAAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:netherrack", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRXAAAACAQAbmFtZRQAbWluZWNyYWZ0Om5ldGhlcnJhY2sECQBuYW1lX2hhc2i/r5ZyRsvPyQMKAG5ldHdvcmtfaWTlLwAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:basalt", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTpAQAACAQAbmFtZRAAbWluZWNyYWZ0OmJhc2FsdAQJAG5hbWVfaGFzaH+UQO2yWodiAwoAbmV0d29ya19pZBccAAAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:polished_basalt", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTqAQAACAQAbmFtZRkAbWluZWNyYWZ0OnBvbGlzaGVkX2Jhc2FsdAQJAG5hbWVfaGFzaMS+L0gMnRcBAwoAbmV0d29ya19pZBoAAAAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:smooth_basalt", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR4AgAACAQAbmFtZRcAbWluZWNyYWZ0OnNtb290aF9iYXNhbHQECQBuYW1lX2hhc2jKPUdz89kuNAMKAG5ldHdvcmtfaWQhCgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:soul_soil", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTrAQAACAQAbmFtZRMAbWluZWNyYWZ0OnNvdWxfc29pbAQJAG5hbWVfaGFzaC1/87ccutuTAwoAbmV0d29ya19pZLElAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:dirt", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAAAACAQAbmFtZQ4AbWluZWNyYWZ0OmRpcnQECQBuYW1lX2hhc2hXp6jnXAe+kQMKAG5ldHdvcmtfaWRgJQAACgYAc3RhdGVzCAkAZGlydF90eXBlBgBub3JtYWwAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:dirt", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAAAACAQAbmFtZQ4AbWluZWNyYWZ0OmRpcnQECQBuYW1lX2hhc2hXp6jnXAe+kQMKAG5ldHdvcmtfaWRhJQAACgYAc3RhdGVzCAkAZGlydF90eXBlBgBjb2Fyc2UAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:farmland", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ8AAAACAQAbmFtZRIAbWluZWNyYWZ0OmZhcm1sYW5kBAkAbmFtZV9oYXNoxyQ5ag7LolADCgBuZXR3b3JrX2lkKRoAAAoGAHN0YXRlcwMSAG1vaXN0dXJpemVkX2Ftb3VudAAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:grass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQCAAAACAQAbmFtZQ8AbWluZWNyYWZ0OmdyYXNzBAkAbmFtZV9oYXNosppASPWFlsUDCgBuZXR3b3JrX2lkoC8AAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:grass_path", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTGAAAACAQAbmFtZRQAbWluZWNyYWZ0OmdyYXNzX3BhdGgECQBuYW1lX2hhc2i0/KZV8Qsy+gMKAG5ldHdvcmtfaWQvNgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:podzol", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTzAAAACAQAbmFtZRAAbWluZWNyYWZ0OnBvZHpvbAQJAG5hbWVfaGFzaBzqokRjH4Z1AwoAbmV0d29ya19pZBcfAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:mycelium", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRuAAAACAQAbmFtZRIAbWluZWNyYWZ0Om15Y2VsaXVtBAkAbmFtZV9oYXNojTN09cKickIDCgBuZXR3b3JrX2lkuxcAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:mud", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTYAgAACAQAbmFtZQ0AbWluZWNyYWZ0Om11ZAQJAG5hbWVfaGFzaPb/3P+uLy+9AwoAbmV0d29ya19pZGsuAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:stone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQBAAAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lk9AYAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:iron_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQPAAAACAQAbmFtZRIAbWluZWNyYWZ0Omlyb25fb3JlBAkAbmFtZV9oYXNoS7BYtLnfx3gDCgBuZXR3b3JrX2lkPx8AAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:gold_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQOAAAACAQAbmFtZRIAbWluZWNyYWZ0OmdvbGRfb3JlBAkAbmFtZV9oYXNoC5Y+DUGXLC4DCgBuZXR3b3JrX2lkQwkAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:diamond_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ4AAAACAQAbmFtZRUAbWluZWNyYWZ0OmRpYW1vbmRfb3JlBAkAbmFtZV9oYXNokUOJ2wZZrGQDCgBuZXR3b3JrX2lkJxwAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:lapis_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQVAAAACAQAbmFtZRMAbWluZWNyYWZ0OmxhcGlzX29yZQQJAG5hbWVfaGFzaMrmrUrSzb7qAwoAbmV0d29ya19pZFU0AAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:redstone_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRJAAAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZHN0b25lX29yZQQJAG5hbWVfaGFzaFHVnp8Wc4JbAwoAbmV0d29ya19pZLEbAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:coal_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQQAAAACAQAbmFtZRIAbWluZWNyYWZ0OmNvYWxfb3JlBAkAbmFtZV9oYXNo1OjA+Iuy51oDCgBuZXR3b3JrX2lkrxsAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:copper_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ2AgAACAQAbmFtZRQAbWluZWNyYWZ0OmNvcHBlcl9vcmUECQBuYW1lX2hhc2iSZduSntOzOwMKAG5ldHdvcmtfaWQyFwAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:emerald_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSBAAAACAQAbmFtZRUAbWluZWNyYWZ0OmVtZXJhbGRfb3JlBAkAbmFtZV9oYXNoJTovr+VgINsDCgBuZXR3b3JrX2lk8DIAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:quartz_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSZAAAACAQAbmFtZRQAbWluZWNyYWZ0OnF1YXJ0el9vcmUECQBuYW1lX2hhc2g0yNHLMK9TaQMKAG5ldHdvcmtfaWS+HAAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:nether_gold_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQfAgAACAQAbmFtZRkAbWluZWNyYWZ0Om5ldGhlcl9nb2xkX29yZQQJAG5hbWVfaGFzaEJZ7segIBgBAwoAbmV0d29ya19pZB0AAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:ancient_debris", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQOAgAACAQAbmFtZRgAbWluZWNyYWZ0OmFuY2llbnRfZGVicmlzBAkAbmFtZV9oYXNoNrbxMc9AwKcDCgBuZXR3b3JrX2lkBiwAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:deepslate_iron_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSQAgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9pcm9uX29yZQQJAG5hbWVfaGFzaB/fDL9pgvXXAwoAbmV0d29ya19pZKYyAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:deepslate_gold_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSRAgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9nb2xkX29yZQQJAG5hbWVfaGFzaF9G7WYhKFinAwoAbmV0d29ya19pZAUsAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:deepslate_diamond_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSUAgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV9kaWFtb25kX29yZQQJAG5hbWVfaGFzaEUH5USh+iD3AwoAbmV0d29ya19pZPk1AAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:deepslate_lapis_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSPAgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV9sYXBpc19vcmUECQBuYW1lX2hhc2j+yFxU/KZs1gMKAG5ldHdvcmtfaWSKMgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:deepslate_redstone_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSSAgAACAQAbmFtZSAAbWluZWNyYWZ0OmRlZXBzbGF0ZV9yZWRzdG9uZV9vcmUECQBuYW1lX2hhc2iVgM3wWWD6ugMKAG5ldHdvcmtfaWQxLgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:deepslate_emerald_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSWAgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV9lbWVyYWxkX29yZQQJAG5hbWVfaGFzaNlfo5HTwS6wAwoAbmV0d29ya19pZOosAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:deepslate_coal_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSVAgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9jb2FsX29yZQQJAG5hbWVfaGFzaIjikmcbRrPPAwoAbmV0d29ya19pZDQyAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:deepslate_copper_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSXAgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9jb3BwZXJfb3JlBAkAbmFtZV9oYXNottjV4Ev5LAQDCgBuZXR3b3JrX2lkcgAAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:gravel", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQNAAAACAQAbmFtZRAAbWluZWNyYWZ0OmdyYXZlbAQJAG5hbWVfaGFzaOFxz8XJd2r/AwoAbmV0d29ya19pZBM3AAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:granite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRNAwAACAQAbmFtZREAbWluZWNyYWZ0OmdyYW5pdGUECQBuYW1lX2hhc2iq+Dur2pw4AwMKAG5ldHdvcmtfaWRTAAAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:diorite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRPAwAACAQAbmFtZREAbWluZWNyYWZ0OmRpb3JpdGUECQBuYW1lX2hhc2iaFsq2iinZBQMKAG5ldHdvcmtfaWSVAAAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:andesite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRRAwAACAQAbmFtZRIAbWluZWNyYWZ0OmFuZGVzaXRlBAkAbmFtZV9oYXNosaLIEnQQoSYDCgBuZXR3b3JrX2lk8gYAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:blackstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQQAgAACAQAbmFtZRQAbWluZWNyYWZ0OmJsYWNrc3RvbmUECQBuYW1lX2hhc2iMFYziD80D6QMKAG5ldHdvcmtfaWTlMwAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:deepslate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR5AgAACAQAbmFtZRMAbWluZWNyYWZ0OmRlZXBzbGF0ZQQJAG5hbWVfaGFzaKX5pAblxz8TAwoAbmV0d29ya19pZKkCAAAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:polished_granite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWROAwAACAQAbmFtZRoAbWluZWNyYWZ0OnBvbGlzaGVkX2dyYW5pdGUECQBuYW1lX2hhc2iLiEfys8pFIAMKAG5ldHdvcmtfaWSDBAAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:polished_diorite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRQAwAACAQAbmFtZRoAbWluZWNyYWZ0OnBvbGlzaGVkX2Rpb3JpdGUECQBuYW1lX2hhc2hTxY4fKmNmlAMKAG5ldHdvcmtfaWQzJwAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:polished_andesite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRSAwAACAQAbmFtZRsAbWluZWNyYWZ0OnBvbGlzaGVkX2FuZGVzaXRlBAkAbmFtZV9oYXNovl28uFk4HuQDCgBuZXR3b3JrX2lkujMAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:polished_blackstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQiAgAACAQAbmFtZR0AbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmUECQBuYW1lX2hhc2jT9fHCl6vWQQMKAG5ldHdvcmtfaWS6FwAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:polished_deepslate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR+AgAACAQAbmFtZRwAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaHC1edoaWF3uAwoAbmV0d29ya19pZJY0AAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:sand", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQMAAAACAQAbmFtZQ4AbWluZWNyYWZ0OnNhbmQECQBuYW1lX2hhc2i6lthXXbAyWAMKAG5ldHdvcmtfaWRQGwAACgYAc3RhdGVzCAkAc2FuZF90eXBlBgBub3JtYWwAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:sand", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQMAAAACAQAbmFtZQ4AbWluZWNyYWZ0OnNhbmQECQBuYW1lX2hhc2i6lthXXbAyWAMKAG5ldHdvcmtfaWRRGwAACgYAc3RhdGVzCAkAc2FuZF90eXBlAwByZWQAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:cactus", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRRAAAACAQAbmFtZRAAbWluZWNyYWZ0OmNhY3R1cwQJAG5hbWVfaGFzaCG9zL0N4wvGAwoAbmV0d29ya19pZKsvAAAKBgBzdGF0ZXMDAwBhZ2UAAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:oak_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQRAAAACAQAbmFtZREAbWluZWNyYWZ0Om9ha19sb2cECQBuYW1lX2hhc2ho6TS+K7PZFQMKAG5ldHdvcmtfaWTbAgAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:stripped_oak_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQJAQAACAQAbmFtZRoAbWluZWNyYWZ0OnN0cmlwcGVkX29ha19sb2cECQBuYW1lX2hhc2h8dqh+OOHU4wMKAG5ldHdvcmtfaWS3MwAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:spruce_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ4AwAACAQAbmFtZRQAbWluZWNyYWZ0OnNwcnVjZV9sb2cECQBuYW1lX2hhc2hZ03qaLoF3WgMKAG5ldHdvcmtfaWSbGwAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:stripped_spruce_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQEAQAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX3NwcnVjZV9sb2cECQBuYW1lX2hhc2iNrhKjS5IyrgMKAG5ldHdvcmtfaWSnLAAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:birch_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ5AwAACAQAbmFtZRMAbWluZWNyYWZ0OmJpcmNoX2xvZwQJAG5hbWVfaGFzaBUzT3NxsZAnAwoAbmV0d29ya19pZPUGAAAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:stripped_birch_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQFAQAACAQAbmFtZRwAbWluZWNyYWZ0OnN0cmlwcGVkX2JpcmNoX2xvZwQJAG5hbWVfaGFzaCFKS4AeuSidAwoAbmV0d29ya19pZNYpAAAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:jungle_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ6AwAACAQAbmFtZRQAbWluZWNyYWZ0Omp1bmdsZV9sb2cECQBuYW1lX2hhc2gkwW0KNulqDgMKAG5ldHdvcmtfaWR/AgAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:stripped_jungle_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAQAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2p1bmdsZV9sb2cECQBuYW1lX2hhc2hAwMsgOk02JAMKAG5ldHdvcmtfaWTnBgAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:acacia_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSiAAAACAQAbmFtZRQAbWluZWNyYWZ0OmFjYWNpYV9sb2cECQBuYW1lX2hhc2iV48VpYhjoYQMKAG5ldHdvcmtfaWQEHAAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:stripped_acacia_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQHAQAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2FjYWNpYV9sb2cECQBuYW1lX2hhc2hJb0lQqnEqlgMKAG5ldHdvcmtfaWRoJwAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:dark_oak_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ7AwAACAQAbmFtZRYAbWluZWNyYWZ0OmRhcmtfb2FrX2xvZwQJAG5hbWVfaGFzaIWfVRd0XUo3AwoAbmV0d29ya19pZCsTAAAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:stripped_dark_oak_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQIAQAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2Rhcmtfb2FrX2xvZwQJAG5hbWVfaGFzaPFTdxRdPwkOAwoAbmV0d29ya19pZHsCAAAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:mangrove_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTjAgAACAQAbmFtZRYAbWluZWNyYWZ0Om1hbmdyb3ZlX2xvZwQJAG5hbWVfaGFzaHZe6DzPZBobAwoAbmV0d29ya19pZEcEAAAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:stripped_mangrove_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTkAgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX21hbmdyb3ZlX2xvZwQJAG5hbWVfaGFzaLqIBo4hwA//AwoAbmV0d29ya19pZBA3AAAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:cherry_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQXAwAACAQAbmFtZRQAbWluZWNyYWZ0OmNoZXJyeV9sb2cECQBuYW1lX2hhc2hwFlaioppB1wMKAG5ldHdvcmtfaWSOMgAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:stripped_cherry_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQWAwAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2NoZXJyeV9sb2cECQBuYW1lX2hhc2i85H6G+WhXaAMKAG5ldHdvcmtfaWR0HAAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:crimson_stem", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTgAQAACAQAbmFtZRYAbWluZWNyYWZ0OmNyaW1zb25fc3RlbQQJAG5hbWVfaGFzaM0FzfL0UTKZAwoAbmV0d29ya19pZDopAAAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:stripped_crimson_stem", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTvAQAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2NyaW1zb25fc3RlbQQJAG5hbWVfaGFzaDlA6nood57EAwoAbmV0d29ya19pZIQvAAAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:warped_stem", + "block_state_b64": "CgAAAwgAYmxvY2tfaWThAQAACAQAbmFtZRUAbWluZWNyYWZ0OndhcnBlZF9zdGVtBAkAbmFtZV9oYXNon7cKfPZxdrUDCgBuZXR3b3JrX2lkoi0AAAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:stripped_warped_stem", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTwAQAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX3dhcnBlZF9zdGVtBAkAbmFtZV9oYXNoEw+y0dDPSd8DCgBuZXR3b3JrX2lkIjMAAAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTTAQAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWQuEwAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlAwBvYWsAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTTAQAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWQ0EwAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlAwBvYWsAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTTAQAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWQvEwAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlBgBzcHJ1Y2UAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTTAQAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWQ1EwAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlBgBzcHJ1Y2UAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTTAQAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWQwEwAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlBQBiaXJjaAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTTAQAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWQ2EwAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlBQBiaXJjaAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTTAQAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWQxEwAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlBgBqdW5nbGUAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTTAQAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWQ3EwAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlBgBqdW5nbGUAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTTAQAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWQyEwAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlBgBhY2FjaWEAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTTAQAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWQ4EwAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlBgBhY2FjaWEAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTTAQAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWQzEwAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlCABkYXJrX29hawADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTTAQAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWQ5EwAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlCABkYXJrX29hawADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:mangrove_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTwAgAACAQAbmFtZRcAbWluZWNyYWZ0Om1hbmdyb3ZlX3dvb2QECQBuYW1lX2hhc2iXVxG0JG2fVAMKAG5ldHdvcmtfaWQlGwAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:stripped_mangrove_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTxAgAACAQAbmFtZSAAbWluZWNyYWZ0OnN0cmlwcGVkX21hbmdyb3ZlX3dvb2QECQBuYW1lX2hhc2h7CkbaBF7/WAMKAG5ldHdvcmtfaWRyGwAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:cherry_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQhAwAACAQAbmFtZRUAbWluZWNyYWZ0OmNoZXJyeV93b29kBAkAbmFtZV9oYXNoAW8srlmpBM8DCgBuZXR3b3JrX2lkWjAAAAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AQwAc3RyaXBwZWRfYml0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:stripped_cherry_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQgAwAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX2NoZXJyeV93b29kBAkAbmFtZV9oYXNo/e7KXv+CB38DCgBuZXR3b3JrX2lktiEAAAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:crimson_hyphae", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQqAgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25faHlwaGFlBAkAbmFtZV9oYXNouRmKmfSqEWADCgBuZXR3b3JrX2lk2xsAAAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:stripped_crimson_hyphae", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQrAgAACAQAbmFtZSEAbWluZWNyYWZ0OnN0cmlwcGVkX2NyaW1zb25faHlwaGFlBAkAbmFtZV9oYXNoFffwmABq4LUDCgBuZXR3b3JrX2lkpi0AAAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:warped_hyphae", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQpAgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9oeXBoYWUECQBuYW1lX2hhc2hn8plQUr6pmQMKAG5ldHdvcmtfaWRCKQAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:stripped_warped_hyphae", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAgAACAQAbmFtZSAAbWluZWNyYWZ0OnN0cmlwcGVkX3dhcnBlZF9oeXBoYWUECQBuYW1lX2hhc2irKq+HYPSgjQMKAG5ldHdvcmtfaWSzJAAACgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:bamboo_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQOAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJhbWJvb19ibG9jawQJAG5hbWVfaGFzaAbDeur6stIBAwoAbmV0d29ya19pZD8AAAAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:stripped_bamboo_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQPAwAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2JhbWJvb19ibG9jawQJAG5hbWVfaGFzaJpwytpZOZM9AwoAbmV0d29ya19pZF4XAAAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQSAAAACAQAbmFtZRAAbWluZWNyYWZ0OmxlYXZlcwQJAG5hbWVfaGFzaACPIsusW0mnAwoAbmV0d29ya19pZPUrAAAKBgBzdGF0ZXMIDQBvbGRfbGVhZl90eXBlAwBvYWsBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQSAAAACAQAbmFtZRAAbWluZWNyYWZ0OmxlYXZlcwQJAG5hbWVfaGFzaACPIsusW0mnAwoAbmV0d29ya19pZPYrAAAKBgBzdGF0ZXMIDQBvbGRfbGVhZl90eXBlBgBzcHJ1Y2UBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQSAAAACAQAbmFtZRAAbWluZWNyYWZ0OmxlYXZlcwQJAG5hbWVfaGFzaACPIsusW0mnAwoAbmV0d29ya19pZPcrAAAKBgBzdGF0ZXMIDQBvbGRfbGVhZl90eXBlBQBiaXJjaAEOAHBlcnNpc3RlbnRfYml0AAEKAHVwZGF0ZV9iaXQAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQSAAAACAQAbmFtZRAAbWluZWNyYWZ0OmxlYXZlcwQJAG5hbWVfaGFzaACPIsusW0mnAwoAbmV0d29ya19pZPgrAAAKBgBzdGF0ZXMIDQBvbGRfbGVhZl90eXBlBgBqdW5nbGUBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:leaves2", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAAAACAQAbmFtZREAbWluZWNyYWZ0OmxlYXZlczIECQBuYW1lX2hhc2gy/bgrncY1ZAMKAG5ldHdvcmtfaWQdHAAACgYAc3RhdGVzCA0AbmV3X2xlYWZfdHlwZQYAYWNhY2lhAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:leaves2", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAAAACAQAbmFtZREAbWluZWNyYWZ0OmxlYXZlczIECQBuYW1lX2hhc2gy/bgrncY1ZAMKAG5ldHdvcmtfaWQeHAAACgYAc3RhdGVzCA0AbmV3X2xlYWZfdHlwZQgAZGFya19vYWsBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:mangrove_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTXAgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX2xlYXZlcwQJAG5hbWVfaGFzaKyI/dWvhEG8AwoAbmV0d29ya19pZGUuAAAKBgBzdGF0ZXMBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:cherry_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQjAwAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9sZWF2ZXMECQBuYW1lX2hhc2giTs9ChhYBlQMKAG5ldHdvcmtfaWQ2JwAACgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:azalea_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRDAgAACAQAbmFtZRcAbWluZWNyYWZ0OmF6YWxlYV9sZWF2ZXMECQBuYW1lX2hhc2iXFhD57wFS7AMKAG5ldHdvcmtfaWRiNAAACgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:azalea_leaves_flowered", + "block_state_b64": "CgAAAwgAYmxvY2tfaWREAgAACAQAbmFtZSAAbWluZWNyYWZ0OmF6YWxlYV9sZWF2ZXNfZmxvd2VyZWQECQBuYW1lX2hhc2gs8jxlS/pMrwMKAG5ldHdvcmtfaWTeLAAACgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAAAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWRjCAAACgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUDAG9hawADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAAAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWRkCAAACgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUGAHNwcnVjZQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAAAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWRlCAAACgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUFAGJpcmNoAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAAAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWRmCAAACgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUGAGp1bmdsZQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAAAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWRnCAAACgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUGAGFjYWNpYQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAAAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWRoCAAACgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUIAGRhcmtfb2FrAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:mangrove_propagule", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTZAgAACAQAbmFtZRwAbWluZWNyYWZ0Om1hbmdyb3ZlX3Byb3BhZ3VsZQQJAG5hbWVfaGFzaJGeox6hkfLFAwoAbmV0d29ya19pZKEvAAAKBgBzdGF0ZXMBBwBoYW5naW5nAAMPAHByb3BhZ3VsZV9zdGFnZQAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:cherry_sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQiAwAACAQAbmFtZRgAbWluZWNyYWZ0OmNoZXJyeV9zYXBsaW5nBAkAbmFtZV9oYXNoGrPpNMf1LtcDCgBuZXR3b3JrX2lkjDIAAAoGAHN0YXRlcwEHAGFnZV9iaXQAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:bee_nest", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTZAQAACAQAbmFtZRIAbWluZWNyYWZ0OmJlZV9uZXN0BAkAbmFtZV9oYXNo2R2WBxUHEZIDCgBuZXR3b3JrX2lkZCUAAAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAADCwBob25leV9sZXZlbAAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:wheat_seeds" + }, + { + "id": "minecraft:pumpkin_seeds" + }, + { + "id": "minecraft:melon_seeds" + }, + { + "id": "minecraft:beetroot_seeds" + }, + { + "id": "minecraft:torchflower_seeds" + }, + { + "id": "minecraft:pitcher_pod" + }, + { + "id": "minecraft:wheat" + }, + { + "id": "minecraft:beetroot" + }, + { + "id": "minecraft:potato" + }, + { + "id": "minecraft:poisonous_potato" + }, + { + "id": "minecraft:carrot" + }, + { + "id": "minecraft:golden_carrot" + }, + { + "id": "minecraft:apple" + }, + { + "id": "minecraft:golden_apple" + }, + { + "id": "minecraft:enchanted_golden_apple" + }, + { + "id": "minecraft:melon_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRnAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1lbG9uX2Jsb2NrBAkAbmFtZV9oYXNoXxSm0iYpAx8DCgBuZXR3b3JrX2lkeAQAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:melon_slice" + }, + { + "id": "minecraft:glistering_melon_slice" + }, + { + "id": "minecraft:sweet_berries" + }, + { + "id": "minecraft:glow_berries" + }, + { + "id": "minecraft:pumpkin", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRWAAAACAQAbmFtZREAbWluZWNyYWZ0OnB1bXBraW4ECQBuYW1lX2hhc2gc8A3jaSzWbgMKAG5ldHdvcmtfaWQNHQAACgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:carved_pumpkin", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSaAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNhcnZlZF9wdW1wa2luBAkAbmFtZV9oYXNoPu1T0MJuG90DCgBuZXR3b3JrX2lkDDMAAAoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:lit_pumpkin", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRbAAAACAQAbmFtZRUAbWluZWNyYWZ0OmxpdF9wdW1wa2luBAkAbmFtZV9oYXNo7gWtEm2uPL0DCgBuZXR3b3JrX2lkbC4AAAoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:honeycomb" + }, + { + "id": "minecraft:tallgrass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQfAAAACAQAbmFtZRMAbWluZWNyYWZ0OnRhbGxncmFzcwQJAG5hbWVfaGFzaC3PXpAXXYswAwoAbmV0d29ya19pZFUJAAAKBgBzdGF0ZXMIDwB0YWxsX2dyYXNzX3R5cGUEAGZlcm4AAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:double_plant", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAAAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZBYkAAAKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQQAZmVybgEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:tallgrass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQfAAAACAQAbmFtZRMAbWluZWNyYWZ0OnRhbGxncmFzcwQJAG5hbWVfaGFzaC3PXpAXXYswAwoAbmV0d29ya19pZFQJAAAKBgBzdGF0ZXMIDwB0YWxsX2dyYXNzX3R5cGUEAHRhbGwAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:double_plant", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAAAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZBUkAAAKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQUAZ3Jhc3MBDwB1cHBlcl9ibG9ja19iaXQAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:nether_sprouts" + }, + { + "id": "minecraft:fire_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRGAwAACAQAbmFtZRQAbWluZWNyYWZ0OmZpcmVfY29yYWwECQBuYW1lX2hhc2hOHyyECVQVJwMKAG5ldHdvcmtfaWTzBgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:brain_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWREAwAACAQAbmFtZRUAbWluZWNyYWZ0OmJyYWluX2NvcmFsBAkAbmFtZV9oYXNoRiWlLCwA2ycDCgBuZXR3b3JrX2lkmwcAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:bubble_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRFAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJ1YmJsZV9jb3JhbAQJAG5hbWVfaGFzaJz6rWnl+v2qAwoAbmV0d29ya19pZGcsAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:tube_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSCAQAACAQAbmFtZRQAbWluZWNyYWZ0OnR1YmVfY29yYWwECQBuYW1lX2hhc2iYa8oO/tgk7wMKAG5ldHdvcmtfaWShNAAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:horn_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRHAwAACAQAbmFtZRQAbWluZWNyYWZ0Omhvcm5fY29yYWwECQBuYW1lX2hhc2iZnRHjZbnLPgMKAG5ldHdvcmtfaWR0FwAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:dead_fire_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRLAwAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfZmlyZV9jb3JhbAQJAG5hbWVfaGFzaEPU6tFy/latAwoAbmV0d29ya19pZJ4sAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:dead_brain_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRJAwAACAQAbmFtZRoAbWluZWNyYWZ0OmRlYWRfYnJhaW5fY29yYWwECQBuYW1lX2hhc2j5L6QJCISvzwMKAG5ldHdvcmtfaWQzMgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:dead_bubble_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRKAwAACAQAbmFtZRsAbWluZWNyYWZ0OmRlYWRfYnViYmxlX2NvcmFsBAkAbmFtZV9oYXNoSTOZ/8wpeNYDCgBuZXR3b3JrX2lkizIAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:dead_tube_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRIAwAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfdHViZV9jb3JhbAQJAG5hbWVfaGFzaJGjNWhlaIJeAwoAbmV0d29ya19pZLkbAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:dead_horn_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRMAwAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfaG9ybl9jb3JhbAQJAG5hbWVfaGFzaJBkz3qt+g2cAwoAbmV0d29ya19pZHopAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAQAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZEkdAAAKBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgMAcmVkAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAQAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZEcdAAAKBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgQAcGluawMTAGNvcmFsX2Zhbl9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAQAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZEgdAAAKBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgYAcHVycGxlAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAQAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZEYdAAAKBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgQAYmx1ZQMTAGNvcmFsX2Zhbl9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAQAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZEodAAAKBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgYAeWVsbG93AxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:coral_fan_dead", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkTAAAAAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yAwByZWQDEwBjb3JhbF9mYW5fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:coral_fan_dead", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkSgAAAAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABwaW5rAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:coral_fan_dead", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkSwAAAAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgBwdXJwbGUDEwBjb3JhbF9mYW5fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:coral_fan_dead", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkSQAAAAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABibHVlAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:coral_fan_dead", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkTQAAAAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgB5ZWxsb3cDEwBjb3JhbF9mYW5fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:crimson_roots", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTeAQAACAQAbmFtZRcAbWluZWNyYWZ0OmNyaW1zb25fcm9vdHMECQBuYW1lX2hhc2j1fWgQLViv5QMKAG5ldHdvcmtfaWTYMwAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:warped_roots", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTfAQAACAQAbmFtZRYAbWluZWNyYWZ0OndhcnBlZF9yb290cwQJAG5hbWVfaGFzaBc3WvbJOLlkAwoAbmV0d29ya19pZCgcAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:yellow_flower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQlAAAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19mbG93ZXIECQBuYW1lX2hhc2jWbU1pF0OUGAMKAG5ldHdvcmtfaWQVBAAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWR3FwAACgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUFAHBvcHB5AAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWR4FwAACgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUGAG9yY2hpZAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWR5FwAACgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUGAGFsbGl1bQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWR6FwAACgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUJAGhvdXN0b25pYQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWR7FwAACgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUJAHR1bGlwX3JlZAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWR8FwAACgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUMAHR1bGlwX29yYW5nZQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWR9FwAACgYAc3RhdGVzCAsAZmxvd2VyX3R5cGULAHR1bGlwX3doaXRlAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWR+FwAACgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUKAHR1bGlwX3BpbmsAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWR/FwAACgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUFAG94ZXllAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWSAFwAACgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUKAGNvcm5mbG93ZXIAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWSBFwAACgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUSAGxpbHlfb2ZfdGhlX3ZhbGxleQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:double_plant", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAAAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZBMkAAAKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQkAc3VuZmxvd2VyAQ8AdXBwZXJfYmxvY2tfYml0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:double_plant", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAAAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZBQkAAAKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQcAc3lyaW5nYQEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:double_plant", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAAAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZBckAAAKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQQAcm9zZQEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:double_plant", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAAAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZBgkAAAKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQcAcGFlb25pYQEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:pitcher_plant", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAwAACAQAbmFtZRcAbWluZWNyYWZ0OnBpdGNoZXJfcGxhbnQECQBuYW1lX2hhc2hRJHzsbDH+SQMKAG5ldHdvcmtfaWQPGAAACgYAc3RhdGVzAQ8AdXBwZXJfYmxvY2tfYml0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:pink_petals", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQkAwAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfcGV0YWxzBAkAbmFtZV9oYXNo6DQwN9SwV3QDCgBuZXR3b3JrX2lkbh0AAAoGAHN0YXRlcwMGAGdyb3d0aAAAAAAIHABtaW5lY3JhZnQ6Y2FyZGluYWxfZGlyZWN0aW9uBQBzb3V0aAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:wither_rose", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTXAQAACAQAbmFtZRUAbWluZWNyYWZ0OndpdGhlcl9yb3NlBAkAbmFtZV9oYXNoaSKxl3I516gDCgBuZXR3b3JrX2lkQSwAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:torchflower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ3AwAACAQAbmFtZRUAbWluZWNyYWZ0OnRvcmNoZmxvd2VyBAkAbmFtZV9oYXNoL+mHtElwbqQDCgBuZXR3b3JrX2lkxisAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:white_dye" + }, + { + "id": "minecraft:light_gray_dye" + }, + { + "id": "minecraft:gray_dye" + }, + { + "id": "minecraft:black_dye" + }, + { + "id": "minecraft:brown_dye" + }, + { + "id": "minecraft:red_dye" + }, + { + "id": "minecraft:orange_dye" + }, + { + "id": "minecraft:yellow_dye" + }, + { + "id": "minecraft:lime_dye" + }, + { + "id": "minecraft:green_dye" + }, + { + "id": "minecraft:cyan_dye" + }, + { + "id": "minecraft:light_blue_dye" + }, + { + "id": "minecraft:blue_dye" + }, + { + "id": "minecraft:purple_dye" + }, + { + "id": "minecraft:magenta_dye" + }, + { + "id": "minecraft:pink_dye" + }, + { + "id": "minecraft:ink_sac" + }, + { + "id": "minecraft:glow_ink_sac" + }, + { + "id": "minecraft:cocoa_beans" + }, + { + "id": "minecraft:lapis_lazuli" + }, + { + "id": "minecraft:bone_meal" + }, + { + "id": "minecraft:vine", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRqAAAACAQAbmFtZQ4AbWluZWNyYWZ0OnZpbmUECQBuYW1lX2hhc2j0Sj8/XeXOLAMKAG5ldHdvcmtfaWQhCQAACgYAc3RhdGVzAxMAdmluZV9kaXJlY3Rpb25fYml0cwAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:weeping_vines", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTmAQAACAQAbmFtZRcAbWluZWNyYWZ0OndlZXBpbmdfdmluZXMECQBuYW1lX2hhc2jrLgLHkQygiwMKAG5ldHdvcmtfaWRPJAAACgYAc3RhdGVzAxEAd2VlcGluZ192aW5lc19hZ2UAAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:twisting_vines", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQeAgAACAQAbmFtZRgAbWluZWNyYWZ0OnR3aXN0aW5nX3ZpbmVzBAkAbmFtZV9oYXNoDYR5QgVUQJADCgBuZXR3b3JrX2lkIiUAAAoGAHN0YXRlcwMSAHR3aXN0aW5nX3ZpbmVzX2FnZQAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:waterlily", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRvAAAACAQAbmFtZRMAbWluZWNyYWZ0OndhdGVybGlseQQJAG5hbWVfaGFzaEHgC4c1SXg0AwoAbmV0d29ya19pZCIKAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:seagrass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSBAQAACAQAbmFtZRIAbWluZWNyYWZ0OnNlYWdyYXNzBAkAbmFtZV9oYXNoHSBFtoHdWxIDCgBuZXR3b3JrX2lkogIAAAoGAHN0YXRlcwgOAHNlYV9ncmFzc190eXBlBwBkZWZhdWx0AAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:kelp" + }, + { + "id": "minecraft:deadbush", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQgAAAACAQAbmFtZRIAbWluZWNyYWZ0OmRlYWRidXNoBAkAbmFtZV9oYXNoPFODe4IScnYDCgBuZXR3b3JrX2lkMh8AAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:bamboo", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSiAQAACAQAbmFtZRAAbWluZWNyYWZ0OmJhbWJvbwQJAG5hbWVfaGFzaBgpGmyzhedCAwoAbmV0d29ya19pZLwXAAAKBgBzdGF0ZXMBBwBhZ2VfYml0AAgQAGJhbWJvb19sZWFmX3NpemUJAG5vX2xlYXZlcwgWAGJhbWJvb19zdGFsa190aGlja25lc3MEAHRoaW4AAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:snow", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRQAAAACAQAbmFtZQ4AbWluZWNyYWZ0OnNub3cECQBuYW1lX2hhc2gVHr5XXdETWAMKAG5ldHdvcmtfaWRPGwAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:ice", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRPAAAACAQAbmFtZQ0AbWluZWNyYWZ0OmljZQQJAG5hbWVfaGFzaNF26f+uUT29AwoAbmV0d29ya19pZHAuAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:packed_ice", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSuAAAACAQAbmFtZRQAbWluZWNyYWZ0OnBhY2tlZF9pY2UECQBuYW1lX2hhc2hk4bu123ZrFgMKAG5ldHdvcmtfaWThAgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:blue_ice", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQKAQAACAQAbmFtZRIAbWluZWNyYWZ0OmJsdWVfaWNlBAkAbmFtZV9oYXNo+EKxYgFhKcgDCgBuZXR3b3JrX2lk2C8AAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:snow_layer", + "block_state_b64": "CgAAAwgAYmxvY2tfaWROAAAACAQAbmFtZRQAbWluZWNyYWZ0OnNub3dfbGF5ZXIECQBuYW1lX2hhc2hXka6atMYUCQMKAG5ldHdvcmtfaWQ9AgAACgYAc3RhdGVzAQsAY292ZXJlZF9iaXQAAwYAaGVpZ2h0AAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:pointed_dripstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQzAgAACAQAbmFtZRsAbWluZWNyYWZ0OnBvaW50ZWRfZHJpcHN0b25lBAkAbmFtZV9oYXNoJMISzmHQgt8DCgBuZXR3b3JrX2lkMjMAAAoGAHN0YXRlcwgTAGRyaXBzdG9uZV90aGlja25lc3MDAHRpcAEHAGhhbmdpbmcBAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:dripstone_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ8AgAACAQAbmFtZRkAbWluZWNyYWZ0OmRyaXBzdG9uZV9ibG9jawQJAG5hbWVfaGFzaIIXnEqY77YsAwoAbmV0d29ya19pZCAJAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:moss_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWROAgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vc3NfY2FycGV0BAkAbmFtZV9oYXNo/NEDxRPTshYDCgBuZXR3b3JrX2lk5QIAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:moss_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ/AgAACAQAbmFtZRQAbWluZWNyYWZ0Om1vc3NfYmxvY2sECQBuYW1lX2hhc2iovcsPUYX2tgMKAG5ldHdvcmtfaWTgLQAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:dirt_with_roots", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ9AgAACAQAbmFtZRkAbWluZWNyYWZ0OmRpcnRfd2l0aF9yb290cwQJAG5hbWVfaGFzaLCNDYPviDCIAwoAbmV0d29ya19pZNsjAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:hanging_roots", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ+AgAACAQAbmFtZRcAbWluZWNyYWZ0Omhhbmdpbmdfcm9vdHMECQBuYW1lX2hhc2jaXn+Y5UZpDAMKAG5ldHdvcmtfaWRwAgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:mangrove_roots", + "block_state_b64": "CgAAAwgAYmxvY2tfaWThAgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hbmdyb3ZlX3Jvb3RzBAkAbmFtZV9oYXNoa786PzQGZ6kDCgBuZXR3b3JrX2lkSywAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:muddy_mangrove_roots", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTiAgAACAQAbmFtZR4AbWluZWNyYWZ0Om11ZGR5X21hbmdyb3ZlX3Jvb3RzBAkAbmFtZV9oYXNo9YApdHpo1RkDCgBuZXR3b3JrX2lkQgQAAAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:big_dripleaf", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRCAgAACAQAbmFtZRYAbWluZWNyYWZ0OmJpZ19kcmlwbGVhZgQJAG5hbWVfaGFzaGBEhXjo6qSdAwoAbmV0d29ya19pZN4pAAAKBgBzdGF0ZXMBEQBiaWdfZHJpcGxlYWZfaGVhZAEIEQBiaWdfZHJpcGxlYWZfdGlsdAQAbm9uZQgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:small_dripleaf_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRPAgAACAQAbmFtZR4AbWluZWNyYWZ0OnNtYWxsX2RyaXBsZWFmX2Jsb2NrBAkAbmFtZV9oYXNojxRAgXP9uWADCgBuZXR3b3JrX2lk9RsAAAoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24EAGVhc3QBDwB1cHBlcl9ibG9ja19iaXQBAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:spore_blossom", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRAAgAACAQAbmFtZRcAbWluZWNyYWZ0OnNwb3JlX2Jsb3Nzb20ECQBuYW1lX2hhc2il3U72Gbco2gMKAG5ldHdvcmtfaWTNMgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:azalea", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRQAgAACAQAbmFtZRAAbWluZWNyYWZ0OmF6YWxlYQQJAG5hbWVfaGFzaNyUl+BW9JrBAwoAbmV0d29ya19pZEAvAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:flowering_azalea", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRRAgAACAQAbmFtZRoAbWluZWNyYWZ0OmZsb3dlcmluZ19hemFsZWEECQBuYW1lX2hhc2ie9r33wz8kiwMKAG5ldHdvcmtfaWRMJAAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:glow_lichen", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSaAgAACAQAbmFtZRUAbWluZWNyYWZ0Omdsb3dfbGljaGVuBAkAbmFtZV9oYXNobyPUrIYlo44DCgBuZXR3b3JrX2lkGyUAAAoGAHN0YXRlcwMZAG11bHRpX2ZhY2VfZGlyZWN0aW9uX2JpdHM/AAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:amethyst_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRGAgAACAQAbmFtZRgAbWluZWNyYWZ0OmFtZXRoeXN0X2Jsb2NrBAkAbmFtZV9oYXNob+JK1iiAthcDCgBuZXR3b3JrX2lkCQMAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:budding_amethyst", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRHAgAACAQAbmFtZRoAbWluZWNyYWZ0OmJ1ZGRpbmdfYW1ldGh5c3QECQBuYW1lX2hhc2gJvAwfI14fxgMKAG5ldHdvcmtfaWS7LwAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:amethyst_cluster", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRIAgAACAQAbmFtZRoAbWluZWNyYWZ0OmFtZXRoeXN0X2NsdXN0ZXIECQBuYW1lX2hhc2jK82S88Jgm8wMKAG5ldHdvcmtfaWQgNQAACgYAc3RhdGVzCBQAbWluZWNyYWZ0OmJsb2NrX2ZhY2UCAHVwAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:large_amethyst_bud", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRJAgAACAQAbmFtZRwAbWluZWNyYWZ0OmxhcmdlX2FtZXRoeXN0X2J1ZAQJAG5hbWVfaGFzaAHhdpWD+sd5AwoAbmV0d29ya19pZGUfAAAKBgBzdGF0ZXMIFABtaW5lY3JhZnQ6YmxvY2tfZmFjZQIAdXAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:medium_amethyst_bud", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRKAgAACAQAbmFtZR0AbWluZWNyYWZ0Om1lZGl1bV9hbWV0aHlzdF9idWQECQBuYW1lX2hhc2g5lBGtC0DzZQMKAG5ldHdvcmtfaWQ1HAAACgYAc3RhdGVzCBQAbWluZWNyYWZ0OmJsb2NrX2ZhY2UCAHVwAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:small_amethyst_bud", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRLAgAACAQAbmFtZRwAbWluZWNyYWZ0OnNtYWxsX2FtZXRoeXN0X2J1ZAQJAG5hbWVfaGFzaEnb4+q9PO4YAwoAbmV0d29ya19pZBkEAAAKBgBzdGF0ZXMIFABtaW5lY3JhZnQ6YmxvY2tfZmFjZQIAdXAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:tuff", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRMAgAACAQAbmFtZQ4AbWluZWNyYWZ0OnR1ZmYECQBuYW1lX2hhc2h1Rwc1XYsBGwMKAG5ldHdvcmtfaWRGBAAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:calcite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRFAgAACAQAbmFtZREAbWluZWNyYWZ0OmNhbGNpdGUECQBuYW1lX2hhc2ixKLu8ZIdzDQMKAG5ldHdvcmtfaWR6AgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:chicken" + }, + { + "id": "minecraft:porkchop" + }, + { + "id": "minecraft:beef" + }, + { + "id": "minecraft:mutton" + }, + { + "id": "minecraft:rabbit" + }, + { + "id": "minecraft:cod" + }, + { + "id": "minecraft:salmon" + }, + { + "id": "minecraft:tropical_fish" + }, + { + "id": "minecraft:pufferfish" + }, + { + "id": "minecraft:brown_mushroom", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQnAAAACAQAbmFtZRgAbWluZWNyYWZ0OmJyb3duX211c2hyb29tBAkAbmFtZV9oYXNonYw/FO78WDoDCgBuZXR3b3JrX2lkGRcAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:red_mushroom", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQoAAAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZF9tdXNocm9vbQQJAG5hbWVfaGFzaPpzJua7669xAwoAbmV0d29ya19pZCgdAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:crimson_fungus", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTjAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fZnVuZ3VzBAkAbmFtZV9oYXNolIcCUuFM2u0DCgBuZXR3b3JrX2lklDQAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:warped_fungus", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTkAQAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9mdW5ndXMECQBuYW1lX2hhc2gq8bSnRVTAFgMKAG5ldHdvcmtfaWTmAgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:brown_mushroom_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAAAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lk/zIAAAoGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cw4AAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:red_mushroom_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRkAAAACAQAbmFtZRwAbWluZWNyYWZ0OnJlZF9tdXNocm9vbV9ibG9jawQJAG5hbWVfaGFzaJTTyJbth9M9AwoAbmV0d29ya19pZG8XAAAKBgBzdGF0ZXMDEgBodWdlX211c2hyb29tX2JpdHMOAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:brown_mushroom_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAAAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkADMAAAoGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cw8AAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:brown_mushroom_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAAAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lk8TIAAAoGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cwAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:egg" + }, + { + "id": "minecraft:sugar_cane" + }, + { + "id": "minecraft:sugar" + }, + { + "id": "minecraft:rotten_flesh" + }, + { + "id": "minecraft:bone" + }, + { + "id": "minecraft:web", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQeAAAACAQAbmFtZQ0AbWluZWNyYWZ0OndlYgQJAG5hbWVfaGFzaA4GKQCvG4i9AwoAbmV0d29ya19pZIkuAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:spider_eye" + }, + { + "id": "minecraft:mob_spawner", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ0AAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vYl9zcGF3bmVyBAkAbmFtZV9oYXNoNwGrCV/Fkh8DCgBuZXR3b3JrX2lkggQAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:monster_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkEhsAAAoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGUFAHN0b25lAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:monster_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkExsAAAoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGULAGNvYmJsZXN0b25lAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:monster_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkFBsAAAoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGULAHN0b25lX2JyaWNrAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:monster_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkFRsAAAoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGURAG1vc3N5X3N0b25lX2JyaWNrAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:monster_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkFhsAAAoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGUTAGNyYWNrZWRfc3RvbmVfYnJpY2sAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:monster_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkFxsAAAoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGUUAGNoaXNlbGVkX3N0b25lX2JyaWNrAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:infested_deepslate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTFAgAACAQAbmFtZRwAbWluZWNyYWZ0OmluZmVzdGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaICF2VYccxF1AwoAbmV0d29ya19pZA4fAAAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:dragon_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR6AAAACAQAbmFtZRQAbWluZWNyYWZ0OmRyYWdvbl9lZ2cECQBuYW1lX2hhc2inMzXrV+/e1wMKAG5ldHdvcmtfaWSjMgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:turtle_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSeAQAACAQAbmFtZRQAbWluZWNyYWZ0OnR1cnRsZV9lZ2cECQBuYW1lX2hhc2iwSRcxOJIJ9gMKAG5ldHdvcmtfaWTfNQAACgYAc3RhdGVzCA0AY3JhY2tlZF9zdGF0ZQkAbm9fY3JhY2tzCBAAdHVydGxlX2VnZ19jb3VudAcAb25lX2VnZwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:sniffer_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRTAwAACAQAbmFtZRUAbWluZWNyYWZ0OnNuaWZmZXJfZWdnBAkAbmFtZV9oYXNoY1lozc8lPcYDCgBuZXR3b3JrX2lkvC8AAAoGAHN0YXRlcwgNAGNyYWNrZWRfc3RhdGUJAG5vX2NyYWNrcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:frog_spawn", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTTAgAACAQAbmFtZRQAbWluZWNyYWZ0OmZyb2dfc3Bhd24ECQBuYW1lX2hhc2iWmd7idp3ZZwMKAG5ldHdvcmtfaWRSHAAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:pearlescent_froglight", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTUAgAACAQAbmFtZR8AbWluZWNyYWZ0OnBlYXJsZXNjZW50X2Zyb2dsaWdodAQJAG5hbWVfaGFzaKkcFRyycYGyAwoAbmV0d29ya19pZGEtAAAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:verdant_froglight", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTVAgAACAQAbmFtZRsAbWluZWNyYWZ0OnZlcmRhbnRfZnJvZ2xpZ2h0BAkAbmFtZV9oYXNoA+eXuTBohrQDCgBuZXR3b3JrX2lknC0AAAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:ochre_froglight", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTWAgAACAQAbmFtZRkAbWluZWNyYWZ0Om9jaHJlX2Zyb2dsaWdodAQJAG5hbWVfaGFzaMY59kjPe+c3AwoAbmV0d29ya19pZNIUAAAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:chicken_spawn_egg" + }, + { + "id": "minecraft:bee_spawn_egg" + }, + { + "id": "minecraft:cow_spawn_egg" + }, + { + "id": "minecraft:pig_spawn_egg" + }, + { + "id": "minecraft:sheep_spawn_egg" + }, + { + "id": "minecraft:wolf_spawn_egg" + }, + { + "id": "minecraft:polar_bear_spawn_egg" + }, + { + "id": "minecraft:ocelot_spawn_egg" + }, + { + "id": "minecraft:cat_spawn_egg" + }, + { + "id": "minecraft:mooshroom_spawn_egg" + }, + { + "id": "minecraft:bat_spawn_egg" + }, + { + "id": "minecraft:parrot_spawn_egg" + }, + { + "id": "minecraft:rabbit_spawn_egg" + }, + { + "id": "minecraft:llama_spawn_egg" + }, + { + "id": "minecraft:horse_spawn_egg" + }, + { + "id": "minecraft:donkey_spawn_egg" + }, + { + "id": "minecraft:mule_spawn_egg" + }, + { + "id": "minecraft:skeleton_horse_spawn_egg" + }, + { + "id": "minecraft:zombie_horse_spawn_egg" + }, + { + "id": "minecraft:tropical_fish_spawn_egg" + }, + { + "id": "minecraft:cod_spawn_egg" + }, + { + "id": "minecraft:pufferfish_spawn_egg" + }, + { + "id": "minecraft:salmon_spawn_egg" + }, + { + "id": "minecraft:dolphin_spawn_egg" + }, + { + "id": "minecraft:turtle_spawn_egg" + }, + { + "id": "minecraft:panda_spawn_egg" + }, + { + "id": "minecraft:fox_spawn_egg" + }, + { + "id": "minecraft:creeper_spawn_egg" + }, + { + "id": "minecraft:enderman_spawn_egg" + }, + { + "id": "minecraft:silverfish_spawn_egg" + }, + { + "id": "minecraft:skeleton_spawn_egg" + }, + { + "id": "minecraft:wither_skeleton_spawn_egg" + }, + { + "id": "minecraft:stray_spawn_egg" + }, + { + "id": "minecraft:slime_spawn_egg" + }, + { + "id": "minecraft:spider_spawn_egg" + }, + { + "id": "minecraft:zombie_spawn_egg" + }, + { + "id": "minecraft:zombie_pigman_spawn_egg" + }, + { + "id": "minecraft:husk_spawn_egg" + }, + { + "id": "minecraft:drowned_spawn_egg" + }, + { + "id": "minecraft:squid_spawn_egg" + }, + { + "id": "minecraft:glow_squid_spawn_egg" + }, + { + "id": "minecraft:cave_spider_spawn_egg" + }, + { + "id": "minecraft:witch_spawn_egg" + }, + { + "id": "minecraft:guardian_spawn_egg" + }, + { + "id": "minecraft:elder_guardian_spawn_egg" + }, + { + "id": "minecraft:endermite_spawn_egg" + }, + { + "id": "minecraft:magma_cube_spawn_egg" + }, + { + "id": "minecraft:strider_spawn_egg" + }, + { + "id": "minecraft:hoglin_spawn_egg" + }, + { + "id": "minecraft:piglin_spawn_egg" + }, + { + "id": "minecraft:zoglin_spawn_egg" + }, + { + "id": "minecraft:piglin_brute_spawn_egg" + }, + { + "id": "minecraft:goat_spawn_egg" + }, + { + "id": "minecraft:axolotl_spawn_egg" + }, + { + "id": "minecraft:warden_spawn_egg" + }, + { + "id": "minecraft:allay_spawn_egg" + }, + { + "id": "minecraft:frog_spawn_egg" + }, + { + "id": "minecraft:tadpole_spawn_egg" + }, + { + "id": "minecraft:trader_llama_spawn_egg" + }, + { + "id": "minecraft:camel_spawn_egg" + }, + { + "id": "minecraft:ghast_spawn_egg" + }, + { + "id": "minecraft:blaze_spawn_egg" + }, + { + "id": "minecraft:shulker_spawn_egg" + }, + { + "id": "minecraft:vindicator_spawn_egg" + }, + { + "id": "minecraft:evoker_spawn_egg" + }, + { + "id": "minecraft:vex_spawn_egg" + }, + { + "id": "minecraft:villager_spawn_egg" + }, + { + "id": "minecraft:wandering_trader_spawn_egg" + }, + { + "id": "minecraft:zombie_villager_spawn_egg" + }, + { + "id": "minecraft:phantom_spawn_egg" + }, + { + "id": "minecraft:pillager_spawn_egg" + }, + { + "id": "minecraft:ravager_spawn_egg" + }, + { + "id": "minecraft:iron_golem_spawn_egg" + }, + { + "id": "minecraft:snow_golem_spawn_egg" + }, + { + "id": "minecraft:sniffer_spawn_egg" + }, + { + "id": "minecraft:obsidian", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQxAAAACAQAbmFtZRIAbWluZWNyYWZ0Om9ic2lkaWFuBAkAbmFtZV9oYXNoiz4qrb8QjyEDCgBuZXR3b3JrX2lknwQAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:crying_obsidian", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQgAgAACAQAbmFtZRkAbWluZWNyYWZ0OmNyeWluZ19vYnNpZGlhbgQJAG5hbWVfaGFzaKT0JlA7Z1K+AwoAbmV0d29ya19pZJQuAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:bedrock", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQHAAAACAQAbmFtZREAbWluZWNyYWZ0OmJlZHJvY2sECQBuYW1lX2hhc2hWfFrh4LVtxwMKAG5ldHdvcmtfaWTOLwAACgYAc3RhdGVzAQ4AaW5maW5pYnVybl9iaXQAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:soul_sand", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRYAAAACAQAbmFtZRMAbWluZWNyYWZ0OnNvdWxfc2FuZAQJAG5hbWVfaGFzaMaf+bccu+KTAwoAbmV0d29ya19pZLIlAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:magma", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTVAAAACAQAbmFtZQ8AbWluZWNyYWZ0Om1hZ21hBAkAbmFtZV9oYXNoqyTjKaIsWfYDCgBuZXR3b3JrX2lk6zUAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:nether_wart" + }, + { + "id": "minecraft:end_stone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR5AAAACAQAbmFtZRMAbWluZWNyYWZ0OmVuZF9zdG9uZQQJAG5hbWVfaGFzaH1J9jA39GJNAwoAbmV0d29ya19pZNkZAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:chorus_flower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTIAAAACAQAbmFtZRcAbWluZWNyYWZ0OmNob3J1c19mbG93ZXIECQBuYW1lX2hhc2iMpSodli5uawMKAG5ldHdvcmtfaWTbHAAACgYAc3RhdGVzAwMAYWdlAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:chorus_plant", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTwAAAACAQAbmFtZRYAbWluZWNyYWZ0OmNob3J1c19wbGFudAQJAG5hbWVfaGFzaJhSrmNGKwaMAwoAbmV0d29ya19pZGkkAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:chorus_fruit" + }, + { + "id": "minecraft:popped_chorus_fruit" + }, + { + "id": "minecraft:sponge", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQTAAAACAQAbmFtZRAAbWluZWNyYWZ0OnNwb25nZQQJAG5hbWVfaGFzaLrd2ScYRDMiAwoAbmV0d29ya19pZFkFAAAKBgBzdGF0ZXMICwBzcG9uZ2VfdHlwZQMAZHJ5AAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:sponge", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQTAAAACAQAbmFtZRAAbWluZWNyYWZ0OnNwb25nZQQJAG5hbWVfaGFzaLrd2ScYRDMiAwoAbmV0d29ya19pZFoFAAAKBgBzdGF0ZXMICwBzcG9uZ2VfdHlwZQMAd2V0AAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkMyMAAAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABibHVlAQgAZGVhZF9iaXQAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkNCMAAAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABwaW5rAQgAZGVhZF9iaXQAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkNSMAAAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgBwdXJwbGUBCABkZWFkX2JpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkNiMAAAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yAwByZWQBCABkZWFkX2JpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkNyMAAAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgB5ZWxsb3cBCABkZWFkX2JpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkOCMAAAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABibHVlAQgAZGVhZF9iaXQBAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkOSMAAAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABwaW5rAQgAZGVhZF9iaXQBAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkOiMAAAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgBwdXJwbGUBCABkZWFkX2JpdAEAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkOyMAAAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yAwByZWQBCABkZWFkX2JpdAEAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkPCMAAAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgB5ZWxsb3cBCABkZWFkX2JpdAEAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:sculk", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAgAACAQAbmFtZQ8AbWluZWNyYWZ0OnNjdWxrBAkAbmFtZV9oYXNo2Lq7T5yQF8kDCgBuZXR3b3JrX2lk4y8AAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:sculk_vein", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTKAgAACAQAbmFtZRQAbWluZWNyYWZ0OnNjdWxrX3ZlaW4ECQBuYW1lX2hhc2gJUdhVooV4zwMKAG5ldHdvcmtfaWTzMQAACgYAc3RhdGVzAxkAbXVsdGlfZmFjZV9kaXJlY3Rpb25fYml0cwAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:sculk_catalyst", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTLAgAACAQAbmFtZRgAbWluZWNyYWZ0OnNjdWxrX2NhdGFseXN0BAkAbmFtZV9oYXNo+gCpbrCHST4DCgBuZXR3b3JrX2lkcRcAAAoGAHN0YXRlcwEFAGJsb29tAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:sculk_shrieker", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTMAgAACAQAbmFtZRgAbWluZWNyYWZ0OnNjdWxrX3Nocmlla2VyBAkAbmFtZV9oYXNo5OXtyObniQ4DCgBuZXR3b3JrX2lkgwIAAAoGAHN0YXRlcwEGAGFjdGl2ZQABCgBjYW5fc3VtbW9uAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:sculk_sensor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQyAgAACAQAbmFtZRYAbWluZWNyYWZ0OnNjdWxrX3NlbnNvcgQJAG5hbWVfaGFzaCkmHreeTgNnAwoAbmV0d29ya19pZEMcAAAKBgBzdGF0ZXMDEgBzY3Vsa19zZW5zb3JfcGhhc2UAAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:calibrated_sculk_sensor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRDAwAACAQAbmFtZSEAbWluZWNyYWZ0OmNhbGlicmF0ZWRfc2N1bGtfc2Vuc29yBAkAbmFtZV9oYXNoffAcXXN/iJUDCgBuZXR3b3JrX2lkTCcAAAoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAxIAc2N1bGtfc2Vuc29yX3BoYXNlAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:reinforced_deepslate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTRAgAACAQAbmFtZR4AbWluZWNyYWZ0OnJlaW5mb3JjZWRfZGVlcHNsYXRlBAkAbmFtZV9oYXNoldDmj91EapQDCgBuZXR3b3JrX2lkNCcAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:leather_helmet" + }, + { + "id": "minecraft:chainmail_helmet" + }, + { + "id": "minecraft:iron_helmet" + }, + { + "id": "minecraft:golden_helmet" + }, + { + "id": "minecraft:diamond_helmet" + }, + { + "id": "minecraft:netherite_helmet" + }, + { + "id": "minecraft:leather_chestplate" + }, + { + "id": "minecraft:chainmail_chestplate" + }, + { + "id": "minecraft:iron_chestplate" + }, + { + "id": "minecraft:golden_chestplate" + }, + { + "id": "minecraft:diamond_chestplate" + }, + { + "id": "minecraft:netherite_chestplate" + }, + { + "id": "minecraft:leather_leggings" + }, + { + "id": "minecraft:chainmail_leggings" + }, + { + "id": "minecraft:iron_leggings" + }, + { + "id": "minecraft:golden_leggings" + }, + { + "id": "minecraft:diamond_leggings" + }, + { + "id": "minecraft:netherite_leggings" + }, + { + "id": "minecraft:leather_boots" + }, + { + "id": "minecraft:chainmail_boots" + }, + { + "id": "minecraft:iron_boots" + }, + { + "id": "minecraft:golden_boots" + }, + { + "id": "minecraft:diamond_boots" + }, + { + "id": "minecraft:netherite_boots" + }, + { + "id": "minecraft:wooden_sword" + }, + { + "id": "minecraft:stone_sword" + }, + { + "id": "minecraft:iron_sword" + }, + { + "id": "minecraft:golden_sword" + }, + { + "id": "minecraft:diamond_sword" + }, + { + "id": "minecraft:netherite_sword" + }, + { + "id": "minecraft:wooden_axe" + }, + { + "id": "minecraft:stone_axe" + }, + { + "id": "minecraft:iron_axe" + }, + { + "id": "minecraft:golden_axe" + }, + { + "id": "minecraft:diamond_axe" + }, + { + "id": "minecraft:netherite_axe" + }, + { + "id": "minecraft:wooden_pickaxe" + }, + { + "id": "minecraft:stone_pickaxe" + }, + { + "id": "minecraft:iron_pickaxe" + }, + { + "id": "minecraft:golden_pickaxe" + }, + { + "id": "minecraft:diamond_pickaxe" + }, + { + "id": "minecraft:netherite_pickaxe" + }, + { + "id": "minecraft:wooden_shovel" + }, + { + "id": "minecraft:stone_shovel" + }, + { + "id": "minecraft:iron_shovel" + }, + { + "id": "minecraft:golden_shovel" + }, + { + "id": "minecraft:diamond_shovel" + }, + { + "id": "minecraft:netherite_shovel" + }, + { + "id": "minecraft:wooden_hoe" + }, + { + "id": "minecraft:stone_hoe" + }, + { + "id": "minecraft:iron_hoe" + }, + { + "id": "minecraft:golden_hoe" + }, + { + "id": "minecraft:diamond_hoe" + }, + { + "id": "minecraft:netherite_hoe" + }, + { + "id": "minecraft:bow" + }, + { + "id": "minecraft:crossbow" + }, + { + "id": "minecraft:arrow" + }, + { + "id": "minecraft:arrow", + "damage": 6 + }, + { + "id": "minecraft:arrow", + "damage": 7 + }, + { + "id": "minecraft:arrow", + "damage": 8 + }, + { + "id": "minecraft:arrow", + "damage": 9 + }, + { + "id": "minecraft:arrow", + "damage": 10 + }, + { + "id": "minecraft:arrow", + "damage": 11 + }, + { + "id": "minecraft:arrow", + "damage": 12 + }, + { + "id": "minecraft:arrow", + "damage": 13 + }, + { + "id": "minecraft:arrow", + "damage": 14 + }, + { + "id": "minecraft:arrow", + "damage": 15 + }, + { + "id": "minecraft:arrow", + "damage": 16 + }, + { + "id": "minecraft:arrow", + "damage": 17 + }, + { + "id": "minecraft:arrow", + "damage": 18 + }, + { + "id": "minecraft:arrow", + "damage": 19 + }, + { + "id": "minecraft:arrow", + "damage": 20 + }, + { + "id": "minecraft:arrow", + "damage": 21 + }, + { + "id": "minecraft:arrow", + "damage": 22 + }, + { + "id": "minecraft:arrow", + "damage": 23 + }, + { + "id": "minecraft:arrow", + "damage": 24 + }, + { + "id": "minecraft:arrow", + "damage": 25 + }, + { + "id": "minecraft:arrow", + "damage": 26 + }, + { + "id": "minecraft:arrow", + "damage": 27 + }, + { + "id": "minecraft:arrow", + "damage": 28 + }, + { + "id": "minecraft:arrow", + "damage": 29 + }, + { + "id": "minecraft:arrow", + "damage": 30 + }, + { + "id": "minecraft:arrow", + "damage": 31 + }, + { + "id": "minecraft:arrow", + "damage": 32 + }, + { + "id": "minecraft:arrow", + "damage": 33 + }, + { + "id": "minecraft:arrow", + "damage": 34 + }, + { + "id": "minecraft:arrow", + "damage": 35 + }, + { + "id": "minecraft:arrow", + "damage": 36 + }, + { + "id": "minecraft:arrow", + "damage": 37 + }, + { + "id": "minecraft:arrow", + "damage": 38 + }, + { + "id": "minecraft:arrow", + "damage": 39 + }, + { + "id": "minecraft:arrow", + "damage": 40 + }, + { + "id": "minecraft:arrow", + "damage": 41 + }, + { + "id": "minecraft:arrow", + "damage": 42 + }, + { + "id": "minecraft:arrow", + "damage": 43 + }, + { + "id": "minecraft:shield" + }, + { + "id": "minecraft:cooked_chicken" + }, + { + "id": "minecraft:cooked_porkchop" + }, + { + "id": "minecraft:cooked_beef" + }, + { + "id": "minecraft:cooked_mutton" + }, + { + "id": "minecraft:cooked_rabbit" + }, + { + "id": "minecraft:cooked_cod" + }, + { + "id": "minecraft:cooked_salmon" + }, + { + "id": "minecraft:bread" + }, + { + "id": "minecraft:mushroom_stew" + }, + { + "id": "minecraft:beetroot_soup" + }, + { + "id": "minecraft:rabbit_stew" + }, + { + "id": "minecraft:baked_potato" + }, + { + "id": "minecraft:cookie" + }, + { + "id": "minecraft:pumpkin_pie" + }, + { + "id": "minecraft:cake" + }, + { + "id": "minecraft:dried_kelp" + }, + { + "id": "minecraft:fishing_rod" + }, + { + "id": "minecraft:carrot_on_a_stick" + }, + { + "id": "minecraft:warped_fungus_on_a_stick" + }, + { + "id": "minecraft:snowball" + }, + { + "id": "minecraft:shears" + }, + { + "id": "minecraft:flint_and_steel" + }, + { + "id": "minecraft:lead" + }, + { + "id": "minecraft:clock" + }, + { + "id": "minecraft:compass" + }, + { + "id": "minecraft:recovery_compass" + }, + { + "id": "minecraft:goat_horn" + }, + { + "id": "minecraft:goat_horn", + "damage": 1 + }, + { + "id": "minecraft:goat_horn", + "damage": 2 + }, + { + "id": "minecraft:goat_horn", + "damage": 3 + }, + { + "id": "minecraft:goat_horn", + "damage": 4 + }, + { + "id": "minecraft:goat_horn", + "damage": 5 + }, + { + "id": "minecraft:goat_horn", + "damage": 6 + }, + { + "id": "minecraft:goat_horn", + "damage": 7 + }, + { + "id": "minecraft:empty_map" + }, + { + "id": "minecraft:empty_map", + "damage": 2 + }, + { + "id": "minecraft:saddle" + }, + { + "id": "minecraft:leather_horse_armor" + }, + { + "id": "minecraft:iron_horse_armor" + }, + { + "id": "minecraft:golden_horse_armor" + }, + { + "id": "minecraft:diamond_horse_armor" + }, + { + "id": "minecraft:trident" + }, + { + "id": "minecraft:turtle_helmet" + }, + { + "id": "minecraft:elytra" + }, + { + "id": "minecraft:totem_of_undying" + }, + { + "id": "minecraft:glass_bottle" + }, + { + "id": "minecraft:experience_bottle" + }, + { + "id": "minecraft:potion" + }, + { + "id": "minecraft:potion", + "damage": 1 + }, + { + "id": "minecraft:potion", + "damage": 2 + }, + { + "id": "minecraft:potion", + "damage": 3 + }, + { + "id": "minecraft:potion", + "damage": 4 + }, + { + "id": "minecraft:potion", + "damage": 5 + }, + { + "id": "minecraft:potion", + "damage": 6 + }, + { + "id": "minecraft:potion", + "damage": 7 + }, + { + "id": "minecraft:potion", + "damage": 8 + }, + { + "id": "minecraft:potion", + "damage": 9 + }, + { + "id": "minecraft:potion", + "damage": 10 + }, + { + "id": "minecraft:potion", + "damage": 11 + }, + { + "id": "minecraft:potion", + "damage": 12 + }, + { + "id": "minecraft:potion", + "damage": 13 + }, + { + "id": "minecraft:potion", + "damage": 14 + }, + { + "id": "minecraft:potion", + "damage": 15 + }, + { + "id": "minecraft:potion", + "damage": 16 + }, + { + "id": "minecraft:potion", + "damage": 17 + }, + { + "id": "minecraft:potion", + "damage": 18 + }, + { + "id": "minecraft:potion", + "damage": 19 + }, + { + "id": "minecraft:potion", + "damage": 20 + }, + { + "id": "minecraft:potion", + "damage": 21 + }, + { + "id": "minecraft:potion", + "damage": 22 + }, + { + "id": "minecraft:potion", + "damage": 23 + }, + { + "id": "minecraft:potion", + "damage": 24 + }, + { + "id": "minecraft:potion", + "damage": 25 + }, + { + "id": "minecraft:potion", + "damage": 26 + }, + { + "id": "minecraft:potion", + "damage": 27 + }, + { + "id": "minecraft:potion", + "damage": 28 + }, + { + "id": "minecraft:potion", + "damage": 29 + }, + { + "id": "minecraft:potion", + "damage": 30 + }, + { + "id": "minecraft:potion", + "damage": 31 + }, + { + "id": "minecraft:potion", + "damage": 32 + }, + { + "id": "minecraft:potion", + "damage": 33 + }, + { + "id": "minecraft:potion", + "damage": 34 + }, + { + "id": "minecraft:potion", + "damage": 35 + }, + { + "id": "minecraft:potion", + "damage": 36 + }, + { + "id": "minecraft:potion", + "damage": 37 + }, + { + "id": "minecraft:potion", + "damage": 38 + }, + { + "id": "minecraft:potion", + "damage": 39 + }, + { + "id": "minecraft:potion", + "damage": 40 + }, + { + "id": "minecraft:potion", + "damage": 41 + }, + { + "id": "minecraft:potion", + "damage": 42 + }, + { + "id": "minecraft:splash_potion" + }, + { + "id": "minecraft:splash_potion", + "damage": 1 + }, + { + "id": "minecraft:splash_potion", + "damage": 2 + }, + { + "id": "minecraft:splash_potion", + "damage": 3 + }, + { + "id": "minecraft:splash_potion", + "damage": 4 + }, + { + "id": "minecraft:splash_potion", + "damage": 5 + }, + { + "id": "minecraft:splash_potion", + "damage": 6 + }, + { + "id": "minecraft:splash_potion", + "damage": 7 + }, + { + "id": "minecraft:splash_potion", + "damage": 8 + }, + { + "id": "minecraft:splash_potion", + "damage": 9 + }, + { + "id": "minecraft:splash_potion", + "damage": 10 + }, + { + "id": "minecraft:splash_potion", + "damage": 11 + }, + { + "id": "minecraft:splash_potion", + "damage": 12 + }, + { + "id": "minecraft:splash_potion", + "damage": 13 + }, + { + "id": "minecraft:splash_potion", + "damage": 14 + }, + { + "id": "minecraft:splash_potion", + "damage": 15 + }, + { + "id": "minecraft:splash_potion", + "damage": 16 + }, + { + "id": "minecraft:splash_potion", + "damage": 17 + }, + { + "id": "minecraft:splash_potion", + "damage": 18 + }, + { + "id": "minecraft:splash_potion", + "damage": 19 + }, + { + "id": "minecraft:splash_potion", + "damage": 20 + }, + { + "id": "minecraft:splash_potion", + "damage": 21 + }, + { + "id": "minecraft:splash_potion", + "damage": 22 + }, + { + "id": "minecraft:splash_potion", + "damage": 23 + }, + { + "id": "minecraft:splash_potion", + "damage": 24 + }, + { + "id": "minecraft:splash_potion", + "damage": 25 + }, + { + "id": "minecraft:splash_potion", + "damage": 26 + }, + { + "id": "minecraft:splash_potion", + "damage": 27 + }, + { + "id": "minecraft:splash_potion", + "damage": 28 + }, + { + "id": "minecraft:splash_potion", + "damage": 29 + }, + { + "id": "minecraft:splash_potion", + "damage": 30 + }, + { + "id": "minecraft:splash_potion", + "damage": 31 + }, + { + "id": "minecraft:splash_potion", + "damage": 32 + }, + { + "id": "minecraft:splash_potion", + "damage": 33 + }, + { + "id": "minecraft:splash_potion", + "damage": 34 + }, + { + "id": "minecraft:splash_potion", + "damage": 35 + }, + { + "id": "minecraft:splash_potion", + "damage": 36 + }, + { + "id": "minecraft:splash_potion", + "damage": 37 + }, + { + "id": "minecraft:splash_potion", + "damage": 38 + }, + { + "id": "minecraft:splash_potion", + "damage": 39 + }, + { + "id": "minecraft:splash_potion", + "damage": 40 + }, + { + "id": "minecraft:splash_potion", + "damage": 41 + }, + { + "id": "minecraft:splash_potion", + "damage": 42 + }, + { + "id": "minecraft:lingering_potion" + }, + { + "id": "minecraft:lingering_potion", + "damage": 1 + }, + { + "id": "minecraft:lingering_potion", + "damage": 2 + }, + { + "id": "minecraft:lingering_potion", + "damage": 3 + }, + { + "id": "minecraft:lingering_potion", + "damage": 4 + }, + { + "id": "minecraft:lingering_potion", + "damage": 5 + }, + { + "id": "minecraft:lingering_potion", + "damage": 6 + }, + { + "id": "minecraft:lingering_potion", + "damage": 7 + }, + { + "id": "minecraft:lingering_potion", + "damage": 8 + }, + { + "id": "minecraft:lingering_potion", + "damage": 9 + }, + { + "id": "minecraft:lingering_potion", + "damage": 10 + }, + { + "id": "minecraft:lingering_potion", + "damage": 11 + }, + { + "id": "minecraft:lingering_potion", + "damage": 12 + }, + { + "id": "minecraft:lingering_potion", + "damage": 13 + }, + { + "id": "minecraft:lingering_potion", + "damage": 14 + }, + { + "id": "minecraft:lingering_potion", + "damage": 15 + }, + { + "id": "minecraft:lingering_potion", + "damage": 16 + }, + { + "id": "minecraft:lingering_potion", + "damage": 17 + }, + { + "id": "minecraft:lingering_potion", + "damage": 18 + }, + { + "id": "minecraft:lingering_potion", + "damage": 19 + }, + { + "id": "minecraft:lingering_potion", + "damage": 20 + }, + { + "id": "minecraft:lingering_potion", + "damage": 21 + }, + { + "id": "minecraft:lingering_potion", + "damage": 22 + }, + { + "id": "minecraft:lingering_potion", + "damage": 23 + }, + { + "id": "minecraft:lingering_potion", + "damage": 24 + }, + { + "id": "minecraft:lingering_potion", + "damage": 25 + }, + { + "id": "minecraft:lingering_potion", + "damage": 26 + }, + { + "id": "minecraft:lingering_potion", + "damage": 27 + }, + { + "id": "minecraft:lingering_potion", + "damage": 28 + }, + { + "id": "minecraft:lingering_potion", + "damage": 29 + }, + { + "id": "minecraft:lingering_potion", + "damage": 30 + }, + { + "id": "minecraft:lingering_potion", + "damage": 31 + }, + { + "id": "minecraft:lingering_potion", + "damage": 32 + }, + { + "id": "minecraft:lingering_potion", + "damage": 33 + }, + { + "id": "minecraft:lingering_potion", + "damage": 34 + }, + { + "id": "minecraft:lingering_potion", + "damage": 35 + }, + { + "id": "minecraft:lingering_potion", + "damage": 36 + }, + { + "id": "minecraft:lingering_potion", + "damage": 37 + }, + { + "id": "minecraft:lingering_potion", + "damage": 38 + }, + { + "id": "minecraft:lingering_potion", + "damage": 39 + }, + { + "id": "minecraft:lingering_potion", + "damage": 40 + }, + { + "id": "minecraft:lingering_potion", + "damage": 41 + }, + { + "id": "minecraft:lingering_potion", + "damage": 42 + }, + { + "id": "minecraft:spyglass" + }, + { + "id": "minecraft:brush" + }, + { + "id": "minecraft:stick" + }, + { + "id": "minecraft:bed" + }, + { + "id": "minecraft:bed", + "damage": 8 + }, + { + "id": "minecraft:bed", + "damage": 7 + }, + { + "id": "minecraft:bed", + "damage": 15 + }, + { + "id": "minecraft:bed", + "damage": 12 + }, + { + "id": "minecraft:bed", + "damage": 14 + }, + { + "id": "minecraft:bed", + "damage": 1 + }, + { + "id": "minecraft:bed", + "damage": 4 + }, + { + "id": "minecraft:bed", + "damage": 5 + }, + { + "id": "minecraft:bed", + "damage": 13 + }, + { + "id": "minecraft:bed", + "damage": 9 + }, + { + "id": "minecraft:bed", + "damage": 3 + }, + { + "id": "minecraft:bed", + "damage": 11 + }, + { + "id": "minecraft:bed", + "damage": 10 + }, + { + "id": "minecraft:bed", + "damage": 2 + }, + { + "id": "minecraft:bed", + "damage": 6 + }, + { + "id": "minecraft:torch", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQyAAAACAQAbmFtZQ8AbWluZWNyYWZ0OnRvcmNoBAkAbmFtZV9oYXNoagn7rmDBzisDCgBuZXR3b3JrX2lkdwgAAAoGAHN0YXRlcwgWAHRvcmNoX2ZhY2luZ19kaXJlY3Rpb24HAHVua25vd24AAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:soul_torch", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQLAgAACAQAbmFtZRQAbWluZWNyYWZ0OnNvdWxfdG9yY2gECQBuYW1lX2hhc2huixOT04BRdQMKAG5ldHdvcmtfaWQRHwAACgYAc3RhdGVzCBYAdG9yY2hfZmFjaW5nX2RpcmVjdGlvbgcAdW5rbm93bgADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:sea_pickle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAQAACAQAbmFtZRQAbWluZWNyYWZ0OnNlYV9waWNrbGUECQBuYW1lX2hhc2iONEfZJB+glgMKAG5ldHdvcmtfaWRvJwAACgYAc3RhdGVzAw0AY2x1c3Rlcl9jb3VudAAAAAABCABkZWFkX2JpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:lantern", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTPAQAACAQAbmFtZREAbWluZWNyYWZ0OmxhbnRlcm4ECQBuYW1lX2hhc2hMw44VI2HWygMKAG5ldHdvcmtfaWQLMAAACgYAc3RhdGVzAQcAaGFuZ2luZwAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:soul_lantern", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQMAgAACAQAbmFtZRYAbWluZWNyYWZ0OnNvdWxfbGFudGVybgQJAG5hbWVfaGFzaGjIpjxk9z+RAwoAbmV0d29ya19pZF4lAAAKBgBzdGF0ZXMBBwBoYW5naW5nAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAgAACAQAbmFtZRAAbWluZWNyYWZ0OmNhbmRsZQQJAG5hbWVfaGFzaHPd+MsNdWTfAwoAbmV0d29ya19pZCUzAAAKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:white_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWScAgAACAQAbmFtZRYAbWluZWNyYWZ0OndoaXRlX2NhbmRsZQQJAG5hbWVfaGFzaN1EG5Q1mHiEAwoAbmV0d29ya19pZIQjAAAKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:orange_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSdAgAACAQAbmFtZRcAbWluZWNyYWZ0Om9yYW5nZV9jYW5kbGUECQBuYW1lX2hhc2jySEVWHgUIHQMKAG5ldHdvcmtfaWRYBAAACgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:magenta_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSeAgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hZ2VudGFfY2FuZGxlBAkAbmFtZV9oYXNoG0u6YIOoBSEDCgBuZXR3b3JrX2lklAQAAAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:light_blue_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSfAgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY2FuZGxlBAkAbmFtZV9oYXNocXGeK0zgrG0DCgBuZXR3b3JrX2lkBB0AAAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:yellow_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSgAgAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19jYW5kbGUECQBuYW1lX2hhc2i00dtusU3CqQMKAG5ldHdvcmtfaWRMLAAACgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:lime_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAgAACAQAbmFtZRUAbWluZWNyYWZ0OmxpbWVfY2FuZGxlBAkAbmFtZV9oYXNokcmrw5xvz7ADCgBuZXR3b3JrX2lk/CwAAAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:pink_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSiAgAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfY2FuZGxlBAkAbmFtZV9oYXNoQJdEY4sZ0dwDCgBuZXR3b3JrX2lkAzMAAAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:gray_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSjAgAACAQAbmFtZRUAbWluZWNyYWZ0OmdyYXlfY2FuZGxlBAkAbmFtZV9oYXNoS5poSo9wBDEDCgBuZXR3b3JrX2lkXwkAAAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:light_gray_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSkAgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY2FuZGxlBAkAbmFtZV9oYXNo9ruTZLBNMasDCgBuZXR3b3JrX2lkaSwAAAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:cyan_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAgAACAQAbmFtZRUAbWluZWNyYWZ0OmN5YW5fY2FuZGxlBAkAbmFtZV9oYXNoc/M8PNVcjOwDCgBuZXR3b3JrX2lkeDQAAAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:purple_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSmAgAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnBsZV9jYW5kbGUECQBuYW1lX2hhc2jaI3xUW0/myQMKAG5ldHdvcmtfaWTmLwAACgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:blue_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSnAgAACAQAbmFtZRUAbWluZWNyYWZ0OmJsdWVfY2FuZGxlBAkAbmFtZV9oYXNoAASSPW6TgQADCgBuZXR3b3JrX2lkAgAAAAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:brown_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAgAACAQAbmFtZRYAbWluZWNyYWZ0OmJyb3duX2NhbmRsZQQJAG5hbWVfaGFzaDia0l6s1+WYAwoAbmV0d29ya19pZCQpAAAKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:green_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSpAgAACAQAbmFtZRYAbWluZWNyYWZ0OmdyZWVuX2NhbmRsZQQJAG5hbWVfaGFzaLeFPO1l+fIoAwoAbmV0d29ya19pZKcHAAAKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:red_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSqAgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9jYW5kbGUECQBuYW1lX2hhc2jjAQpGf59ZdwMKAG5ldHdvcmtfaWQ2HwAACgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:black_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSrAgAACAQAbmFtZRYAbWluZWNyYWZ0OmJsYWNrX2NhbmRsZQQJAG5hbWVfaGFzaB+wRDpOqREKAwoAbmV0d29ya19pZE0CAAAKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:crafting_table", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ6AAAACAQAbmFtZRgAbWluZWNyYWZ0OmNyYWZ0aW5nX3RhYmxlBAkAbmFtZV9oYXNoe76VAmjvbpYDCgBuZXR3b3JrX2lkbicAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:cartography_table", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTHAQAACAQAbmFtZRsAbWluZWNyYWZ0OmNhcnRvZ3JhcGh5X3RhYmxlBAkAbmFtZV9oYXNomaWiiD/znP8DCgBuZXR3b3JrX2lkFDcAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:fletching_table", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTIAQAACAQAbmFtZRkAbWluZWNyYWZ0OmZsZXRjaGluZ190YWJsZQQJAG5hbWVfaGFzaPFibh8unKyUAwoAbmV0d29ya19pZDUnAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:smithing_table", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAQAACAQAbmFtZRgAbWluZWNyYWZ0OnNtaXRoaW5nX3RhYmxlBAkAbmFtZV9oYXNo4tFES2xOXEYDCgBuZXR3b3JrX2lk6RcAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:beehive", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTaAQAACAQAbmFtZREAbWluZWNyYWZ0OmJlZWhpdmUECQBuYW1lX2hhc2hCcqn12UbNpwMKAG5ldHdvcmtfaWQHLAAACgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAMLAGhvbmV5X2xldmVsAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:suspicious_sand", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQQAwAACAQAbmFtZRkAbWluZWNyYWZ0OnN1c3BpY2lvdXNfc2FuZAQJAG5hbWVfaGFzaL67QsuvLP00AwoAbmV0d29ya19pZCYKAAAKBgBzdGF0ZXMDEABicnVzaGVkX3Byb2dyZXNzAAAAAAEHAGhhbmdpbmcBAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:suspicious_gravel", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ8AwAACAQAbmFtZRsAbWluZWNyYWZ0OnN1c3BpY2lvdXNfZ3JhdmVsBAkAbmFtZV9oYXNoJSVbGNk7C3oDCgBuZXR3b3JrX2lkix8AAAoGAHN0YXRlcwMQAGJydXNoZWRfcHJvZ3Jlc3MAAAAAAQcAaGFuZ2luZwEAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:campfire" + }, + { + "id": "minecraft:soul_campfire" + }, + { + "id": "minecraft:furnace", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ9AAAACAQAbmFtZREAbWluZWNyYWZ0OmZ1cm5hY2UECQBuYW1lX2hhc2ioOQrludYY8wMKAG5ldHdvcmtfaWQaNQAACgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:blast_furnace", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTDAQAACAQAbmFtZRcAbWluZWNyYWZ0OmJsYXN0X2Z1cm5hY2UECQBuYW1lX2hhc2ivDbnjkpGm5QMKAG5ldHdvcmtfaWTUMwAACgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:smoker", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTFAQAACAQAbmFtZRAAbWluZWNyYWZ0OnNtb2tlcgQJAG5hbWVfaGFzaJd1rDMkRWomAwoAbmV0d29ya19pZO0GAAAKBgBzdGF0ZXMIHABtaW5lY3JhZnQ6Y2FyZGluYWxfZGlyZWN0aW9uBQBzb3V0aAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:respawn_anchor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQPAgAACAQAbmFtZRgAbWluZWNyYWZ0OnJlc3Bhd25fYW5jaG9yBAkAbmFtZV9oYXNoZOdcjW05qigDCgBuZXR3b3JrX2lkoQcAAAoGAHN0YXRlcwMVAHJlc3Bhd25fYW5jaG9yX2NoYXJnZQAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:brewing_stand" + }, + { + "id": "minecraft:anvil", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSRAAAACAQAbmFtZQ8AbWluZWNyYWZ0OmFudmlsBAkAbmFtZV9oYXNoNqB3fgcUCbwDCgBuZXR3b3JrX2lkRC4AAAoGAHN0YXRlcwgGAGRhbWFnZQkAdW5kYW1hZ2VkCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:anvil", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSRAAAACAQAbmFtZQ8AbWluZWNyYWZ0OmFudmlsBAkAbmFtZV9oYXNoNqB3fgcUCbwDCgBuZXR3b3JrX2lkSC4AAAoGAHN0YXRlcwgGAGRhbWFnZRAAc2xpZ2h0bHlfZGFtYWdlZAgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:anvil", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSRAAAACAQAbmFtZQ8AbWluZWNyYWZ0OmFudmlsBAkAbmFtZV9oYXNoNqB3fgcUCbwDCgBuZXR3b3JrX2lkTC4AAAoGAHN0YXRlcwgGAGRhbWFnZQwAdmVyeV9kYW1hZ2VkCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:grindstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTCAQAACAQAbmFtZRQAbWluZWNyYWZ0OmdyaW5kc3RvbmUECQBuYW1lX2hhc2id56zc0nk99wMKAG5ldHdvcmtfaWT6NQAACgYAc3RhdGVzCAoAYXR0YWNobWVudAgAc3RhbmRpbmcDCQBkaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:enchanting_table", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR0AAAACAQAbmFtZRoAbWluZWNyYWZ0OmVuY2hhbnRpbmdfdGFibGUECQBuYW1lX2hhc2jgIx24VLvMvwMKAG5ldHdvcmtfaWSaLgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:bookshelf", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQvAAAACAQAbmFtZRMAbWluZWNyYWZ0OmJvb2tzaGVsZgQJAG5hbWVfaGFzaDU04DrgJCS9AwoAbmV0d29ya19pZGouAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:chiseled_bookshelf", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQNAwAACAQAbmFtZRwAbWluZWNyYWZ0OmNoaXNlbGVkX2Jvb2tzaGVsZgQJAG5hbWVfaGFzaNXDBnsIsywYAwoAbmV0d29ya19pZA0DAAAKBgBzdGF0ZXMDDABib29rc19zdG9yZWQAAAAAAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:lectern", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTBAQAACAQAbmFtZREAbWluZWNyYWZ0OmxlY3Rlcm4ECQBuYW1lX2hhc2j5Z4Mmi/1QxAMKAG5ldHdvcmtfaWR8LwAACgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgBCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:cauldron" + }, + { + "id": "minecraft:composter", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTUAQAACAQAbmFtZRMAbWluZWNyYWZ0OmNvbXBvc3RlcgQJAG5hbWVfaGFzaPAADHptzeWJAwoAbmV0d29ya19pZO4jAAAKBgBzdGF0ZXMDFABjb21wb3N0ZXJfZmlsbF9sZXZlbAAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:chest", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ2AAAACAQAbmFtZQ8AbWluZWNyYWZ0OmNoZXN0BAkAbmFtZV9oYXNog9ozMxlcA88DCgBuZXR3b3JrX2lkWDAAAAoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAG5vcnRoAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:trapped_chest", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSSAAAACAQAbmFtZRcAbWluZWNyYWZ0OnRyYXBwZWRfY2hlc3QECQBuYW1lX2hhc2g2qpF9stsEjgMKAG5ldHdvcmtfaWS5JAAACgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAbm9ydGgAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:ender_chest", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSCAAAACAQAbmFtZRUAbWluZWNyYWZ0OmVuZGVyX2NoZXN0BAkAbmFtZV9oYXNohEZzOFdg0WUDCgBuZXR3b3JrX2lkMhwAAAoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAG5vcnRoAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:barrel", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTKAQAACAQAbmFtZRAAbWluZWNyYWZ0OmJhcnJlbAQJAG5hbWVfaGFzaHDkRPGymiRqAwoAbmV0d29ya19pZM8cAAAKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:undyed_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTNAAAACAQAbmFtZRwAbWluZWNyYWZ0OnVuZHllZF9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaOC9mypm/MlBAwoAbmV0d29ya19pZLkXAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:white_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTaAAAACAQAbmFtZRsAbWluZWNyYWZ0OndoaXRlX3NodWxrZXJfYm94BAkAbmFtZV9oYXNosK79m1rPUBwDCgBuZXR3b3JrX2lkVQQAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:light_gray_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRrAwAACAQAbmFtZSAAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2iBe5zq7PxHmgMKAG5ldHdvcmtfaWRGKQAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:gray_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRqAwAACAQAbmFtZRoAbWluZWNyYWZ0OmdyYXlfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2ga2s8ctjHUhgMKAG5ldHdvcmtfaWSoIwAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:black_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRyAwAACAQAbmFtZRsAbWluZWNyYWZ0OmJsYWNrX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoPm03OZphrp8DCgBuZXR3b3JrX2lklysAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:brown_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRvAwAACAQAbmFtZRsAbWluZWNyYWZ0OmJyb3duX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoT3DD6qAL9cADCgBuZXR3b3JrX2lkPy8AAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:red_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRxAwAACAQAbmFtZRkAbWluZWNyYWZ0OnJlZF9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaMIlKSCzqSZoAwoAbmV0d29ya19pZHMcAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:orange_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRkAwAACAQAbmFtZRwAbWluZWNyYWZ0Om9yYW5nZV9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaG2MAXU67wGrAwoAbmV0d29ya19pZGgsAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:yellow_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRnAwAACAQAbmFtZRwAbWluZWNyYWZ0OnllbGxvd19zaHVsa2VyX2JveAQJAG5hbWVfaGFzaIsLwQHYjcIEAwoAbmV0d29ya19pZHsAAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:lime_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRoAwAACAQAbmFtZRoAbWluZWNyYWZ0OmxpbWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2hUwBkg+faUGAMKAG5ldHdvcmtfaWQWBAAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:green_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRwAwAACAQAbmFtZRsAbWluZWNyYWZ0OmdyZWVuX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoZgUeT3LupLUDCgBuZXR3b3JrX2lkpS0AAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:cyan_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRsAwAACAQAbmFtZRoAbWluZWNyYWZ0OmN5YW5fc2h1bGtlcl9ib3gECQBuYW1lX2hhc2gSfbjteXg5yAMKAG5ldHdvcmtfaWTZLwAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:light_blue_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRmAwAACAQAbmFtZSAAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2h0VFCX0qsRxQMKAG5ldHdvcmtfaWSXLwAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:blue_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRuAwAACAQAbmFtZRoAbWluZWNyYWZ0OmJsdWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2hn9gS0XIe6rAMKAG5ldHdvcmtfaWSZLAAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:purple_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRtAwAACAQAbmFtZRwAbWluZWNyYWZ0OnB1cnBsZV9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaEV/lkNPxRDdAwoAbmV0d29ya19pZAszAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:magenta_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRlAwAACAQAbmFtZR0AbWluZWNyYWZ0Om1hZ2VudGFfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2iqWM7IJHxcFgMKAG5ldHdvcmtfaWTgAgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:pink_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRpAwAACAQAbmFtZRoAbWluZWNyYWZ0OnBpbmtfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2in1tkJ1GNcZgMKAG5ldHdvcmtfaWQ6HAAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:armor_stand" + }, + { + "id": "minecraft:noteblock", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQZAAAACAQAbmFtZRMAbWluZWNyYWZ0Om5vdGVibG9jawQJAG5hbWVfaGFzaHPA8dBBH0UaAwoAbmV0d29ya19pZEUEAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:jukebox", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRUAAAACAQAbmFtZREAbWluZWNyYWZ0Omp1a2Vib3gECQBuYW1lX2hhc2ieAIPExf/ZfgMKAG5ldHdvcmtfaWS1IQAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:music_disc_13" + }, + { + "id": "minecraft:music_disc_cat" + }, + { + "id": "minecraft:music_disc_blocks" + }, + { + "id": "minecraft:music_disc_chirp" + }, + { + "id": "minecraft:music_disc_far" + }, + { + "id": "minecraft:music_disc_mall" + }, + { + "id": "minecraft:music_disc_mellohi" + }, + { + "id": "minecraft:music_disc_stal" + }, + { + "id": "minecraft:music_disc_strad" + }, + { + "id": "minecraft:music_disc_ward" + }, + { + "id": "minecraft:music_disc_11" + }, + { + "id": "minecraft:music_disc_wait" + }, + { + "id": "minecraft:music_disc_otherside" + }, + { + "id": "minecraft:music_disc_5" + }, + { + "id": "minecraft:music_disc_pigstep" + }, + { + "id": "minecraft:music_disc_relic" + }, + { + "id": "minecraft:disc_fragment_5" + }, + { + "id": "minecraft:glowstone_dust" + }, + { + "id": "minecraft:glowstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRZAAAACAQAbmFtZRMAbWluZWNyYWZ0Omdsb3dzdG9uZQQJAG5hbWVfaGFzaFYqXNkefIlPAwoAbmV0d29ya19pZA0aAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:redstone_lamp", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR7AAAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZHN0b25lX2xhbXAECQBuYW1lX2hhc2hJ9V80caPvEgMKAG5ldHdvcmtfaWSnAgAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:sea_lantern", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSpAAAACAQAbmFtZRUAbWluZWNyYWZ0OnNlYV9sYW50ZXJuBAkAbmFtZV9oYXNoLPsv1TX9M+QDCgBuZXR3b3JrX2lkuzMAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:oak_sign" + }, + { + "id": "minecraft:spruce_sign" + }, + { + "id": "minecraft:birch_sign" + }, + { + "id": "minecraft:jungle_sign" + }, + { + "id": "minecraft:acacia_sign" + }, + { + "id": "minecraft:dark_oak_sign" + }, + { + "id": "minecraft:mangrove_sign" + }, + { + "id": "minecraft:cherry_sign" + }, + { + "id": "minecraft:bamboo_sign" + }, + { + "id": "minecraft:crimson_sign" + }, + { + "id": "minecraft:warped_sign" + }, + { + "id": "minecraft:oak_hanging_sign" + }, + { + "id": "minecraft:spruce_hanging_sign" + }, + { + "id": "minecraft:birch_hanging_sign" + }, + { + "id": "minecraft:jungle_hanging_sign" + }, + { + "id": "minecraft:acacia_hanging_sign" + }, + { + "id": "minecraft:dark_oak_hanging_sign" + }, + { + "id": "minecraft:mangrove_hanging_sign" + }, + { + "id": "minecraft:cherry_hanging_sign" + }, + { + "id": "minecraft:bamboo_hanging_sign" + }, + { + "id": "minecraft:crimson_hanging_sign" + }, + { + "id": "minecraft:warped_hanging_sign" + }, + { + "id": "minecraft:painting" + }, + { + "id": "minecraft:frame" + }, + { + "id": "minecraft:glow_frame" + }, + { + "id": "minecraft:honey_bottle" + }, + { + "id": "minecraft:flower_pot" + }, + { + "id": "minecraft:bowl" + }, + { + "id": "minecraft:bucket" + }, + { + "id": "minecraft:milk_bucket" + }, + { + "id": "minecraft:water_bucket" + }, + { + "id": "minecraft:lava_bucket" + }, + { + "id": "minecraft:cod_bucket" + }, + { + "id": "minecraft:salmon_bucket" + }, + { + "id": "minecraft:tropical_fish_bucket" + }, + { + "id": "minecraft:pufferfish_bucket" + }, + { + "id": "minecraft:powder_snow_bucket" + }, + { + "id": "minecraft:axolotl_bucket" + }, + { + "id": "minecraft:tadpole_bucket" + }, + { + "id": "minecraft:skull", + "damage": 3 + }, + { + "id": "minecraft:skull", + "damage": 2 + }, + { + "id": "minecraft:skull", + "damage": 4 + }, + { + "id": "minecraft:skull", + "damage": 5 + }, + { + "id": "minecraft:skull" + }, + { + "id": "minecraft:skull", + "damage": 1 + }, + { + "id": "minecraft:skull", + "damage": 6 + }, + { + "id": "minecraft:beacon", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSKAAAACAQAbmFtZRAAbWluZWNyYWZ0OmJlYWNvbgQJAG5hbWVfaGFzaACwhhfSkdkHAwoAbmV0d29ya19pZDMCAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:bell", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTNAQAACAQAbmFtZQ4AbWluZWNyYWZ0OmJlbGwECQBuYW1lX2hhc2iPqsgDXRcsxAMKAG5ldHdvcmtfaWRcLwAACgYAc3RhdGVzCAoAYXR0YWNobWVudAgAc3RhbmRpbmcDCQBkaXJlY3Rpb24AAAAAAQoAdG9nZ2xlX2JpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:conduit", + "block_state_b64": "CgAAAwgAYmxvY2tfaWScAQAACAQAbmFtZREAbWluZWNyYWZ0OmNvbmR1aXQECQBuYW1lX2hhc2jqxKAxq2EaWQMKAG5ldHdvcmtfaWR1GwAACgYAc3RhdGVzAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:stonecutter_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTEAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lY3V0dGVyX2Jsb2NrBAkAbmFtZV9oYXNoQAXTbAM3MeYDCgBuZXR3b3JrX2lk2zMAAAoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAG5vcnRoAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:end_portal_frame", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR4AAAACAQAbmFtZRoAbWluZWNyYWZ0OmVuZF9wb3J0YWxfZnJhbWUECQBuYW1lX2hhc2gqofyUIjGOpQMKAG5ldHdvcmtfaWTHKwAACgYAc3RhdGVzARIAZW5kX3BvcnRhbF9leWVfYml0AAgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:coal" + }, + { + "id": "minecraft:charcoal" + }, + { + "id": "minecraft:diamond" + }, + { + "id": "minecraft:iron_nugget" + }, + { + "id": "minecraft:raw_iron" + }, + { + "id": "minecraft:raw_gold" + }, + { + "id": "minecraft:raw_copper" + }, + { + "id": "minecraft:copper_ingot" + }, + { + "id": "minecraft:iron_ingot" + }, + { + "id": "minecraft:netherite_scrap" + }, + { + "id": "minecraft:netherite_ingot" + }, + { + "id": "minecraft:gold_nugget" + }, + { + "id": "minecraft:gold_ingot" + }, + { + "id": "minecraft:emerald" + }, + { + "id": "minecraft:quartz" + }, + { + "id": "minecraft:clay_ball" + }, + { + "id": "minecraft:brick" + }, + { + "id": "minecraft:netherbrick" + }, + { + "id": "minecraft:prismarine_shard" + }, + { + "id": "minecraft:amethyst_shard" + }, + { + "id": "minecraft:prismarine_crystals" + }, + { + "id": "minecraft:nautilus_shell" + }, + { + "id": "minecraft:heart_of_the_sea" + }, + { + "id": "minecraft:turtle_scute" + }, + { + "id": "minecraft:phantom_membrane" + }, + { + "id": "minecraft:string" + }, + { + "id": "minecraft:feather" + }, + { + "id": "minecraft:flint" + }, + { + "id": "minecraft:gunpowder" + }, + { + "id": "minecraft:leather" + }, + { + "id": "minecraft:rabbit_hide" + }, + { + "id": "minecraft:rabbit_foot" + }, + { + "id": "minecraft:fire_charge" + }, + { + "id": "minecraft:blaze_rod" + }, + { + "id": "minecraft:blaze_powder" + }, + { + "id": "minecraft:magma_cream" + }, + { + "id": "minecraft:fermented_spider_eye" + }, + { + "id": "minecraft:echo_shard" + }, + { + "id": "minecraft:dragon_breath" + }, + { + "id": "minecraft:shulker_shell" + }, + { + "id": "minecraft:ghast_tear" + }, + { + "id": "minecraft:slime_ball" + }, + { + "id": "minecraft:ender_pearl" + }, + { + "id": "minecraft:ender_eye" + }, + { + "id": "minecraft:nether_star" + }, + { + "id": "minecraft:end_rod", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTQAAAACAQAbmFtZREAbWluZWNyYWZ0OmVuZF9yb2QECQBuYW1lX2hhc2jx/q5cEA0hmQMKAG5ldHdvcmtfaWQ0KQAACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:lightning_rod", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ3AgAACAQAbmFtZRcAbWluZWNyYWZ0OmxpZ2h0bmluZ19yb2QECQBuYW1lX2hhc2ioXQF1xvfHNQMKAG5ldHdvcmtfaWQ+CgAACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:end_crystal" + }, + { + "id": "minecraft:paper" + }, + { + "id": "minecraft:book" + }, + { + "id": "minecraft:writable_book" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQFAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQFAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQFAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQGAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQGAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQGAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQHAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQHAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQHAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQIAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAUAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAUAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAUAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQMAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQMAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQNAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQNAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQOAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQOAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQOAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAUAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQQAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQRAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQRAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQRAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQSAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQSAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQSAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAUAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQUAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQUAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQVAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQWAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQXAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQXAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQXAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQYAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQYAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQYAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQZAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQZAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQaAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQbAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQcAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAUAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQeAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQeAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQeAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQfAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQfAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQfAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQgAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQhAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQjAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQjAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQjAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQkAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQkAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQkAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQlAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQlAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQlAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:oak_boat" + }, + { + "id": "minecraft:spruce_boat" + }, + { + "id": "minecraft:birch_boat" + }, + { + "id": "minecraft:jungle_boat" + }, + { + "id": "minecraft:acacia_boat" + }, + { + "id": "minecraft:dark_oak_boat" + }, + { + "id": "minecraft:mangrove_boat" + }, + { + "id": "minecraft:cherry_boat" + }, + { + "id": "minecraft:bamboo_raft" + }, + { + "id": "minecraft:oak_chest_boat" + }, + { + "id": "minecraft:spruce_chest_boat" + }, + { + "id": "minecraft:birch_chest_boat" + }, + { + "id": "minecraft:jungle_chest_boat" + }, + { + "id": "minecraft:acacia_chest_boat" + }, + { + "id": "minecraft:dark_oak_chest_boat" + }, + { + "id": "minecraft:mangrove_chest_boat" + }, + { + "id": "minecraft:cherry_chest_boat" + }, + { + "id": "minecraft:bamboo_chest_raft" + }, + { + "id": "minecraft:rail", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRCAAAACAQAbmFtZQ4AbWluZWNyYWZ0OnJhaWwECQBuYW1lX2hhc2hUzmhUXYJDUQMKAG5ldHdvcmtfaWQxGgAACgYAc3RhdGVzAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:golden_rail", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQbAAAACAQAbmFtZRUAbWluZWNyYWZ0OmdvbGRlbl9yYWlsBAkAbmFtZV9oYXNoOoV5MaKipoUDCgBuZXR3b3JrX2lklSMAAAoGAHN0YXRlcwENAHJhaWxfZGF0YV9iaXQAAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:detector_rail", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQcAAAACAQAbmFtZRcAbWluZWNyYWZ0OmRldGVjdG9yX3JhaWwECQBuYW1lX2hhc2gVUk31qOysUQMKAG5ldHdvcmtfaWQGGwAACgYAc3RhdGVzAQ0AcmFpbF9kYXRhX2JpdAADDgByYWlsX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:activator_rail", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR+AAAACAQAbmFtZRgAbWluZWNyYWZ0OmFjdGl2YXRvcl9yYWlsBAkAbmFtZV9oYXNosIL91qriCRkDCgBuZXR3b3JrX2lkHgQAAAoGAHN0YXRlcwENAHJhaWxfZGF0YV9iaXQAAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:minecart" + }, + { + "id": "minecraft:chest_minecart" + }, + { + "id": "minecraft:hopper_minecart" + }, + { + "id": "minecraft:tnt_minecart" + }, + { + "id": "minecraft:redstone" + }, + { + "id": "minecraft:redstone_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSYAAAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZHN0b25lX2Jsb2NrBAkAbmFtZV9oYXNoRhULL0r8o0sDCgBuZXR3b3JrX2lkIxgAAAoGAHN0YXRlcwADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:redstone_torch", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRMAAAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZHN0b25lX3RvcmNoBAkAbmFtZV9oYXNoizFRjpYMIDgDCgBuZXR3b3JrX2lkgxUAAAoGAHN0YXRlcwgWAHRvcmNoX2ZhY2luZ19kaXJlY3Rpb24HAHVua25vd24AAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:lever", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRFAAAACAQAbmFtZQ8AbWluZWNyYWZ0OmxldmVyBAkAbmFtZV9oYXNoGMJeLJsUMLYDCgBuZXR3b3JrX2lktS0AAAoGAHN0YXRlcwgPAGxldmVyX2RpcmVjdGlvbg4AZG93bl9lYXN0X3dlc3QBCABvcGVuX2JpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:wooden_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSPAAAACAQAbmFtZRcAbWluZWNyYWZ0Ondvb2Rlbl9idXR0b24ECQBuYW1lX2hhc2hR7PgSTQt0sQMKAG5ldHdvcmtfaWQULQAACgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:spruce_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSPAQAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9idXR0b24ECQBuYW1lX2hhc2jBW9Z8aYE7YQMKAG5ldHdvcmtfaWT4GwAACgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:birch_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSMAQAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX2J1dHRvbgQJAG5hbWVfaGFzaJXYgGuSHbTwAwoAbmV0d29ya19pZMU0AAAKBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:jungle_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSOAQAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9idXR0b24ECQBuYW1lX2hhc2iCgNANcJs+BQMKAG5ldHdvcmtfaWSAAAAACgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:acacia_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAQAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9idXR0b24ECQBuYW1lX2hhc2gVvmcT7LTO0wMKAG5ldHdvcmtfaWRqMgAACgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:dark_oak_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSNAQAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX2J1dHRvbgQJAG5hbWVfaGFzaIV10ZGGrCIEAwoAbmV0d29ya19pZGYAAAAKBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:mangrove_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTmAgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX2J1dHRvbgQJAG5hbWVfaGFzaNzeYYKLgOzJAwoAbmV0d29ya19pZP4vAAAKBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:cherry_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQRAwAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9idXR0b24ECQBuYW1lX2hhc2j2/IHjeAbUcwMKAG5ldHdvcmtfaWRQHQAACgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:bamboo_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT+AgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19idXR0b24ECQBuYW1lX2hhc2j7AddMi+6nsgMKAG5ldHdvcmtfaWSOLQAACgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:stone_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRNAAAACAQAbmFtZRYAbWluZWNyYWZ0OnN0b25lX2J1dHRvbgQJAG5hbWVfaGFzaM4ejMctmvohAwoAbmV0d29ya19pZEkFAAAKBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:crimson_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fYnV0dG9uBAkAbmFtZV9oYXNofnjYHaYIeWgDCgBuZXR3b3JrX2lkdxwAAAoGAHN0YXRlcwESAGJ1dHRvbl9wcmVzc2VkX2JpdAADEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:warped_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQEAgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9idXR0b24ECQBuYW1lX2hhc2jwkV2EU6Cn1QMKAG5ldHdvcmtfaWR8MgAACgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:polished_blackstone_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQnAgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnV0dG9uBAkAbmFtZV9oYXNojmxzQKS0S/EDCgBuZXR3b3JrX2lk3TQAAAoGAHN0YXRlcwESAGJ1dHRvbl9wcmVzc2VkX2JpdAADEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:tripwire_hook", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAAAACAQAbmFtZRcAbWluZWNyYWZ0OnRyaXB3aXJlX2hvb2sECQBuYW1lX2hhc2gQdp+oGZLNnAMKAG5ldHdvcmtfaWR7KQAACgYAc3RhdGVzAQwAYXR0YWNoZWRfYml0AAMJAGRpcmVjdGlvbgAAAAABCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:wooden_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRIAAAACAQAbmFtZR8AbWluZWNyYWZ0Ondvb2Rlbl9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaGkGs5kCuA74AwoAbmV0d29ya19pZBM2AAAKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:spruce_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSZAQAACAQAbmFtZR8AbWluZWNyYWZ0OnNwcnVjZV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaNmwuq549fJKAwoAbmV0d29ya19pZBEYAAAKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:birch_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSWAQAACAQAbmFtZR4AbWluZWNyYWZ0OmJpcmNoX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNorQkT9kDdlTwDCgBuZXR3b3JrX2lkNBcAAAoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:jungle_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSYAQAACAQAbmFtZR8AbWluZWNyYWZ0Omp1bmdsZV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaJ7DcteCkb8/AwoAbmV0d29ya19pZIoXAAAKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:acacia_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSVAQAACAQAbmFtZR8AbWluZWNyYWZ0OmFjYWNpYV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaC2frZtfoYqCAwoAbmV0d29ya19pZD4jAAAKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:dark_oak_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSXAQAACAQAbmFtZSEAbWluZWNyYWZ0OmRhcmtfb2FrX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoHUCJsTy52pwDCgBuZXR3b3JrX2lkpSkAAAoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:mangrove_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTpAgAACAQAbmFtZSEAbWluZWNyYWZ0Om1hbmdyb3ZlX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoiDsTfJaX100DCgBuZXR3b3JrX2lk/BkAAAoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:cherry_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQZAwAACAQAbmFtZR8AbWluZWNyYWZ0OmNoZXJyeV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaALMqYEZDUQHAwoAbmV0d29ya19pZJoAAAAKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:bamboo_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQBAwAACAQAbmFtZR8AbWluZWNyYWZ0OmJhbWJvb19wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaNvxJ7NIAaqlAwoAbmV0d29ya19pZM8rAAAKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:crimson_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQFAgAACAQAbmFtZSAAbWluZWNyYWZ0OmNyaW1zb25fcHJlc3N1cmVfcGxhdGUECQBuYW1lX2hhc2hqBDVDAd31/gMKAG5ldHdvcmtfaWQANwAACgYAc3RhdGVzAw8AcmVkc3RvbmVfc2lnbmFsAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:warped_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAgAACAQAbmFtZR8AbWluZWNyYWZ0OndhcnBlZF9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaBxFoQksWtYUAwoAbmV0d29ya19pZMECAAAKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:stone_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRGAAAACAQAbmFtZR4AbWluZWNyYWZ0OnN0b25lX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNounJuTBUTrU8DCgBuZXR3b3JrX2lkDhoAAAoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:light_weighted_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSTAAAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X3dlaWdodGVkX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoOyOJkNxLtkEDCgBuZXR3b3JrX2lkqRcAAAoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:heavy_weighted_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSUAAAACAQAbmFtZScAbWluZWNyYWZ0OmhlYXZ5X3dlaWdodGVkX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoltgDmDvTajUDCgBuZXR3b3JrX2lkLQoAAAoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:polished_blackstone_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAgAACAQAbmFtZSwAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfcHJlc3N1cmVfcGxhdGUECQBuYW1lX2hhc2h65Ci6/CeGqwMKAG5ldHdvcmtfaWRxLAAACgYAc3RhdGVzAw8AcmVkc3RvbmVfc2lnbmFsAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:observer", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT7AAAACAQAbmFtZRIAbWluZWNyYWZ0Om9ic2VydmVyBAkAbmFtZV9oYXNoYhlh1lpmHTgDCgBuZXR3b3JrX2lkdxUAAAoGAHN0YXRlcwgaAG1pbmVjcmFmdDpmYWNpbmdfZGlyZWN0aW9uBABkb3duAQsAcG93ZXJlZF9iaXQAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:daylight_detector", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSXAAAACAQAbmFtZRsAbWluZWNyYWZ0OmRheWxpZ2h0X2RldGVjdG9yBAkAbmFtZV9oYXNoV0F0s7B7PVgDCgBuZXR3b3JrX2lkUhsAAAoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:repeater" + }, + { + "id": "minecraft:comparator" + }, + { + "id": "minecraft:hopper" + }, + { + "id": "minecraft:dropper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR9AAAACAQAbmFtZREAbWluZWNyYWZ0OmRyb3BwZXIECQBuYW1lX2hhc2joXP7XqU0l3QMKAG5ldHdvcmtfaWQTMwAACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgMAAAABDQB0cmlnZ2VyZWRfYml0AAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:dispenser", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQXAAAACAQAbmFtZRMAbWluZWNyYWZ0OmRpc3BlbnNlcgQJAG5hbWVfaGFzaP1RR+zAbYP2AwoAbmV0d29ya19pZO81AAAKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAwAAAAENAHRyaWdnZXJlZF9iaXQAAAMHAHZlcnNpb24BPBQBAA==" + }, + { + "id": "minecraft:piston", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQhAAAACAQAbmFtZRAAbWluZWNyYWZ0OnBpc3RvbgQJAG5hbWVfaGFzaDs3AFh1fL0uAwoAbmV0d29ya19pZE0JAAAKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAQAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:sticky_piston", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQdAAAACAQAbmFtZRcAbWluZWNyYWZ0OnN0aWNreV9waXN0b24ECQBuYW1lX2hhc2hPFJFJSiJ0ZQMKAG5ldHdvcmtfaWQrHAAACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgEAAAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:tnt", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQuAAAACAQAbmFtZQ0AbWluZWNyYWZ0OnRudAQJAG5hbWVfaGFzaEYOHwCvJH29AwoAbmV0d29ya19pZIMuAAAKBgBzdGF0ZXMBFABhbGxvd191bmRlcndhdGVyX2JpdAABCwBleHBsb2RlX2JpdAAAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:name_tag" + }, + { + "id": "minecraft:loom", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTLAQAACAQAbmFtZQ4AbWluZWNyYWZ0Omxvb20ECQBuYW1lX2hhc2i7DKjAXNq8TAMKAG5ldHdvcmtfaWTVGQAACgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:banner" + }, + { + "id": "minecraft:banner", + "damage": 8 + }, + { + "id": "minecraft:banner", + "damage": 7 + }, + { + "id": "minecraft:banner", + "damage": 15 + }, + { + "id": "minecraft:banner", + "damage": 12 + }, + { + "id": "minecraft:banner", + "damage": 14 + }, + { + "id": "minecraft:banner", + "damage": 1 + }, + { + "id": "minecraft:banner", + "damage": 4 + }, + { + "id": "minecraft:banner", + "damage": 5 + }, + { + "id": "minecraft:banner", + "damage": 13 + }, + { + "id": "minecraft:banner", + "damage": 9 + }, + { + "id": "minecraft:banner", + "damage": 3 + }, + { + "id": "minecraft:banner", + "damage": 11 + }, + { + "id": "minecraft:banner", + "damage": 10 + }, + { + "id": "minecraft:banner", + "damage": 2 + }, + { + "id": "minecraft:banner", + "damage": 6 + }, + { + "id": "minecraft:banner", + "damage": 15, + "nbt_b64": "CgAAAwQAVHlwZQEAAAAA" + }, + { + "id": "minecraft:creeper_banner_pattern" + }, + { + "id": "minecraft:skull_banner_pattern" + }, + { + "id": "minecraft:flower_banner_pattern" + }, + { + "id": "minecraft:mojang_banner_pattern" + }, + { + "id": "minecraft:field_masoned_banner_pattern" + }, + { + "id": "minecraft:bordure_indented_banner_pattern" + }, + { + "id": "minecraft:piglin_banner_pattern" + }, + { + "id": "minecraft:globe_banner_pattern" + }, + { + "id": "minecraft:angler_pottery_sherd" + }, + { + "id": "minecraft:archer_pottery_sherd" + }, + { + "id": "minecraft:arms_up_pottery_sherd" + }, + { + "id": "minecraft:blade_pottery_sherd" + }, + { + "id": "minecraft:brewer_pottery_sherd" + }, + { + "id": "minecraft:burn_pottery_sherd" + }, + { + "id": "minecraft:danger_pottery_sherd" + }, + { + "id": "minecraft:explorer_pottery_sherd" + }, + { + "id": "minecraft:friend_pottery_sherd" + }, + { + "id": "minecraft:heart_pottery_sherd" + }, + { + "id": "minecraft:heartbreak_pottery_sherd" + }, + { + "id": "minecraft:howl_pottery_sherd" + }, + { + "id": "minecraft:miner_pottery_sherd" + }, + { + "id": "minecraft:mourner_pottery_sherd" + }, + { + "id": "minecraft:plenty_pottery_sherd" + }, + { + "id": "minecraft:prize_pottery_sherd" + }, + { + "id": "minecraft:sheaf_pottery_sherd" + }, + { + "id": "minecraft:shelter_pottery_sherd" + }, + { + "id": "minecraft:skull_pottery_sherd" + }, + { + "id": "minecraft:snort_pottery_sherd" + }, + { + "id": "minecraft:netherite_upgrade_smithing_template" + }, + { + "id": "minecraft:sentry_armor_trim_smithing_template" + }, + { + "id": "minecraft:vex_armor_trim_smithing_template" + }, + { + "id": "minecraft:wild_armor_trim_smithing_template" + }, + { + "id": "minecraft:coast_armor_trim_smithing_template" + }, + { + "id": "minecraft:dune_armor_trim_smithing_template" + }, + { + "id": "minecraft:wayfinder_armor_trim_smithing_template" + }, + { + "id": "minecraft:shaper_armor_trim_smithing_template" + }, + { + "id": "minecraft:raiser_armor_trim_smithing_template" + }, + { + "id": "minecraft:host_armor_trim_smithing_template" + }, + { + "id": "minecraft:ward_armor_trim_smithing_template" + }, + { + "id": "minecraft:silence_armor_trim_smithing_template" + }, + { + "id": "minecraft:tide_armor_trim_smithing_template" + }, + { + "id": "minecraft:snout_armor_trim_smithing_template" + }, + { + "id": "minecraft:rib_armor_trim_smithing_template" + }, + { + "id": "minecraft:eye_armor_trim_smithing_template" + }, + { + "id": "minecraft:spire_armor_trim_smithing_template" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwAAAAAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAABwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAIBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAHBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAPBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAMBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAOBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAABBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAEBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAFBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAANBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAJBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAADBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAALBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAKBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAACBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAGBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_star", + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yIR0d/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 8, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yUk9H/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 7, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yl52d/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 15, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9y8PDw/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 12, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9y2rM6/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 14, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yHYD5/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 1, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yJi6w/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 4, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yqkQ8/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 5, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yuDKJ/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 13, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yvU7H/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 9, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yqovz/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 3, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yMlSD/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 11, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yPdj+/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 10, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yH8eA/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 2, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yFnxe/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 6, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9ynJwW/wA=" + }, + { + "id": "minecraft:chain" + }, + { + "id": "minecraft:target", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTuAQAACAQAbmFtZRAAbWluZWNyYWZ0OnRhcmdldAQJAG5hbWVfaGFzaJc66SVbYlaxAwoAbmV0d29ya19pZBMtAAAKBgBzdGF0ZXMAAwcAdmVyc2lvbgE8FAEA" + }, + { + "id": "minecraft:decorated_pot", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAwAACAQAbmFtZRcAbWluZWNyYWZ0OmRlY29yYXRlZF9wb3QECQBuYW1lX2hhc2jjQgckn8VTvwMKAG5ldHdvcmtfaWSWLgAACgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATwUAQA=" + }, + { + "id": "minecraft:lodestone_compass" + }, + { + "id": "minecraft:wither_spawn_egg" + }, + { + "id": "minecraft:ender_dragon_spawn_egg" + } + ] +} \ No newline at end of file diff --git a/core/src/main/resources/bedrock/runtime_item_states.1_20_60.json b/core/src/main/resources/bedrock/runtime_item_states.1_20_60.json new file mode 100644 index 000000000..f8b3199e3 --- /dev/null +++ b/core/src/main/resources/bedrock/runtime_item_states.1_20_60.json @@ -0,0 +1,5998 @@ +[ + { + "name": "minecraft:acacia_boat", + "id": 382 + }, + { + "name": "minecraft:acacia_button", + "id": -140 + }, + { + "name": "minecraft:acacia_chest_boat", + "id": 651 + }, + { + "name": "minecraft:acacia_door", + "id": 565 + }, + { + "name": "minecraft:acacia_fence", + "id": -575 + }, + { + "name": "minecraft:acacia_fence_gate", + "id": 187 + }, + { + "name": "minecraft:acacia_hanging_sign", + "id": -504 + }, + { + "name": "minecraft:acacia_log", + "id": 162 + }, + { + "name": "minecraft:acacia_planks", + "id": -742 + }, + { + "name": "minecraft:acacia_pressure_plate", + "id": -150 + }, + { + "name": "minecraft:acacia_sign", + "id": 588 + }, + { + "name": "minecraft:acacia_stairs", + "id": 163 + }, + { + "name": "minecraft:acacia_standing_sign", + "id": -190 + }, + { + "name": "minecraft:acacia_trapdoor", + "id": -145 + }, + { + "name": "minecraft:acacia_wall_sign", + "id": -191 + }, + { + "name": "minecraft:activator_rail", + "id": 126 + }, + { + "name": "minecraft:agent_spawn_egg", + "id": 490 + }, + { + "name": "minecraft:air", + "id": -158 + }, + { + "name": "minecraft:allay_spawn_egg", + "id": 640 + }, + { + "name": "minecraft:allow", + "id": 210 + }, + { + "name": "minecraft:amethyst_block", + "id": -327 + }, + { + "name": "minecraft:amethyst_cluster", + "id": -329 + }, + { + "name": "minecraft:amethyst_shard", + "id": 633 + }, + { + "name": "minecraft:ancient_debris", + "id": -271 + }, + { + "name": "minecraft:andesite", + "id": -594 + }, + { + "name": "minecraft:andesite_stairs", + "id": -171 + }, + { + "name": "minecraft:angler_pottery_sherd", + "id": 665 + }, + { + "name": "minecraft:anvil", + "id": 145 + }, + { + "name": "minecraft:apple", + "id": 257 + }, + { + "name": "minecraft:archer_pottery_sherd", + "id": 666 + }, + { + "name": "minecraft:armadillo_scute", + "id": 707 + }, + { + "name": "minecraft:armadillo_spawn_egg", + "id": 706 + }, + { + "name": "minecraft:armor_stand", + "id": 561 + }, + { + "name": "minecraft:arms_up_pottery_sherd", + "id": 667 + }, + { + "name": "minecraft:arrow", + "id": 304 + }, + { + "name": "minecraft:axolotl_bucket", + "id": 372 + }, + { + "name": "minecraft:axolotl_spawn_egg", + "id": 505 + }, + { + "name": "minecraft:azalea", + "id": -337 + }, + { + "name": "minecraft:azalea_leaves", + "id": -324 + }, + { + "name": "minecraft:azalea_leaves_flowered", + "id": -325 + }, + { + "name": "minecraft:baked_potato", + "id": 282 + }, + { + "name": "minecraft:balloon", + "id": 607 + }, + { + "name": "minecraft:bamboo", + "id": -163 + }, + { + "name": "minecraft:bamboo_block", + "id": -527 + }, + { + "name": "minecraft:bamboo_button", + "id": -511 + }, + { + "name": "minecraft:bamboo_chest_raft", + "id": 663 + }, + { + "name": "minecraft:bamboo_door", + "id": -517 + }, + { + "name": "minecraft:bamboo_double_slab", + "id": -521 + }, + { + "name": "minecraft:bamboo_fence", + "id": -515 + }, + { + "name": "minecraft:bamboo_fence_gate", + "id": -516 + }, + { + "name": "minecraft:bamboo_hanging_sign", + "id": -522 + }, + { + "name": "minecraft:bamboo_mosaic", + "id": -509 + }, + { + "name": "minecraft:bamboo_mosaic_double_slab", + "id": -525 + }, + { + "name": "minecraft:bamboo_mosaic_slab", + "id": -524 + }, + { + "name": "minecraft:bamboo_mosaic_stairs", + "id": -523 + }, + { + "name": "minecraft:bamboo_planks", + "id": -510 + }, + { + "name": "minecraft:bamboo_pressure_plate", + "id": -514 + }, + { + "name": "minecraft:bamboo_raft", + "id": 662 + }, + { + "name": "minecraft:bamboo_sapling", + "id": -164 + }, + { + "name": "minecraft:bamboo_sign", + "id": 661 + }, + { + "name": "minecraft:bamboo_slab", + "id": -513 + }, + { + "name": "minecraft:bamboo_stairs", + "id": -512 + }, + { + "name": "minecraft:bamboo_standing_sign", + "id": -518 + }, + { + "name": "minecraft:bamboo_trapdoor", + "id": -520 + }, + { + "name": "minecraft:bamboo_wall_sign", + "id": -519 + }, + { + "name": "minecraft:banner", + "id": 576 + }, + { + "name": "minecraft:banner_pattern", + "id": 725 + }, + { + "name": "minecraft:barrel", + "id": -203 + }, + { + "name": "minecraft:barrier", + "id": -161 + }, + { + "name": "minecraft:basalt", + "id": -234 + }, + { + "name": "minecraft:bat_spawn_egg", + "id": 456 + }, + { + "name": "minecraft:beacon", + "id": 138 + }, + { + "name": "minecraft:bed", + "id": 421 + }, + { + "name": "minecraft:bedrock", + "id": 7 + }, + { + "name": "minecraft:bee_nest", + "id": -218 + }, + { + "name": "minecraft:bee_spawn_egg", + "id": 497 + }, + { + "name": "minecraft:beef", + "id": 274 + }, + { + "name": "minecraft:beehive", + "id": -219 + }, + { + "name": "minecraft:beetroot", + "id": 286 + }, + { + "name": "minecraft:beetroot_seeds", + "id": 296 + }, + { + "name": "minecraft:beetroot_soup", + "id": 287 + }, + { + "name": "minecraft:bell", + "id": -206 + }, + { + "name": "minecraft:big_dripleaf", + "id": -323 + }, + { + "name": "minecraft:birch_boat", + "id": 379 + }, + { + "name": "minecraft:birch_button", + "id": -141 + }, + { + "name": "minecraft:birch_chest_boat", + "id": 648 + }, + { + "name": "minecraft:birch_door", + "id": 563 + }, + { + "name": "minecraft:birch_fence", + "id": -576 + }, + { + "name": "minecraft:birch_fence_gate", + "id": 184 + }, + { + "name": "minecraft:birch_hanging_sign", + "id": -502 + }, + { + "name": "minecraft:birch_log", + "id": -570 + }, + { + "name": "minecraft:birch_planks", + "id": -740 + }, + { + "name": "minecraft:birch_pressure_plate", + "id": -151 + }, + { + "name": "minecraft:birch_sign", + "id": 586 + }, + { + "name": "minecraft:birch_stairs", + "id": 135 + }, + { + "name": "minecraft:birch_standing_sign", + "id": -186 + }, + { + "name": "minecraft:birch_trapdoor", + "id": -146 + }, + { + "name": "minecraft:birch_wall_sign", + "id": -187 + }, + { + "name": "minecraft:black_candle", + "id": -428 + }, + { + "name": "minecraft:black_candle_cake", + "id": -445 + }, + { + "name": "minecraft:black_carpet", + "id": -611 + }, + { + "name": "minecraft:black_concrete", + "id": -642 + }, + { + "name": "minecraft:black_concrete_powder", + "id": -723 + }, + { + "name": "minecraft:black_dye", + "id": 398 + }, + { + "name": "minecraft:black_glazed_terracotta", + "id": 235 + }, + { + "name": "minecraft:black_shulker_box", + "id": -627 + }, + { + "name": "minecraft:black_stained_glass", + "id": -687 + }, + { + "name": "minecraft:black_stained_glass_pane", + "id": -657 + }, + { + "name": "minecraft:black_terracotta", + "id": -738 + }, + { + "name": "minecraft:black_wool", + "id": -554 + }, + { + "name": "minecraft:blackstone", + "id": -273 + }, + { + "name": "minecraft:blackstone_double_slab", + "id": -283 + }, + { + "name": "minecraft:blackstone_slab", + "id": -282 + }, + { + "name": "minecraft:blackstone_stairs", + "id": -276 + }, + { + "name": "minecraft:blackstone_wall", + "id": -277 + }, + { + "name": "minecraft:blade_pottery_sherd", + "id": 668 + }, + { + "name": "minecraft:blast_furnace", + "id": -196 + }, + { + "name": "minecraft:blaze_powder", + "id": 432 + }, + { + "name": "minecraft:blaze_rod", + "id": 426 + }, + { + "name": "minecraft:blaze_spawn_egg", + "id": 459 + }, + { + "name": "minecraft:bleach", + "id": 605 + }, + { + "name": "minecraft:blue_candle", + "id": -424 + }, + { + "name": "minecraft:blue_candle_cake", + "id": -441 + }, + { + "name": "minecraft:blue_carpet", + "id": -607 + }, + { + "name": "minecraft:blue_concrete", + "id": -638 + }, + { + "name": "minecraft:blue_concrete_powder", + "id": -719 + }, + { + "name": "minecraft:blue_dye", + "id": 402 + }, + { + "name": "minecraft:blue_glazed_terracotta", + "id": 231 + }, + { + "name": "minecraft:blue_ice", + "id": -11 + }, + { + "name": "minecraft:blue_shulker_box", + "id": -623 + }, + { + "name": "minecraft:blue_stained_glass", + "id": -683 + }, + { + "name": "minecraft:blue_stained_glass_pane", + "id": -653 + }, + { + "name": "minecraft:blue_terracotta", + "id": -734 + }, + { + "name": "minecraft:blue_wool", + "id": -563 + }, + { + "name": "minecraft:boat", + "id": 723 + }, + { + "name": "minecraft:bone", + "id": 418 + }, + { + "name": "minecraft:bone_block", + "id": 216 + }, + { + "name": "minecraft:bone_meal", + "id": 414 + }, + { + "name": "minecraft:book", + "id": 390 + }, + { + "name": "minecraft:bookshelf", + "id": 47 + }, + { + "name": "minecraft:border_block", + "id": 212 + }, + { + "name": "minecraft:bordure_indented_banner_pattern", + "id": 595 + }, + { + "name": "minecraft:bow", + "id": 303 + }, + { + "name": "minecraft:bowl", + "id": 324 + }, + { + "name": "minecraft:brain_coral", + "id": -581 + }, + { + "name": "minecraft:bread", + "id": 262 + }, + { + "name": "minecraft:breeze_spawn_egg", + "id": 504 + }, + { + "name": "minecraft:brewer_pottery_sherd", + "id": 669 + }, + { + "name": "minecraft:brewing_stand", + "id": 434 + }, + { + "name": "minecraft:brick", + "id": 386 + }, + { + "name": "minecraft:brick_block", + "id": 45 + }, + { + "name": "minecraft:brick_stairs", + "id": 108 + }, + { + "name": "minecraft:brown_candle", + "id": -425 + }, + { + "name": "minecraft:brown_candle_cake", + "id": -442 + }, + { + "name": "minecraft:brown_carpet", + "id": -608 + }, + { + "name": "minecraft:brown_concrete", + "id": -639 + }, + { + "name": "minecraft:brown_concrete_powder", + "id": -720 + }, + { + "name": "minecraft:brown_dye", + "id": 401 + }, + { + "name": "minecraft:brown_glazed_terracotta", + "id": 232 + }, + { + "name": "minecraft:brown_mushroom", + "id": 39 + }, + { + "name": "minecraft:brown_mushroom_block", + "id": 99 + }, + { + "name": "minecraft:brown_shulker_box", + "id": -624 + }, + { + "name": "minecraft:brown_stained_glass", + "id": -684 + }, + { + "name": "minecraft:brown_stained_glass_pane", + "id": -654 + }, + { + "name": "minecraft:brown_terracotta", + "id": -735 + }, + { + "name": "minecraft:brown_wool", + "id": -555 + }, + { + "name": "minecraft:brush", + "id": 685 + }, + { + "name": "minecraft:bubble_column", + "id": -160 + }, + { + "name": "minecraft:bubble_coral", + "id": -582 + }, + { + "name": "minecraft:bucket", + "id": 363 + }, + { + "name": "minecraft:budding_amethyst", + "id": -328 + }, + { + "name": "minecraft:burn_pottery_sherd", + "id": 670 + }, + { + "name": "minecraft:cactus", + "id": 81 + }, + { + "name": "minecraft:cake", + "id": 420 + }, + { + "name": "minecraft:calcite", + "id": -326 + }, + { + "name": "minecraft:calibrated_sculk_sensor", + "id": -580 + }, + { + "name": "minecraft:camel_spawn_egg", + "id": 664 + }, + { + "name": "minecraft:camera", + "id": 602 + }, + { + "name": "minecraft:campfire", + "id": 598 + }, + { + "name": "minecraft:candle", + "id": -412 + }, + { + "name": "minecraft:candle_cake", + "id": -429 + }, + { + "name": "minecraft:carpet", + "id": 710 + }, + { + "name": "minecraft:carrot", + "id": 280 + }, + { + "name": "minecraft:carrot_on_a_stick", + "id": 526 + }, + { + "name": "minecraft:carrots", + "id": 141 + }, + { + "name": "minecraft:cartography_table", + "id": -200 + }, + { + "name": "minecraft:carved_pumpkin", + "id": -155 + }, + { + "name": "minecraft:cat_spawn_egg", + "id": 491 + }, + { + "name": "minecraft:cauldron", + "id": 435 + }, + { + "name": "minecraft:cave_spider_spawn_egg", + "id": 460 + }, + { + "name": "minecraft:cave_vines", + "id": -322 + }, + { + "name": "minecraft:cave_vines_body_with_berries", + "id": -375 + }, + { + "name": "minecraft:cave_vines_head_with_berries", + "id": -376 + }, + { + "name": "minecraft:chain", + "id": 628 + }, + { + "name": "minecraft:chain_command_block", + "id": 189 + }, + { + "name": "minecraft:chainmail_boots", + "id": 345 + }, + { + "name": "minecraft:chainmail_chestplate", + "id": 343 + }, + { + "name": "minecraft:chainmail_helmet", + "id": 342 + }, + { + "name": "minecraft:chainmail_leggings", + "id": 344 + }, + { + "name": "minecraft:charcoal", + "id": 306 + }, + { + "name": "minecraft:chemical_heat", + "id": 192 + }, + { + "name": "minecraft:chemistry_table", + "id": 238 + }, + { + "name": "minecraft:cherry_boat", + "id": 658 + }, + { + "name": "minecraft:cherry_button", + "id": -530 + }, + { + "name": "minecraft:cherry_chest_boat", + "id": 659 + }, + { + "name": "minecraft:cherry_door", + "id": -531 + }, + { + "name": "minecraft:cherry_double_slab", + "id": -540 + }, + { + "name": "minecraft:cherry_fence", + "id": -532 + }, + { + "name": "minecraft:cherry_fence_gate", + "id": -533 + }, + { + "name": "minecraft:cherry_hanging_sign", + "id": -534 + }, + { + "name": "minecraft:cherry_leaves", + "id": -548 + }, + { + "name": "minecraft:cherry_log", + "id": -536 + }, + { + "name": "minecraft:cherry_planks", + "id": -537 + }, + { + "name": "minecraft:cherry_pressure_plate", + "id": -538 + }, + { + "name": "minecraft:cherry_sapling", + "id": -547 + }, + { + "name": "minecraft:cherry_sign", + "id": 660 + }, + { + "name": "minecraft:cherry_slab", + "id": -539 + }, + { + "name": "minecraft:cherry_stairs", + "id": -541 + }, + { + "name": "minecraft:cherry_standing_sign", + "id": -542 + }, + { + "name": "minecraft:cherry_trapdoor", + "id": -543 + }, + { + "name": "minecraft:cherry_wall_sign", + "id": -544 + }, + { + "name": "minecraft:cherry_wood", + "id": -546 + }, + { + "name": "minecraft:chest", + "id": 54 + }, + { + "name": "minecraft:chest_boat", + "id": 654 + }, + { + "name": "minecraft:chest_minecart", + "id": 392 + }, + { + "name": "minecraft:chicken", + "id": 276 + }, + { + "name": "minecraft:chicken_spawn_egg", + "id": 438 + }, + { + "name": "minecraft:chiseled_bookshelf", + "id": -526 + }, + { + "name": "minecraft:chiseled_copper", + "id": -760 + }, + { + "name": "minecraft:chiseled_deepslate", + "id": -395 + }, + { + "name": "minecraft:chiseled_nether_bricks", + "id": -302 + }, + { + "name": "minecraft:chiseled_polished_blackstone", + "id": -279 + }, + { + "name": "minecraft:chiseled_tuff", + "id": -753 + }, + { + "name": "minecraft:chiseled_tuff_bricks", + "id": -759 + }, + { + "name": "minecraft:chorus_flower", + "id": 200 + }, + { + "name": "minecraft:chorus_fruit", + "id": 567 + }, + { + "name": "minecraft:chorus_plant", + "id": 240 + }, + { + "name": "minecraft:clay", + "id": 82 + }, + { + "name": "minecraft:clay_ball", + "id": 387 + }, + { + "name": "minecraft:client_request_placeholder_block", + "id": -465 + }, + { + "name": "minecraft:clock", + "id": 396 + }, + { + "name": "minecraft:coal", + "id": 305 + }, + { + "name": "minecraft:coal_block", + "id": 173 + }, + { + "name": "minecraft:coal_ore", + "id": 16 + }, + { + "name": "minecraft:coast_armor_trim_smithing_template", + "id": 689 + }, + { + "name": "minecraft:cobbled_deepslate", + "id": -379 + }, + { + "name": "minecraft:cobbled_deepslate_double_slab", + "id": -396 + }, + { + "name": "minecraft:cobbled_deepslate_slab", + "id": -380 + }, + { + "name": "minecraft:cobbled_deepslate_stairs", + "id": -381 + }, + { + "name": "minecraft:cobbled_deepslate_wall", + "id": -382 + }, + { + "name": "minecraft:cobblestone", + "id": 4 + }, + { + "name": "minecraft:cobblestone_wall", + "id": 139 + }, + { + "name": "minecraft:cocoa", + "id": 127 + }, + { + "name": "minecraft:cocoa_beans", + "id": 415 + }, + { + "name": "minecraft:cod", + "id": 265 + }, + { + "name": "minecraft:cod_bucket", + "id": 367 + }, + { + "name": "minecraft:cod_spawn_egg", + "id": 483 + }, + { + "name": "minecraft:colored_torch_bp", + "id": 204 + }, + { + "name": "minecraft:colored_torch_rg", + "id": 202 + }, + { + "name": "minecraft:command_block", + "id": 137 + }, + { + "name": "minecraft:command_block_minecart", + "id": 572 + }, + { + "name": "minecraft:comparator", + "id": 531 + }, + { + "name": "minecraft:compass", + "id": 394 + }, + { + "name": "minecraft:composter", + "id": -213 + }, + { + "name": "minecraft:compound", + "id": 603 + }, + { + "name": "minecraft:concrete", + "id": 716 + }, + { + "name": "minecraft:concrete_powder", + "id": 717 + }, + { + "name": "minecraft:conduit", + "id": -157 + }, + { + "name": "minecraft:cooked_beef", + "id": 275 + }, + { + "name": "minecraft:cooked_chicken", + "id": 277 + }, + { + "name": "minecraft:cooked_cod", + "id": 269 + }, + { + "name": "minecraft:cooked_mutton", + "id": 560 + }, + { + "name": "minecraft:cooked_porkchop", + "id": 264 + }, + { + "name": "minecraft:cooked_rabbit", + "id": 290 + }, + { + "name": "minecraft:cooked_salmon", + "id": 270 + }, + { + "name": "minecraft:cookie", + "id": 272 + }, + { + "name": "minecraft:copper_block", + "id": -340 + }, + { + "name": "minecraft:copper_bulb", + "id": -776 + }, + { + "name": "minecraft:copper_door", + "id": -784 + }, + { + "name": "minecraft:copper_grate", + "id": -768 + }, + { + "name": "minecraft:copper_ingot", + "id": 513 + }, + { + "name": "minecraft:copper_ore", + "id": -311 + }, + { + "name": "minecraft:copper_trapdoor", + "id": -792 + }, + { + "name": "minecraft:coral", + "id": 714 + }, + { + "name": "minecraft:coral_block", + "id": -132 + }, + { + "name": "minecraft:coral_fan", + "id": -133 + }, + { + "name": "minecraft:coral_fan_dead", + "id": -134 + }, + { + "name": "minecraft:coral_fan_hang", + "id": -135 + }, + { + "name": "minecraft:coral_fan_hang2", + "id": -136 + }, + { + "name": "minecraft:coral_fan_hang3", + "id": -137 + }, + { + "name": "minecraft:cow_spawn_egg", + "id": 439 + }, + { + "name": "minecraft:cracked_deepslate_bricks", + "id": -410 + }, + { + "name": "minecraft:cracked_deepslate_tiles", + "id": -409 + }, + { + "name": "minecraft:cracked_nether_bricks", + "id": -303 + }, + { + "name": "minecraft:cracked_polished_blackstone_bricks", + "id": -280 + }, + { + "name": "minecraft:crafter", + "id": -313 + }, + { + "name": "minecraft:crafting_table", + "id": 58 + }, + { + "name": "minecraft:creeper_banner_pattern", + "id": 591 + }, + { + "name": "minecraft:creeper_spawn_egg", + "id": 444 + }, + { + "name": "minecraft:crimson_button", + "id": -260 + }, + { + "name": "minecraft:crimson_door", + "id": 625 + }, + { + "name": "minecraft:crimson_double_slab", + "id": -266 + }, + { + "name": "minecraft:crimson_fence", + "id": -256 + }, + { + "name": "minecraft:crimson_fence_gate", + "id": -258 + }, + { + "name": "minecraft:crimson_fungus", + "id": -228 + }, + { + "name": "minecraft:crimson_hanging_sign", + "id": -506 + }, + { + "name": "minecraft:crimson_hyphae", + "id": -299 + }, + { + "name": "minecraft:crimson_nylium", + "id": -232 + }, + { + "name": "minecraft:crimson_planks", + "id": -242 + }, + { + "name": "minecraft:crimson_pressure_plate", + "id": -262 + }, + { + "name": "minecraft:crimson_roots", + "id": -223 + }, + { + "name": "minecraft:crimson_sign", + "id": 623 + }, + { + "name": "minecraft:crimson_slab", + "id": -264 + }, + { + "name": "minecraft:crimson_stairs", + "id": -254 + }, + { + "name": "minecraft:crimson_standing_sign", + "id": -250 + }, + { + "name": "minecraft:crimson_stem", + "id": -225 + }, + { + "name": "minecraft:crimson_trapdoor", + "id": -246 + }, + { + "name": "minecraft:crimson_wall_sign", + "id": -252 + }, + { + "name": "minecraft:crossbow", + "id": 584 + }, + { + "name": "minecraft:crying_obsidian", + "id": -289 + }, + { + "name": "minecraft:cut_copper", + "id": -347 + }, + { + "name": "minecraft:cut_copper_slab", + "id": -361 + }, + { + "name": "minecraft:cut_copper_stairs", + "id": -354 + }, + { + "name": "minecraft:cyan_candle", + "id": -422 + }, + { + "name": "minecraft:cyan_candle_cake", + "id": -439 + }, + { + "name": "minecraft:cyan_carpet", + "id": -605 + }, + { + "name": "minecraft:cyan_concrete", + "id": -636 + }, + { + "name": "minecraft:cyan_concrete_powder", + "id": -717 + }, + { + "name": "minecraft:cyan_dye", + "id": 404 + }, + { + "name": "minecraft:cyan_glazed_terracotta", + "id": 229 + }, + { + "name": "minecraft:cyan_shulker_box", + "id": -621 + }, + { + "name": "minecraft:cyan_stained_glass", + "id": -681 + }, + { + "name": "minecraft:cyan_stained_glass_pane", + "id": -651 + }, + { + "name": "minecraft:cyan_terracotta", + "id": -732 + }, + { + "name": "minecraft:cyan_wool", + "id": -561 + }, + { + "name": "minecraft:danger_pottery_sherd", + "id": 671 + }, + { + "name": "minecraft:dark_oak_boat", + "id": 383 + }, + { + "name": "minecraft:dark_oak_button", + "id": -142 + }, + { + "name": "minecraft:dark_oak_chest_boat", + "id": 652 + }, + { + "name": "minecraft:dark_oak_door", + "id": 566 + }, + { + "name": "minecraft:dark_oak_fence", + "id": -577 + }, + { + "name": "minecraft:dark_oak_fence_gate", + "id": 186 + }, + { + "name": "minecraft:dark_oak_hanging_sign", + "id": -505 + }, + { + "name": "minecraft:dark_oak_log", + "id": -572 + }, + { + "name": "minecraft:dark_oak_planks", + "id": -743 + }, + { + "name": "minecraft:dark_oak_pressure_plate", + "id": -152 + }, + { + "name": "minecraft:dark_oak_sign", + "id": 589 + }, + { + "name": "minecraft:dark_oak_stairs", + "id": 164 + }, + { + "name": "minecraft:dark_oak_trapdoor", + "id": -147 + }, + { + "name": "minecraft:dark_prismarine_stairs", + "id": -3 + }, + { + "name": "minecraft:darkoak_standing_sign", + "id": -192 + }, + { + "name": "minecraft:darkoak_wall_sign", + "id": -193 + }, + { + "name": "minecraft:daylight_detector", + "id": 151 + }, + { + "name": "minecraft:daylight_detector_inverted", + "id": 178 + }, + { + "name": "minecraft:dead_brain_coral", + "id": -586 + }, + { + "name": "minecraft:dead_bubble_coral", + "id": -587 + }, + { + "name": "minecraft:dead_fire_coral", + "id": -588 + }, + { + "name": "minecraft:dead_horn_coral", + "id": -589 + }, + { + "name": "minecraft:dead_tube_coral", + "id": -585 + }, + { + "name": "minecraft:deadbush", + "id": 32 + }, + { + "name": "minecraft:decorated_pot", + "id": -551 + }, + { + "name": "minecraft:deepslate", + "id": -378 + }, + { + "name": "minecraft:deepslate_brick_double_slab", + "id": -399 + }, + { + "name": "minecraft:deepslate_brick_slab", + "id": -392 + }, + { + "name": "minecraft:deepslate_brick_stairs", + "id": -393 + }, + { + "name": "minecraft:deepslate_brick_wall", + "id": -394 + }, + { + "name": "minecraft:deepslate_bricks", + "id": -391 + }, + { + "name": "minecraft:deepslate_coal_ore", + "id": -406 + }, + { + "name": "minecraft:deepslate_copper_ore", + "id": -408 + }, + { + "name": "minecraft:deepslate_diamond_ore", + "id": -405 + }, + { + "name": "minecraft:deepslate_emerald_ore", + "id": -407 + }, + { + "name": "minecraft:deepslate_gold_ore", + "id": -402 + }, + { + "name": "minecraft:deepslate_iron_ore", + "id": -401 + }, + { + "name": "minecraft:deepslate_lapis_ore", + "id": -400 + }, + { + "name": "minecraft:deepslate_redstone_ore", + "id": -403 + }, + { + "name": "minecraft:deepslate_tile_double_slab", + "id": -398 + }, + { + "name": "minecraft:deepslate_tile_slab", + "id": -388 + }, + { + "name": "minecraft:deepslate_tile_stairs", + "id": -389 + }, + { + "name": "minecraft:deepslate_tile_wall", + "id": -390 + }, + { + "name": "minecraft:deepslate_tiles", + "id": -387 + }, + { + "name": "minecraft:deny", + "id": 211 + }, + { + "name": "minecraft:detector_rail", + "id": 28 + }, + { + "name": "minecraft:diamond", + "id": 307 + }, + { + "name": "minecraft:diamond_axe", + "id": 322 + }, + { + "name": "minecraft:diamond_block", + "id": 57 + }, + { + "name": "minecraft:diamond_boots", + "id": 353 + }, + { + "name": "minecraft:diamond_chestplate", + "id": 351 + }, + { + "name": "minecraft:diamond_helmet", + "id": 350 + }, + { + "name": "minecraft:diamond_hoe", + "id": 335 + }, + { + "name": "minecraft:diamond_horse_armor", + "id": 542 + }, + { + "name": "minecraft:diamond_leggings", + "id": 352 + }, + { + "name": "minecraft:diamond_ore", + "id": 56 + }, + { + "name": "minecraft:diamond_pickaxe", + "id": 321 + }, + { + "name": "minecraft:diamond_shovel", + "id": 320 + }, + { + "name": "minecraft:diamond_sword", + "id": 319 + }, + { + "name": "minecraft:diorite", + "id": -592 + }, + { + "name": "minecraft:diorite_stairs", + "id": -170 + }, + { + "name": "minecraft:dirt", + "id": 3 + }, + { + "name": "minecraft:dirt_with_roots", + "id": -318 + }, + { + "name": "minecraft:disc_fragment_5", + "id": 646 + }, + { + "name": "minecraft:dispenser", + "id": 23 + }, + { + "name": "minecraft:dolphin_spawn_egg", + "id": 487 + }, + { + "name": "minecraft:donkey_spawn_egg", + "id": 468 + }, + { + "name": "minecraft:double_cut_copper_slab", + "id": -368 + }, + { + "name": "minecraft:double_plant", + "id": 175 + }, + { + "name": "minecraft:double_stone_block_slab", + "id": 43 + }, + { + "name": "minecraft:double_stone_block_slab2", + "id": 181 + }, + { + "name": "minecraft:double_stone_block_slab3", + "id": -167 + }, + { + "name": "minecraft:double_stone_block_slab4", + "id": -168 + }, + { + "name": "minecraft:double_wooden_slab", + "id": 157 + }, + { + "name": "minecraft:dragon_breath", + "id": 569 + }, + { + "name": "minecraft:dragon_egg", + "id": 122 + }, + { + "name": "minecraft:dried_kelp", + "id": 271 + }, + { + "name": "minecraft:dried_kelp_block", + "id": -139 + }, + { + "name": "minecraft:dripstone_block", + "id": -317 + }, + { + "name": "minecraft:dropper", + "id": 125 + }, + { + "name": "minecraft:drowned_spawn_egg", + "id": 486 + }, + { + "name": "minecraft:dune_armor_trim_smithing_template", + "id": 688 + }, + { + "name": "minecraft:dye", + "id": 724 + }, + { + "name": "minecraft:echo_shard", + "id": 656 + }, + { + "name": "minecraft:egg", + "id": 393 + }, + { + "name": "minecraft:elder_guardian_spawn_egg", + "id": 474 + }, + { + "name": "minecraft:element_0", + "id": 36 + }, + { + "name": "minecraft:element_1", + "id": -12 + }, + { + "name": "minecraft:element_10", + "id": -21 + }, + { + "name": "minecraft:element_100", + "id": -111 + }, + { + "name": "minecraft:element_101", + "id": -112 + }, + { + "name": "minecraft:element_102", + "id": -113 + }, + { + "name": "minecraft:element_103", + "id": -114 + }, + { + "name": "minecraft:element_104", + "id": -115 + }, + { + "name": "minecraft:element_105", + "id": -116 + }, + { + "name": "minecraft:element_106", + "id": -117 + }, + { + "name": "minecraft:element_107", + "id": -118 + }, + { + "name": "minecraft:element_108", + "id": -119 + }, + { + "name": "minecraft:element_109", + "id": -120 + }, + { + "name": "minecraft:element_11", + "id": -22 + }, + { + "name": "minecraft:element_110", + "id": -121 + }, + { + "name": "minecraft:element_111", + "id": -122 + }, + { + "name": "minecraft:element_112", + "id": -123 + }, + { + "name": "minecraft:element_113", + "id": -124 + }, + { + "name": "minecraft:element_114", + "id": -125 + }, + { + "name": "minecraft:element_115", + "id": -126 + }, + { + "name": "minecraft:element_116", + "id": -127 + }, + { + "name": "minecraft:element_117", + "id": -128 + }, + { + "name": "minecraft:element_118", + "id": -129 + }, + { + "name": "minecraft:element_12", + "id": -23 + }, + { + "name": "minecraft:element_13", + "id": -24 + }, + { + "name": "minecraft:element_14", + "id": -25 + }, + { + "name": "minecraft:element_15", + "id": -26 + }, + { + "name": "minecraft:element_16", + "id": -27 + }, + { + "name": "minecraft:element_17", + "id": -28 + }, + { + "name": "minecraft:element_18", + "id": -29 + }, + { + "name": "minecraft:element_19", + "id": -30 + }, + { + "name": "minecraft:element_2", + "id": -13 + }, + { + "name": "minecraft:element_20", + "id": -31 + }, + { + "name": "minecraft:element_21", + "id": -32 + }, + { + "name": "minecraft:element_22", + "id": -33 + }, + { + "name": "minecraft:element_23", + "id": -34 + }, + { + "name": "minecraft:element_24", + "id": -35 + }, + { + "name": "minecraft:element_25", + "id": -36 + }, + { + "name": "minecraft:element_26", + "id": -37 + }, + { + "name": "minecraft:element_27", + "id": -38 + }, + { + "name": "minecraft:element_28", + "id": -39 + }, + { + "name": "minecraft:element_29", + "id": -40 + }, + { + "name": "minecraft:element_3", + "id": -14 + }, + { + "name": "minecraft:element_30", + "id": -41 + }, + { + "name": "minecraft:element_31", + "id": -42 + }, + { + "name": "minecraft:element_32", + "id": -43 + }, + { + "name": "minecraft:element_33", + "id": -44 + }, + { + "name": "minecraft:element_34", + "id": -45 + }, + { + "name": "minecraft:element_35", + "id": -46 + }, + { + "name": "minecraft:element_36", + "id": -47 + }, + { + "name": "minecraft:element_37", + "id": -48 + }, + { + "name": "minecraft:element_38", + "id": -49 + }, + { + "name": "minecraft:element_39", + "id": -50 + }, + { + "name": "minecraft:element_4", + "id": -15 + }, + { + "name": "minecraft:element_40", + "id": -51 + }, + { + "name": "minecraft:element_41", + "id": -52 + }, + { + "name": "minecraft:element_42", + "id": -53 + }, + { + "name": "minecraft:element_43", + "id": -54 + }, + { + "name": "minecraft:element_44", + "id": -55 + }, + { + "name": "minecraft:element_45", + "id": -56 + }, + { + "name": "minecraft:element_46", + "id": -57 + }, + { + "name": "minecraft:element_47", + "id": -58 + }, + { + "name": "minecraft:element_48", + "id": -59 + }, + { + "name": "minecraft:element_49", + "id": -60 + }, + { + "name": "minecraft:element_5", + "id": -16 + }, + { + "name": "minecraft:element_50", + "id": -61 + }, + { + "name": "minecraft:element_51", + "id": -62 + }, + { + "name": "minecraft:element_52", + "id": -63 + }, + { + "name": "minecraft:element_53", + "id": -64 + }, + { + "name": "minecraft:element_54", + "id": -65 + }, + { + "name": "minecraft:element_55", + "id": -66 + }, + { + "name": "minecraft:element_56", + "id": -67 + }, + { + "name": "minecraft:element_57", + "id": -68 + }, + { + "name": "minecraft:element_58", + "id": -69 + }, + { + "name": "minecraft:element_59", + "id": -70 + }, + { + "name": "minecraft:element_6", + "id": -17 + }, + { + "name": "minecraft:element_60", + "id": -71 + }, + { + "name": "minecraft:element_61", + "id": -72 + }, + { + "name": "minecraft:element_62", + "id": -73 + }, + { + "name": "minecraft:element_63", + "id": -74 + }, + { + "name": "minecraft:element_64", + "id": -75 + }, + { + "name": "minecraft:element_65", + "id": -76 + }, + { + "name": "minecraft:element_66", + "id": -77 + }, + { + "name": "minecraft:element_67", + "id": -78 + }, + { + "name": "minecraft:element_68", + "id": -79 + }, + { + "name": "minecraft:element_69", + "id": -80 + }, + { + "name": "minecraft:element_7", + "id": -18 + }, + { + "name": "minecraft:element_70", + "id": -81 + }, + { + "name": "minecraft:element_71", + "id": -82 + }, + { + "name": "minecraft:element_72", + "id": -83 + }, + { + "name": "minecraft:element_73", + "id": -84 + }, + { + "name": "minecraft:element_74", + "id": -85 + }, + { + "name": "minecraft:element_75", + "id": -86 + }, + { + "name": "minecraft:element_76", + "id": -87 + }, + { + "name": "minecraft:element_77", + "id": -88 + }, + { + "name": "minecraft:element_78", + "id": -89 + }, + { + "name": "minecraft:element_79", + "id": -90 + }, + { + "name": "minecraft:element_8", + "id": -19 + }, + { + "name": "minecraft:element_80", + "id": -91 + }, + { + "name": "minecraft:element_81", + "id": -92 + }, + { + "name": "minecraft:element_82", + "id": -93 + }, + { + "name": "minecraft:element_83", + "id": -94 + }, + { + "name": "minecraft:element_84", + "id": -95 + }, + { + "name": "minecraft:element_85", + "id": -96 + }, + { + "name": "minecraft:element_86", + "id": -97 + }, + { + "name": "minecraft:element_87", + "id": -98 + }, + { + "name": "minecraft:element_88", + "id": -99 + }, + { + "name": "minecraft:element_89", + "id": -100 + }, + { + "name": "minecraft:element_9", + "id": -20 + }, + { + "name": "minecraft:element_90", + "id": -101 + }, + { + "name": "minecraft:element_91", + "id": -102 + }, + { + "name": "minecraft:element_92", + "id": -103 + }, + { + "name": "minecraft:element_93", + "id": -104 + }, + { + "name": "minecraft:element_94", + "id": -105 + }, + { + "name": "minecraft:element_95", + "id": -106 + }, + { + "name": "minecraft:element_96", + "id": -107 + }, + { + "name": "minecraft:element_97", + "id": -108 + }, + { + "name": "minecraft:element_98", + "id": -109 + }, + { + "name": "minecraft:element_99", + "id": -110 + }, + { + "name": "minecraft:elytra", + "id": 573 + }, + { + "name": "minecraft:emerald", + "id": 521 + }, + { + "name": "minecraft:emerald_block", + "id": 133 + }, + { + "name": "minecraft:emerald_ore", + "id": 129 + }, + { + "name": "minecraft:empty_map", + "id": 524 + }, + { + "name": "minecraft:enchanted_book", + "id": 530 + }, + { + "name": "minecraft:enchanted_golden_apple", + "id": 260 + }, + { + "name": "minecraft:enchanting_table", + "id": 116 + }, + { + "name": "minecraft:end_brick_stairs", + "id": -178 + }, + { + "name": "minecraft:end_bricks", + "id": 206 + }, + { + "name": "minecraft:end_crystal", + "id": 727 + }, + { + "name": "minecraft:end_gateway", + "id": 209 + }, + { + "name": "minecraft:end_portal", + "id": 119 + }, + { + "name": "minecraft:end_portal_frame", + "id": 120 + }, + { + "name": "minecraft:end_rod", + "id": 208 + }, + { + "name": "minecraft:end_stone", + "id": 121 + }, + { + "name": "minecraft:ender_chest", + "id": 130 + }, + { + "name": "minecraft:ender_dragon_spawn_egg", + "id": 510 + }, + { + "name": "minecraft:ender_eye", + "id": 436 + }, + { + "name": "minecraft:ender_pearl", + "id": 425 + }, + { + "name": "minecraft:enderman_spawn_egg", + "id": 445 + }, + { + "name": "minecraft:endermite_spawn_egg", + "id": 463 + }, + { + "name": "minecraft:evoker_spawn_egg", + "id": 478 + }, + { + "name": "minecraft:experience_bottle", + "id": 517 + }, + { + "name": "minecraft:explorer_pottery_sherd", + "id": 672 + }, + { + "name": "minecraft:exposed_chiseled_copper", + "id": -761 + }, + { + "name": "minecraft:exposed_copper", + "id": -341 + }, + { + "name": "minecraft:exposed_copper_bulb", + "id": -777 + }, + { + "name": "minecraft:exposed_copper_door", + "id": -785 + }, + { + "name": "minecraft:exposed_copper_grate", + "id": -769 + }, + { + "name": "minecraft:exposed_copper_trapdoor", + "id": -793 + }, + { + "name": "minecraft:exposed_cut_copper", + "id": -348 + }, + { + "name": "minecraft:exposed_cut_copper_slab", + "id": -362 + }, + { + "name": "minecraft:exposed_cut_copper_stairs", + "id": -355 + }, + { + "name": "minecraft:exposed_double_cut_copper_slab", + "id": -369 + }, + { + "name": "minecraft:eye_armor_trim_smithing_template", + "id": 692 + }, + { + "name": "minecraft:farmland", + "id": 60 + }, + { + "name": "minecraft:feather", + "id": 330 + }, + { + "name": "minecraft:fence", + "id": 712 + }, + { + "name": "minecraft:fence_gate", + "id": 107 + }, + { + "name": "minecraft:fermented_spider_eye", + "id": 431 + }, + { + "name": "minecraft:field_masoned_banner_pattern", + "id": 594 + }, + { + "name": "minecraft:filled_map", + "id": 423 + }, + { + "name": "minecraft:fire", + "id": 51 + }, + { + "name": "minecraft:fire_charge", + "id": 518 + }, + { + "name": "minecraft:fire_coral", + "id": -583 + }, + { + "name": "minecraft:firework_rocket", + "id": 528 + }, + { + "name": "minecraft:firework_star", + "id": 529 + }, + { + "name": "minecraft:fishing_rod", + "id": 395 + }, + { + "name": "minecraft:fletching_table", + "id": -201 + }, + { + "name": "minecraft:flint", + "id": 359 + }, + { + "name": "minecraft:flint_and_steel", + "id": 302 + }, + { + "name": "minecraft:flower_banner_pattern", + "id": 590 + }, + { + "name": "minecraft:flower_pot", + "id": 523 + }, + { + "name": "minecraft:flowering_azalea", + "id": -338 + }, + { + "name": "minecraft:flowing_lava", + "id": 10 + }, + { + "name": "minecraft:flowing_water", + "id": 8 + }, + { + "name": "minecraft:fox_spawn_egg", + "id": 493 + }, + { + "name": "minecraft:frame", + "id": 522 + }, + { + "name": "minecraft:friend_pottery_sherd", + "id": 673 + }, + { + "name": "minecraft:frog_spawn", + "id": -468 + }, + { + "name": "minecraft:frog_spawn_egg", + "id": 637 + }, + { + "name": "minecraft:frosted_ice", + "id": 207 + }, + { + "name": "minecraft:furnace", + "id": 61 + }, + { + "name": "minecraft:ghast_spawn_egg", + "id": 457 + }, + { + "name": "minecraft:ghast_tear", + "id": 427 + }, + { + "name": "minecraft:gilded_blackstone", + "id": -281 + }, + { + "name": "minecraft:glass", + "id": 20 + }, + { + "name": "minecraft:glass_bottle", + "id": 430 + }, + { + "name": "minecraft:glass_pane", + "id": 102 + }, + { + "name": "minecraft:glistering_melon_slice", + "id": 437 + }, + { + "name": "minecraft:globe_banner_pattern", + "id": 597 + }, + { + "name": "minecraft:glow_berries", + "id": 728 + }, + { + "name": "minecraft:glow_frame", + "id": 632 + }, + { + "name": "minecraft:glow_ink_sac", + "id": 512 + }, + { + "name": "minecraft:glow_lichen", + "id": -411 + }, + { + "name": "minecraft:glow_squid_spawn_egg", + "id": 507 + }, + { + "name": "minecraft:glow_stick", + "id": 610 + }, + { + "name": "minecraft:glowingobsidian", + "id": 246 + }, + { + "name": "minecraft:glowstone", + "id": 89 + }, + { + "name": "minecraft:glowstone_dust", + "id": 397 + }, + { + "name": "minecraft:goat_horn", + "id": 636 + }, + { + "name": "minecraft:goat_spawn_egg", + "id": 506 + }, + { + "name": "minecraft:gold_block", + "id": 41 + }, + { + "name": "minecraft:gold_ingot", + "id": 309 + }, + { + "name": "minecraft:gold_nugget", + "id": 428 + }, + { + "name": "minecraft:gold_ore", + "id": 14 + }, + { + "name": "minecraft:golden_apple", + "id": 259 + }, + { + "name": "minecraft:golden_axe", + "id": 328 + }, + { + "name": "minecraft:golden_boots", + "id": 357 + }, + { + "name": "minecraft:golden_carrot", + "id": 284 + }, + { + "name": "minecraft:golden_chestplate", + "id": 355 + }, + { + "name": "minecraft:golden_helmet", + "id": 354 + }, + { + "name": "minecraft:golden_hoe", + "id": 336 + }, + { + "name": "minecraft:golden_horse_armor", + "id": 541 + }, + { + "name": "minecraft:golden_leggings", + "id": 356 + }, + { + "name": "minecraft:golden_pickaxe", + "id": 327 + }, + { + "name": "minecraft:golden_rail", + "id": 27 + }, + { + "name": "minecraft:golden_shovel", + "id": 326 + }, + { + "name": "minecraft:golden_sword", + "id": 325 + }, + { + "name": "minecraft:granite", + "id": -590 + }, + { + "name": "minecraft:granite_stairs", + "id": -169 + }, + { + "name": "minecraft:grass", + "id": 2 + }, + { + "name": "minecraft:grass_path", + "id": 198 + }, + { + "name": "minecraft:gravel", + "id": 13 + }, + { + "name": "minecraft:gray_candle", + "id": -420 + }, + { + "name": "minecraft:gray_candle_cake", + "id": -437 + }, + { + "name": "minecraft:gray_carpet", + "id": -603 + }, + { + "name": "minecraft:gray_concrete", + "id": -634 + }, + { + "name": "minecraft:gray_concrete_powder", + "id": -715 + }, + { + "name": "minecraft:gray_dye", + "id": 406 + }, + { + "name": "minecraft:gray_glazed_terracotta", + "id": 227 + }, + { + "name": "minecraft:gray_shulker_box", + "id": -619 + }, + { + "name": "minecraft:gray_stained_glass", + "id": -679 + }, + { + "name": "minecraft:gray_stained_glass_pane", + "id": -649 + }, + { + "name": "minecraft:gray_terracotta", + "id": -730 + }, + { + "name": "minecraft:gray_wool", + "id": -553 + }, + { + "name": "minecraft:green_candle", + "id": -426 + }, + { + "name": "minecraft:green_candle_cake", + "id": -443 + }, + { + "name": "minecraft:green_carpet", + "id": -609 + }, + { + "name": "minecraft:green_concrete", + "id": -640 + }, + { + "name": "minecraft:green_concrete_powder", + "id": -721 + }, + { + "name": "minecraft:green_dye", + "id": 400 + }, + { + "name": "minecraft:green_glazed_terracotta", + "id": 233 + }, + { + "name": "minecraft:green_shulker_box", + "id": -625 + }, + { + "name": "minecraft:green_stained_glass", + "id": -685 + }, + { + "name": "minecraft:green_stained_glass_pane", + "id": -655 + }, + { + "name": "minecraft:green_terracotta", + "id": -736 + }, + { + "name": "minecraft:green_wool", + "id": -560 + }, + { + "name": "minecraft:grindstone", + "id": -195 + }, + { + "name": "minecraft:guardian_spawn_egg", + "id": 464 + }, + { + "name": "minecraft:gunpowder", + "id": 331 + }, + { + "name": "minecraft:hanging_roots", + "id": -319 + }, + { + "name": "minecraft:hard_black_stained_glass", + "id": -702 + }, + { + "name": "minecraft:hard_black_stained_glass_pane", + "id": -672 + }, + { + "name": "minecraft:hard_blue_stained_glass", + "id": -698 + }, + { + "name": "minecraft:hard_blue_stained_glass_pane", + "id": -668 + }, + { + "name": "minecraft:hard_brown_stained_glass", + "id": -699 + }, + { + "name": "minecraft:hard_brown_stained_glass_pane", + "id": -669 + }, + { + "name": "minecraft:hard_cyan_stained_glass", + "id": -696 + }, + { + "name": "minecraft:hard_cyan_stained_glass_pane", + "id": -666 + }, + { + "name": "minecraft:hard_glass", + "id": 253 + }, + { + "name": "minecraft:hard_glass_pane", + "id": 190 + }, + { + "name": "minecraft:hard_gray_stained_glass", + "id": -694 + }, + { + "name": "minecraft:hard_gray_stained_glass_pane", + "id": -664 + }, + { + "name": "minecraft:hard_green_stained_glass", + "id": -700 + }, + { + "name": "minecraft:hard_green_stained_glass_pane", + "id": -670 + }, + { + "name": "minecraft:hard_light_blue_stained_glass", + "id": -690 + }, + { + "name": "minecraft:hard_light_blue_stained_glass_pane", + "id": -660 + }, + { + "name": "minecraft:hard_light_gray_stained_glass", + "id": -695 + }, + { + "name": "minecraft:hard_light_gray_stained_glass_pane", + "id": -665 + }, + { + "name": "minecraft:hard_lime_stained_glass", + "id": -692 + }, + { + "name": "minecraft:hard_lime_stained_glass_pane", + "id": -662 + }, + { + "name": "minecraft:hard_magenta_stained_glass", + "id": -689 + }, + { + "name": "minecraft:hard_magenta_stained_glass_pane", + "id": -659 + }, + { + "name": "minecraft:hard_orange_stained_glass", + "id": -688 + }, + { + "name": "minecraft:hard_orange_stained_glass_pane", + "id": -658 + }, + { + "name": "minecraft:hard_pink_stained_glass", + "id": -693 + }, + { + "name": "minecraft:hard_pink_stained_glass_pane", + "id": -663 + }, + { + "name": "minecraft:hard_purple_stained_glass", + "id": -697 + }, + { + "name": "minecraft:hard_purple_stained_glass_pane", + "id": -667 + }, + { + "name": "minecraft:hard_red_stained_glass", + "id": -701 + }, + { + "name": "minecraft:hard_red_stained_glass_pane", + "id": -671 + }, + { + "name": "minecraft:hard_stained_glass", + "id": 721 + }, + { + "name": "minecraft:hard_stained_glass_pane", + "id": 722 + }, + { + "name": "minecraft:hard_white_stained_glass", + "id": 254 + }, + { + "name": "minecraft:hard_white_stained_glass_pane", + "id": 191 + }, + { + "name": "minecraft:hard_yellow_stained_glass", + "id": -691 + }, + { + "name": "minecraft:hard_yellow_stained_glass_pane", + "id": -661 + }, + { + "name": "minecraft:hardened_clay", + "id": 172 + }, + { + "name": "minecraft:hay_block", + "id": 170 + }, + { + "name": "minecraft:heart_of_the_sea", + "id": 580 + }, + { + "name": "minecraft:heart_pottery_sherd", + "id": 674 + }, + { + "name": "minecraft:heartbreak_pottery_sherd", + "id": 675 + }, + { + "name": "minecraft:heavy_weighted_pressure_plate", + "id": 148 + }, + { + "name": "minecraft:hoglin_spawn_egg", + "id": 499 + }, + { + "name": "minecraft:honey_block", + "id": -220 + }, + { + "name": "minecraft:honey_bottle", + "id": 601 + }, + { + "name": "minecraft:honeycomb", + "id": 600 + }, + { + "name": "minecraft:honeycomb_block", + "id": -221 + }, + { + "name": "minecraft:hopper", + "id": 536 + }, + { + "name": "minecraft:hopper_minecart", + "id": 535 + }, + { + "name": "minecraft:horn_coral", + "id": -584 + }, + { + "name": "minecraft:horse_spawn_egg", + "id": 461 + }, + { + "name": "minecraft:host_armor_trim_smithing_template", + "id": 702 + }, + { + "name": "minecraft:howl_pottery_sherd", + "id": 676 + }, + { + "name": "minecraft:husk_spawn_egg", + "id": 466 + }, + { + "name": "minecraft:ice", + "id": 79 + }, + { + "name": "minecraft:ice_bomb", + "id": 604 + }, + { + "name": "minecraft:infested_deepslate", + "id": -454 + }, + { + "name": "minecraft:info_update", + "id": 248 + }, + { + "name": "minecraft:info_update2", + "id": 249 + }, + { + "name": "minecraft:ink_sac", + "id": 416 + }, + { + "name": "minecraft:invisible_bedrock", + "id": 95 + }, + { + "name": "minecraft:iron_axe", + "id": 301 + }, + { + "name": "minecraft:iron_bars", + "id": 101 + }, + { + "name": "minecraft:iron_block", + "id": 42 + }, + { + "name": "minecraft:iron_boots", + "id": 349 + }, + { + "name": "minecraft:iron_chestplate", + "id": 347 + }, + { + "name": "minecraft:iron_door", + "id": 375 + }, + { + "name": "minecraft:iron_golem_spawn_egg", + "id": 508 + }, + { + "name": "minecraft:iron_helmet", + "id": 346 + }, + { + "name": "minecraft:iron_hoe", + "id": 334 + }, + { + "name": "minecraft:iron_horse_armor", + "id": 540 + }, + { + "name": "minecraft:iron_ingot", + "id": 308 + }, + { + "name": "minecraft:iron_leggings", + "id": 348 + }, + { + "name": "minecraft:iron_nugget", + "id": 578 + }, + { + "name": "minecraft:iron_ore", + "id": 15 + }, + { + "name": "minecraft:iron_pickaxe", + "id": 300 + }, + { + "name": "minecraft:iron_shovel", + "id": 299 + }, + { + "name": "minecraft:iron_sword", + "id": 310 + }, + { + "name": "minecraft:iron_trapdoor", + "id": 167 + }, + { + "name": "minecraft:item.acacia_door", + "id": 196 + }, + { + "name": "minecraft:item.bed", + "id": 26 + }, + { + "name": "minecraft:item.beetroot", + "id": 244 + }, + { + "name": "minecraft:item.birch_door", + "id": 194 + }, + { + "name": "minecraft:item.brewing_stand", + "id": 117 + }, + { + "name": "minecraft:item.cake", + "id": 92 + }, + { + "name": "minecraft:item.camera", + "id": 242 + }, + { + "name": "minecraft:item.campfire", + "id": -209 + }, + { + "name": "minecraft:item.cauldron", + "id": 118 + }, + { + "name": "minecraft:item.chain", + "id": -286 + }, + { + "name": "minecraft:item.crimson_door", + "id": -244 + }, + { + "name": "minecraft:item.dark_oak_door", + "id": 197 + }, + { + "name": "minecraft:item.flower_pot", + "id": 140 + }, + { + "name": "minecraft:item.frame", + "id": 199 + }, + { + "name": "minecraft:item.glow_frame", + "id": -339 + }, + { + "name": "minecraft:item.hopper", + "id": 154 + }, + { + "name": "minecraft:item.iron_door", + "id": 71 + }, + { + "name": "minecraft:item.jungle_door", + "id": 195 + }, + { + "name": "minecraft:item.kelp", + "id": -138 + }, + { + "name": "minecraft:item.mangrove_door", + "id": -493 + }, + { + "name": "minecraft:item.nether_sprouts", + "id": -238 + }, + { + "name": "minecraft:item.nether_wart", + "id": 115 + }, + { + "name": "minecraft:item.reeds", + "id": 83 + }, + { + "name": "minecraft:item.skull", + "id": 144 + }, + { + "name": "minecraft:item.soul_campfire", + "id": -290 + }, + { + "name": "minecraft:item.spruce_door", + "id": 193 + }, + { + "name": "minecraft:item.warped_door", + "id": -245 + }, + { + "name": "minecraft:item.wheat", + "id": 59 + }, + { + "name": "minecraft:item.wooden_door", + "id": 64 + }, + { + "name": "minecraft:jigsaw", + "id": -211 + }, + { + "name": "minecraft:jukebox", + "id": 84 + }, + { + "name": "minecraft:jungle_boat", + "id": 380 + }, + { + "name": "minecraft:jungle_button", + "id": -143 + }, + { + "name": "minecraft:jungle_chest_boat", + "id": 649 + }, + { + "name": "minecraft:jungle_door", + "id": 564 + }, + { + "name": "minecraft:jungle_fence", + "id": -578 + }, + { + "name": "minecraft:jungle_fence_gate", + "id": 185 + }, + { + "name": "minecraft:jungle_hanging_sign", + "id": -503 + }, + { + "name": "minecraft:jungle_log", + "id": -571 + }, + { + "name": "minecraft:jungle_planks", + "id": -741 + }, + { + "name": "minecraft:jungle_pressure_plate", + "id": -153 + }, + { + "name": "minecraft:jungle_sign", + "id": 587 + }, + { + "name": "minecraft:jungle_stairs", + "id": 136 + }, + { + "name": "minecraft:jungle_standing_sign", + "id": -188 + }, + { + "name": "minecraft:jungle_trapdoor", + "id": -148 + }, + { + "name": "minecraft:jungle_wall_sign", + "id": -189 + }, + { + "name": "minecraft:kelp", + "id": 385 + }, + { + "name": "minecraft:ladder", + "id": 65 + }, + { + "name": "minecraft:lantern", + "id": -208 + }, + { + "name": "minecraft:lapis_block", + "id": 22 + }, + { + "name": "minecraft:lapis_lazuli", + "id": 417 + }, + { + "name": "minecraft:lapis_ore", + "id": 21 + }, + { + "name": "minecraft:large_amethyst_bud", + "id": -330 + }, + { + "name": "minecraft:lava", + "id": 11 + }, + { + "name": "minecraft:lava_bucket", + "id": 366 + }, + { + "name": "minecraft:lead", + "id": 556 + }, + { + "name": "minecraft:leather", + "id": 384 + }, + { + "name": "minecraft:leather_boots", + "id": 341 + }, + { + "name": "minecraft:leather_chestplate", + "id": 339 + }, + { + "name": "minecraft:leather_helmet", + "id": 338 + }, + { + "name": "minecraft:leather_horse_armor", + "id": 539 + }, + { + "name": "minecraft:leather_leggings", + "id": 340 + }, + { + "name": "minecraft:leaves", + "id": 18 + }, + { + "name": "minecraft:leaves2", + "id": 161 + }, + { + "name": "minecraft:lectern", + "id": -194 + }, + { + "name": "minecraft:lever", + "id": 69 + }, + { + "name": "minecraft:light_block", + "id": -215 + }, + { + "name": "minecraft:light_blue_candle", + "id": -416 + }, + { + "name": "minecraft:light_blue_candle_cake", + "id": -433 + }, + { + "name": "minecraft:light_blue_carpet", + "id": -599 + }, + { + "name": "minecraft:light_blue_concrete", + "id": -630 + }, + { + "name": "minecraft:light_blue_concrete_powder", + "id": -711 + }, + { + "name": "minecraft:light_blue_dye", + "id": 410 + }, + { + "name": "minecraft:light_blue_glazed_terracotta", + "id": 223 + }, + { + "name": "minecraft:light_blue_shulker_box", + "id": -615 + }, + { + "name": "minecraft:light_blue_stained_glass", + "id": -675 + }, + { + "name": "minecraft:light_blue_stained_glass_pane", + "id": -645 + }, + { + "name": "minecraft:light_blue_terracotta", + "id": -726 + }, + { + "name": "minecraft:light_blue_wool", + "id": -562 + }, + { + "name": "minecraft:light_gray_candle", + "id": -421 + }, + { + "name": "minecraft:light_gray_candle_cake", + "id": -438 + }, + { + "name": "minecraft:light_gray_carpet", + "id": -604 + }, + { + "name": "minecraft:light_gray_concrete", + "id": -635 + }, + { + "name": "minecraft:light_gray_concrete_powder", + "id": -716 + }, + { + "name": "minecraft:light_gray_dye", + "id": 405 + }, + { + "name": "minecraft:light_gray_shulker_box", + "id": -620 + }, + { + "name": "minecraft:light_gray_stained_glass", + "id": -680 + }, + { + "name": "minecraft:light_gray_stained_glass_pane", + "id": -650 + }, + { + "name": "minecraft:light_gray_terracotta", + "id": -731 + }, + { + "name": "minecraft:light_gray_wool", + "id": -552 + }, + { + "name": "minecraft:light_weighted_pressure_plate", + "id": 147 + }, + { + "name": "minecraft:lightning_rod", + "id": -312 + }, + { + "name": "minecraft:lime_candle", + "id": -418 + }, + { + "name": "minecraft:lime_candle_cake", + "id": -435 + }, + { + "name": "minecraft:lime_carpet", + "id": -601 + }, + { + "name": "minecraft:lime_concrete", + "id": -632 + }, + { + "name": "minecraft:lime_concrete_powder", + "id": -713 + }, + { + "name": "minecraft:lime_dye", + "id": 408 + }, + { + "name": "minecraft:lime_glazed_terracotta", + "id": 225 + }, + { + "name": "minecraft:lime_shulker_box", + "id": -617 + }, + { + "name": "minecraft:lime_stained_glass", + "id": -677 + }, + { + "name": "minecraft:lime_stained_glass_pane", + "id": -647 + }, + { + "name": "minecraft:lime_terracotta", + "id": -728 + }, + { + "name": "minecraft:lime_wool", + "id": -559 + }, + { + "name": "minecraft:lingering_potion", + "id": 571 + }, + { + "name": "minecraft:lit_blast_furnace", + "id": -214 + }, + { + "name": "minecraft:lit_deepslate_redstone_ore", + "id": -404 + }, + { + "name": "minecraft:lit_furnace", + "id": 62 + }, + { + "name": "minecraft:lit_pumpkin", + "id": 91 + }, + { + "name": "minecraft:lit_redstone_lamp", + "id": 124 + }, + { + "name": "minecraft:lit_redstone_ore", + "id": 74 + }, + { + "name": "minecraft:lit_smoker", + "id": -199 + }, + { + "name": "minecraft:llama_spawn_egg", + "id": 476 + }, + { + "name": "minecraft:lodestone", + "id": -222 + }, + { + "name": "minecraft:lodestone_compass", + "id": 611 + }, + { + "name": "minecraft:log", + "id": 711 + }, + { + "name": "minecraft:log2", + "id": 715 + }, + { + "name": "minecraft:loom", + "id": -204 + }, + { + "name": "minecraft:magenta_candle", + "id": -415 + }, + { + "name": "minecraft:magenta_candle_cake", + "id": -432 + }, + { + "name": "minecraft:magenta_carpet", + "id": -598 + }, + { + "name": "minecraft:magenta_concrete", + "id": -629 + }, + { + "name": "minecraft:magenta_concrete_powder", + "id": -710 + }, + { + "name": "minecraft:magenta_dye", + "id": 411 + }, + { + "name": "minecraft:magenta_glazed_terracotta", + "id": 222 + }, + { + "name": "minecraft:magenta_shulker_box", + "id": -614 + }, + { + "name": "minecraft:magenta_stained_glass", + "id": -674 + }, + { + "name": "minecraft:magenta_stained_glass_pane", + "id": -644 + }, + { + "name": "minecraft:magenta_terracotta", + "id": -725 + }, + { + "name": "minecraft:magenta_wool", + "id": -565 + }, + { + "name": "minecraft:magma", + "id": 213 + }, + { + "name": "minecraft:magma_cream", + "id": 433 + }, + { + "name": "minecraft:magma_cube_spawn_egg", + "id": 458 + }, + { + "name": "minecraft:mangrove_boat", + "id": 644 + }, + { + "name": "minecraft:mangrove_button", + "id": -487 + }, + { + "name": "minecraft:mangrove_chest_boat", + "id": 653 + }, + { + "name": "minecraft:mangrove_door", + "id": 642 + }, + { + "name": "minecraft:mangrove_double_slab", + "id": -499 + }, + { + "name": "minecraft:mangrove_fence", + "id": -491 + }, + { + "name": "minecraft:mangrove_fence_gate", + "id": -492 + }, + { + "name": "minecraft:mangrove_hanging_sign", + "id": -508 + }, + { + "name": "minecraft:mangrove_leaves", + "id": -472 + }, + { + "name": "minecraft:mangrove_log", + "id": -484 + }, + { + "name": "minecraft:mangrove_planks", + "id": -486 + }, + { + "name": "minecraft:mangrove_pressure_plate", + "id": -490 + }, + { + "name": "minecraft:mangrove_propagule", + "id": -474 + }, + { + "name": "minecraft:mangrove_roots", + "id": -482 + }, + { + "name": "minecraft:mangrove_sign", + "id": 643 + }, + { + "name": "minecraft:mangrove_slab", + "id": -489 + }, + { + "name": "minecraft:mangrove_stairs", + "id": -488 + }, + { + "name": "minecraft:mangrove_standing_sign", + "id": -494 + }, + { + "name": "minecraft:mangrove_trapdoor", + "id": -496 + }, + { + "name": "minecraft:mangrove_wall_sign", + "id": -495 + }, + { + "name": "minecraft:mangrove_wood", + "id": -497 + }, + { + "name": "minecraft:medicine", + "id": 608 + }, + { + "name": "minecraft:medium_amethyst_bud", + "id": -331 + }, + { + "name": "minecraft:melon_block", + "id": 103 + }, + { + "name": "minecraft:melon_seeds", + "id": 294 + }, + { + "name": "minecraft:melon_slice", + "id": 273 + }, + { + "name": "minecraft:melon_stem", + "id": 105 + }, + { + "name": "minecraft:milk_bucket", + "id": 364 + }, + { + "name": "minecraft:minecart", + "id": 373 + }, + { + "name": "minecraft:miner_pottery_sherd", + "id": 677 + }, + { + "name": "minecraft:mob_spawner", + "id": 52 + }, + { + "name": "minecraft:mojang_banner_pattern", + "id": 593 + }, + { + "name": "minecraft:monster_egg", + "id": 97 + }, + { + "name": "minecraft:mooshroom_spawn_egg", + "id": 443 + }, + { + "name": "minecraft:moss_block", + "id": -320 + }, + { + "name": "minecraft:moss_carpet", + "id": -335 + }, + { + "name": "minecraft:mossy_cobblestone", + "id": 48 + }, + { + "name": "minecraft:mossy_cobblestone_stairs", + "id": -179 + }, + { + "name": "minecraft:mossy_stone_brick_stairs", + "id": -175 + }, + { + "name": "minecraft:mourner_pottery_sherd", + "id": 678 + }, + { + "name": "minecraft:moving_block", + "id": 250 + }, + { + "name": "minecraft:mud", + "id": -473 + }, + { + "name": "minecraft:mud_brick_double_slab", + "id": -479 + }, + { + "name": "minecraft:mud_brick_slab", + "id": -478 + }, + { + "name": "minecraft:mud_brick_stairs", + "id": -480 + }, + { + "name": "minecraft:mud_brick_wall", + "id": -481 + }, + { + "name": "minecraft:mud_bricks", + "id": -475 + }, + { + "name": "minecraft:muddy_mangrove_roots", + "id": -483 + }, + { + "name": "minecraft:mule_spawn_egg", + "id": 469 + }, + { + "name": "minecraft:mushroom_stew", + "id": 261 + }, + { + "name": "minecraft:music_disc_11", + "id": 553 + }, + { + "name": "minecraft:music_disc_13", + "id": 543 + }, + { + "name": "minecraft:music_disc_5", + "id": 645 + }, + { + "name": "minecraft:music_disc_blocks", + "id": 545 + }, + { + "name": "minecraft:music_disc_cat", + "id": 544 + }, + { + "name": "minecraft:music_disc_chirp", + "id": 546 + }, + { + "name": "minecraft:music_disc_far", + "id": 547 + }, + { + "name": "minecraft:music_disc_mall", + "id": 548 + }, + { + "name": "minecraft:music_disc_mellohi", + "id": 549 + }, + { + "name": "minecraft:music_disc_otherside", + "id": 635 + }, + { + "name": "minecraft:music_disc_pigstep", + "id": 629 + }, + { + "name": "minecraft:music_disc_relic", + "id": 703 + }, + { + "name": "minecraft:music_disc_stal", + "id": 550 + }, + { + "name": "minecraft:music_disc_strad", + "id": 551 + }, + { + "name": "minecraft:music_disc_wait", + "id": 554 + }, + { + "name": "minecraft:music_disc_ward", + "id": 552 + }, + { + "name": "minecraft:mutton", + "id": 559 + }, + { + "name": "minecraft:mycelium", + "id": 110 + }, + { + "name": "minecraft:name_tag", + "id": 557 + }, + { + "name": "minecraft:nautilus_shell", + "id": 579 + }, + { + "name": "minecraft:nether_brick", + "id": 112 + }, + { + "name": "minecraft:nether_brick_fence", + "id": 113 + }, + { + "name": "minecraft:nether_brick_stairs", + "id": 114 + }, + { + "name": "minecraft:nether_gold_ore", + "id": -288 + }, + { + "name": "minecraft:nether_sprouts", + "id": 630 + }, + { + "name": "minecraft:nether_star", + "id": 527 + }, + { + "name": "minecraft:nether_wart", + "id": 295 + }, + { + "name": "minecraft:nether_wart_block", + "id": 214 + }, + { + "name": "minecraft:netherbrick", + "id": 532 + }, + { + "name": "minecraft:netherite_axe", + "id": 615 + }, + { + "name": "minecraft:netherite_block", + "id": -270 + }, + { + "name": "minecraft:netherite_boots", + "id": 621 + }, + { + "name": "minecraft:netherite_chestplate", + "id": 619 + }, + { + "name": "minecraft:netherite_helmet", + "id": 618 + }, + { + "name": "minecraft:netherite_hoe", + "id": 616 + }, + { + "name": "minecraft:netherite_ingot", + "id": 617 + }, + { + "name": "minecraft:netherite_leggings", + "id": 620 + }, + { + "name": "minecraft:netherite_pickaxe", + "id": 614 + }, + { + "name": "minecraft:netherite_scrap", + "id": 622 + }, + { + "name": "minecraft:netherite_shovel", + "id": 613 + }, + { + "name": "minecraft:netherite_sword", + "id": 612 + }, + { + "name": "minecraft:netherite_upgrade_smithing_template", + "id": 686 + }, + { + "name": "minecraft:netherrack", + "id": 87 + }, + { + "name": "minecraft:netherreactor", + "id": 247 + }, + { + "name": "minecraft:normal_stone_stairs", + "id": -180 + }, + { + "name": "minecraft:noteblock", + "id": 25 + }, + { + "name": "minecraft:npc_spawn_egg", + "id": 473 + }, + { + "name": "minecraft:oak_boat", + "id": 378 + }, + { + "name": "minecraft:oak_chest_boat", + "id": 647 + }, + { + "name": "minecraft:oak_fence", + "id": 85 + }, + { + "name": "minecraft:oak_hanging_sign", + "id": -500 + }, + { + "name": "minecraft:oak_log", + "id": 17 + }, + { + "name": "minecraft:oak_planks", + "id": 5 + }, + { + "name": "minecraft:oak_sign", + "id": 361 + }, + { + "name": "minecraft:oak_stairs", + "id": 53 + }, + { + "name": "minecraft:observer", + "id": 251 + }, + { + "name": "minecraft:obsidian", + "id": 49 + }, + { + "name": "minecraft:ocelot_spawn_egg", + "id": 454 + }, + { + "name": "minecraft:ochre_froglight", + "id": -471 + }, + { + "name": "minecraft:orange_candle", + "id": -414 + }, + { + "name": "minecraft:orange_candle_cake", + "id": -431 + }, + { + "name": "minecraft:orange_carpet", + "id": -597 + }, + { + "name": "minecraft:orange_concrete", + "id": -628 + }, + { + "name": "minecraft:orange_concrete_powder", + "id": -709 + }, + { + "name": "minecraft:orange_dye", + "id": 412 + }, + { + "name": "minecraft:orange_glazed_terracotta", + "id": 221 + }, + { + "name": "minecraft:orange_shulker_box", + "id": -613 + }, + { + "name": "minecraft:orange_stained_glass", + "id": -673 + }, + { + "name": "minecraft:orange_stained_glass_pane", + "id": -643 + }, + { + "name": "minecraft:orange_terracotta", + "id": -724 + }, + { + "name": "minecraft:orange_wool", + "id": -557 + }, + { + "name": "minecraft:oxidized_chiseled_copper", + "id": -763 + }, + { + "name": "minecraft:oxidized_copper", + "id": -343 + }, + { + "name": "minecraft:oxidized_copper_bulb", + "id": -779 + }, + { + "name": "minecraft:oxidized_copper_door", + "id": -787 + }, + { + "name": "minecraft:oxidized_copper_grate", + "id": -771 + }, + { + "name": "minecraft:oxidized_copper_trapdoor", + "id": -795 + }, + { + "name": "minecraft:oxidized_cut_copper", + "id": -350 + }, + { + "name": "minecraft:oxidized_cut_copper_slab", + "id": -364 + }, + { + "name": "minecraft:oxidized_cut_copper_stairs", + "id": -357 + }, + { + "name": "minecraft:oxidized_double_cut_copper_slab", + "id": -371 + }, + { + "name": "minecraft:packed_ice", + "id": 174 + }, + { + "name": "minecraft:packed_mud", + "id": -477 + }, + { + "name": "minecraft:painting", + "id": 360 + }, + { + "name": "minecraft:panda_spawn_egg", + "id": 492 + }, + { + "name": "minecraft:paper", + "id": 389 + }, + { + "name": "minecraft:parrot_spawn_egg", + "id": 481 + }, + { + "name": "minecraft:pearlescent_froglight", + "id": -469 + }, + { + "name": "minecraft:phantom_membrane", + "id": 583 + }, + { + "name": "minecraft:phantom_spawn_egg", + "id": 489 + }, + { + "name": "minecraft:pig_spawn_egg", + "id": 440 + }, + { + "name": "minecraft:piglin_banner_pattern", + "id": 596 + }, + { + "name": "minecraft:piglin_brute_spawn_egg", + "id": 502 + }, + { + "name": "minecraft:piglin_spawn_egg", + "id": 500 + }, + { + "name": "minecraft:pillager_spawn_egg", + "id": 494 + }, + { + "name": "minecraft:pink_candle", + "id": -419 + }, + { + "name": "minecraft:pink_candle_cake", + "id": -436 + }, + { + "name": "minecraft:pink_carpet", + "id": -602 + }, + { + "name": "minecraft:pink_concrete", + "id": -633 + }, + { + "name": "minecraft:pink_concrete_powder", + "id": -714 + }, + { + "name": "minecraft:pink_dye", + "id": 407 + }, + { + "name": "minecraft:pink_glazed_terracotta", + "id": 226 + }, + { + "name": "minecraft:pink_petals", + "id": -549 + }, + { + "name": "minecraft:pink_shulker_box", + "id": -618 + }, + { + "name": "minecraft:pink_stained_glass", + "id": -678 + }, + { + "name": "minecraft:pink_stained_glass_pane", + "id": -648 + }, + { + "name": "minecraft:pink_terracotta", + "id": -729 + }, + { + "name": "minecraft:pink_wool", + "id": -566 + }, + { + "name": "minecraft:piston", + "id": 33 + }, + { + "name": "minecraft:piston_arm_collision", + "id": 34 + }, + { + "name": "minecraft:pitcher_crop", + "id": -574 + }, + { + "name": "minecraft:pitcher_plant", + "id": -612 + }, + { + "name": "minecraft:pitcher_pod", + "id": 298 + }, + { + "name": "minecraft:planks", + "id": 713 + }, + { + "name": "minecraft:plenty_pottery_sherd", + "id": 679 + }, + { + "name": "minecraft:podzol", + "id": 243 + }, + { + "name": "minecraft:pointed_dripstone", + "id": -308 + }, + { + "name": "minecraft:poisonous_potato", + "id": 283 + }, + { + "name": "minecraft:polar_bear_spawn_egg", + "id": 475 + }, + { + "name": "minecraft:polished_andesite", + "id": -595 + }, + { + "name": "minecraft:polished_andesite_stairs", + "id": -174 + }, + { + "name": "minecraft:polished_basalt", + "id": -235 + }, + { + "name": "minecraft:polished_blackstone", + "id": -291 + }, + { + "name": "minecraft:polished_blackstone_brick_double_slab", + "id": -285 + }, + { + "name": "minecraft:polished_blackstone_brick_slab", + "id": -284 + }, + { + "name": "minecraft:polished_blackstone_brick_stairs", + "id": -275 + }, + { + "name": "minecraft:polished_blackstone_brick_wall", + "id": -278 + }, + { + "name": "minecraft:polished_blackstone_bricks", + "id": -274 + }, + { + "name": "minecraft:polished_blackstone_button", + "id": -296 + }, + { + "name": "minecraft:polished_blackstone_double_slab", + "id": -294 + }, + { + "name": "minecraft:polished_blackstone_pressure_plate", + "id": -295 + }, + { + "name": "minecraft:polished_blackstone_slab", + "id": -293 + }, + { + "name": "minecraft:polished_blackstone_stairs", + "id": -292 + }, + { + "name": "minecraft:polished_blackstone_wall", + "id": -297 + }, + { + "name": "minecraft:polished_deepslate", + "id": -383 + }, + { + "name": "minecraft:polished_deepslate_double_slab", + "id": -397 + }, + { + "name": "minecraft:polished_deepslate_slab", + "id": -384 + }, + { + "name": "minecraft:polished_deepslate_stairs", + "id": -385 + }, + { + "name": "minecraft:polished_deepslate_wall", + "id": -386 + }, + { + "name": "minecraft:polished_diorite", + "id": -593 + }, + { + "name": "minecraft:polished_diorite_stairs", + "id": -173 + }, + { + "name": "minecraft:polished_granite", + "id": -591 + }, + { + "name": "minecraft:polished_granite_stairs", + "id": -172 + }, + { + "name": "minecraft:polished_tuff", + "id": -748 + }, + { + "name": "minecraft:polished_tuff_double_slab", + "id": -750 + }, + { + "name": "minecraft:polished_tuff_slab", + "id": -749 + }, + { + "name": "minecraft:polished_tuff_stairs", + "id": -751 + }, + { + "name": "minecraft:polished_tuff_wall", + "id": -752 + }, + { + "name": "minecraft:popped_chorus_fruit", + "id": 568 + }, + { + "name": "minecraft:porkchop", + "id": 263 + }, + { + "name": "minecraft:portal", + "id": 90 + }, + { + "name": "minecraft:potato", + "id": 281 + }, + { + "name": "minecraft:potatoes", + "id": 142 + }, + { + "name": "minecraft:potion", + "id": 429 + }, + { + "name": "minecraft:powder_snow", + "id": -306 + }, + { + "name": "minecraft:powder_snow_bucket", + "id": 371 + }, + { + "name": "minecraft:powered_comparator", + "id": 150 + }, + { + "name": "minecraft:powered_repeater", + "id": 94 + }, + { + "name": "minecraft:prismarine", + "id": 168 + }, + { + "name": "minecraft:prismarine_bricks_stairs", + "id": -4 + }, + { + "name": "minecraft:prismarine_crystals", + "id": 558 + }, + { + "name": "minecraft:prismarine_shard", + "id": 574 + }, + { + "name": "minecraft:prismarine_stairs", + "id": -2 + }, + { + "name": "minecraft:prize_pottery_sherd", + "id": 680 + }, + { + "name": "minecraft:pufferfish", + "id": 268 + }, + { + "name": "minecraft:pufferfish_bucket", + "id": 370 + }, + { + "name": "minecraft:pufferfish_spawn_egg", + "id": 484 + }, + { + "name": "minecraft:pumpkin", + "id": 86 + }, + { + "name": "minecraft:pumpkin_pie", + "id": 285 + }, + { + "name": "minecraft:pumpkin_seeds", + "id": 293 + }, + { + "name": "minecraft:pumpkin_stem", + "id": 104 + }, + { + "name": "minecraft:purple_candle", + "id": -423 + }, + { + "name": "minecraft:purple_candle_cake", + "id": -440 + }, + { + "name": "minecraft:purple_carpet", + "id": -606 + }, + { + "name": "minecraft:purple_concrete", + "id": -637 + }, + { + "name": "minecraft:purple_concrete_powder", + "id": -718 + }, + { + "name": "minecraft:purple_dye", + "id": 403 + }, + { + "name": "minecraft:purple_glazed_terracotta", + "id": 219 + }, + { + "name": "minecraft:purple_shulker_box", + "id": -622 + }, + { + "name": "minecraft:purple_stained_glass", + "id": -682 + }, + { + "name": "minecraft:purple_stained_glass_pane", + "id": -652 + }, + { + "name": "minecraft:purple_terracotta", + "id": -733 + }, + { + "name": "minecraft:purple_wool", + "id": -564 + }, + { + "name": "minecraft:purpur_block", + "id": 201 + }, + { + "name": "minecraft:purpur_stairs", + "id": 203 + }, + { + "name": "minecraft:quartz", + "id": 533 + }, + { + "name": "minecraft:quartz_block", + "id": 155 + }, + { + "name": "minecraft:quartz_bricks", + "id": -304 + }, + { + "name": "minecraft:quartz_ore", + "id": 153 + }, + { + "name": "minecraft:quartz_stairs", + "id": 156 + }, + { + "name": "minecraft:rabbit", + "id": 289 + }, + { + "name": "minecraft:rabbit_foot", + "id": 537 + }, + { + "name": "minecraft:rabbit_hide", + "id": 538 + }, + { + "name": "minecraft:rabbit_spawn_egg", + "id": 462 + }, + { + "name": "minecraft:rabbit_stew", + "id": 291 + }, + { + "name": "minecraft:rail", + "id": 66 + }, + { + "name": "minecraft:raiser_armor_trim_smithing_template", + "id": 700 + }, + { + "name": "minecraft:rapid_fertilizer", + "id": 606 + }, + { + "name": "minecraft:ravager_spawn_egg", + "id": 496 + }, + { + "name": "minecraft:raw_copper", + "id": 516 + }, + { + "name": "minecraft:raw_copper_block", + "id": -452 + }, + { + "name": "minecraft:raw_gold", + "id": 515 + }, + { + "name": "minecraft:raw_gold_block", + "id": -453 + }, + { + "name": "minecraft:raw_iron", + "id": 514 + }, + { + "name": "minecraft:raw_iron_block", + "id": -451 + }, + { + "name": "minecraft:recovery_compass", + "id": 655 + }, + { + "name": "minecraft:red_candle", + "id": -427 + }, + { + "name": "minecraft:red_candle_cake", + "id": -444 + }, + { + "name": "minecraft:red_carpet", + "id": -610 + }, + { + "name": "minecraft:red_concrete", + "id": -641 + }, + { + "name": "minecraft:red_concrete_powder", + "id": -722 + }, + { + "name": "minecraft:red_dye", + "id": 399 + }, + { + "name": "minecraft:red_flower", + "id": 38 + }, + { + "name": "minecraft:red_glazed_terracotta", + "id": 234 + }, + { + "name": "minecraft:red_mushroom", + "id": 40 + }, + { + "name": "minecraft:red_mushroom_block", + "id": 100 + }, + { + "name": "minecraft:red_nether_brick", + "id": 215 + }, + { + "name": "minecraft:red_nether_brick_stairs", + "id": -184 + }, + { + "name": "minecraft:red_sandstone", + "id": 179 + }, + { + "name": "minecraft:red_sandstone_stairs", + "id": 180 + }, + { + "name": "minecraft:red_shulker_box", + "id": -626 + }, + { + "name": "minecraft:red_stained_glass", + "id": -686 + }, + { + "name": "minecraft:red_stained_glass_pane", + "id": -656 + }, + { + "name": "minecraft:red_terracotta", + "id": -737 + }, + { + "name": "minecraft:red_wool", + "id": -556 + }, + { + "name": "minecraft:redstone", + "id": 376 + }, + { + "name": "minecraft:redstone_block", + "id": 152 + }, + { + "name": "minecraft:redstone_lamp", + "id": 123 + }, + { + "name": "minecraft:redstone_ore", + "id": 73 + }, + { + "name": "minecraft:redstone_torch", + "id": 76 + }, + { + "name": "minecraft:redstone_wire", + "id": 55 + }, + { + "name": "minecraft:reinforced_deepslate", + "id": -466 + }, + { + "name": "minecraft:repeater", + "id": 422 + }, + { + "name": "minecraft:repeating_command_block", + "id": 188 + }, + { + "name": "minecraft:reserved6", + "id": 255 + }, + { + "name": "minecraft:respawn_anchor", + "id": -272 + }, + { + "name": "minecraft:rib_armor_trim_smithing_template", + "id": 696 + }, + { + "name": "minecraft:rotten_flesh", + "id": 278 + }, + { + "name": "minecraft:saddle", + "id": 374 + }, + { + "name": "minecraft:salmon", + "id": 266 + }, + { + "name": "minecraft:salmon_bucket", + "id": 368 + }, + { + "name": "minecraft:salmon_spawn_egg", + "id": 485 + }, + { + "name": "minecraft:sand", + "id": 12 + }, + { + "name": "minecraft:sandstone", + "id": 24 + }, + { + "name": "minecraft:sandstone_stairs", + "id": 128 + }, + { + "name": "minecraft:sapling", + "id": 6 + }, + { + "name": "minecraft:scaffolding", + "id": -165 + }, + { + "name": "minecraft:sculk", + "id": -458 + }, + { + "name": "minecraft:sculk_catalyst", + "id": -460 + }, + { + "name": "minecraft:sculk_sensor", + "id": -307 + }, + { + "name": "minecraft:sculk_shrieker", + "id": -461 + }, + { + "name": "minecraft:sculk_vein", + "id": -459 + }, + { + "name": "minecraft:sea_lantern", + "id": 169 + }, + { + "name": "minecraft:sea_pickle", + "id": -156 + }, + { + "name": "minecraft:seagrass", + "id": -130 + }, + { + "name": "minecraft:sentry_armor_trim_smithing_template", + "id": 687 + }, + { + "name": "minecraft:shaper_armor_trim_smithing_template", + "id": 701 + }, + { + "name": "minecraft:sheaf_pottery_sherd", + "id": 681 + }, + { + "name": "minecraft:shears", + "id": 424 + }, + { + "name": "minecraft:sheep_spawn_egg", + "id": 441 + }, + { + "name": "minecraft:shelter_pottery_sherd", + "id": 682 + }, + { + "name": "minecraft:shield", + "id": 358 + }, + { + "name": "minecraft:shroomlight", + "id": -230 + }, + { + "name": "minecraft:shulker_box", + "id": 720 + }, + { + "name": "minecraft:shulker_shell", + "id": 575 + }, + { + "name": "minecraft:shulker_spawn_egg", + "id": 472 + }, + { + "name": "minecraft:silence_armor_trim_smithing_template", + "id": 698 + }, + { + "name": "minecraft:silver_glazed_terracotta", + "id": 228 + }, + { + "name": "minecraft:silverfish_spawn_egg", + "id": 446 + }, + { + "name": "minecraft:skeleton_horse_spawn_egg", + "id": 470 + }, + { + "name": "minecraft:skeleton_spawn_egg", + "id": 447 + }, + { + "name": "minecraft:skull", + "id": 525 + }, + { + "name": "minecraft:skull_banner_pattern", + "id": 592 + }, + { + "name": "minecraft:skull_pottery_sherd", + "id": 683 + }, + { + "name": "minecraft:slime", + "id": 165 + }, + { + "name": "minecraft:slime_ball", + "id": 391 + }, + { + "name": "minecraft:slime_spawn_egg", + "id": 448 + }, + { + "name": "minecraft:small_amethyst_bud", + "id": -332 + }, + { + "name": "minecraft:small_dripleaf_block", + "id": -336 + }, + { + "name": "minecraft:smithing_table", + "id": -202 + }, + { + "name": "minecraft:smoker", + "id": -198 + }, + { + "name": "minecraft:smooth_basalt", + "id": -377 + }, + { + "name": "minecraft:smooth_quartz_stairs", + "id": -185 + }, + { + "name": "minecraft:smooth_red_sandstone_stairs", + "id": -176 + }, + { + "name": "minecraft:smooth_sandstone_stairs", + "id": -177 + }, + { + "name": "minecraft:smooth_stone", + "id": -183 + }, + { + "name": "minecraft:sniffer_egg", + "id": -596 + }, + { + "name": "minecraft:sniffer_spawn_egg", + "id": 503 + }, + { + "name": "minecraft:snort_pottery_sherd", + "id": 684 + }, + { + "name": "minecraft:snout_armor_trim_smithing_template", + "id": 695 + }, + { + "name": "minecraft:snow", + "id": 80 + }, + { + "name": "minecraft:snow_golem_spawn_egg", + "id": 509 + }, + { + "name": "minecraft:snow_layer", + "id": 78 + }, + { + "name": "minecraft:snowball", + "id": 377 + }, + { + "name": "minecraft:soul_campfire", + "id": 631 + }, + { + "name": "minecraft:soul_fire", + "id": -237 + }, + { + "name": "minecraft:soul_lantern", + "id": -269 + }, + { + "name": "minecraft:soul_sand", + "id": 88 + }, + { + "name": "minecraft:soul_soil", + "id": -236 + }, + { + "name": "minecraft:soul_torch", + "id": -268 + }, + { + "name": "minecraft:sparkler", + "id": 609 + }, + { + "name": "minecraft:spawn_egg", + "id": 726 + }, + { + "name": "minecraft:spider_eye", + "id": 279 + }, + { + "name": "minecraft:spider_spawn_egg", + "id": 449 + }, + { + "name": "minecraft:spire_armor_trim_smithing_template", + "id": 697 + }, + { + "name": "minecraft:splash_potion", + "id": 570 + }, + { + "name": "minecraft:sponge", + "id": 19 + }, + { + "name": "minecraft:spore_blossom", + "id": -321 + }, + { + "name": "minecraft:spruce_boat", + "id": 381 + }, + { + "name": "minecraft:spruce_button", + "id": -144 + }, + { + "name": "minecraft:spruce_chest_boat", + "id": 650 + }, + { + "name": "minecraft:spruce_door", + "id": 562 + }, + { + "name": "minecraft:spruce_fence", + "id": -579 + }, + { + "name": "minecraft:spruce_fence_gate", + "id": 183 + }, + { + "name": "minecraft:spruce_hanging_sign", + "id": -501 + }, + { + "name": "minecraft:spruce_log", + "id": -569 + }, + { + "name": "minecraft:spruce_planks", + "id": -739 + }, + { + "name": "minecraft:spruce_pressure_plate", + "id": -154 + }, + { + "name": "minecraft:spruce_sign", + "id": 585 + }, + { + "name": "minecraft:spruce_stairs", + "id": 134 + }, + { + "name": "minecraft:spruce_standing_sign", + "id": -181 + }, + { + "name": "minecraft:spruce_trapdoor", + "id": -149 + }, + { + "name": "minecraft:spruce_wall_sign", + "id": -182 + }, + { + "name": "minecraft:spyglass", + "id": 634 + }, + { + "name": "minecraft:squid_spawn_egg", + "id": 453 + }, + { + "name": "minecraft:stained_glass", + "id": 718 + }, + { + "name": "minecraft:stained_glass_pane", + "id": 719 + }, + { + "name": "minecraft:stained_hardened_clay", + "id": 704 + }, + { + "name": "minecraft:standing_banner", + "id": 176 + }, + { + "name": "minecraft:standing_sign", + "id": 63 + }, + { + "name": "minecraft:stick", + "id": 323 + }, + { + "name": "minecraft:sticky_piston", + "id": 29 + }, + { + "name": "minecraft:sticky_piston_arm_collision", + "id": -217 + }, + { + "name": "minecraft:stone", + "id": 1 + }, + { + "name": "minecraft:stone_axe", + "id": 318 + }, + { + "name": "minecraft:stone_block_slab", + "id": 44 + }, + { + "name": "minecraft:stone_block_slab2", + "id": 182 + }, + { + "name": "minecraft:stone_block_slab3", + "id": -162 + }, + { + "name": "minecraft:stone_block_slab4", + "id": -166 + }, + { + "name": "minecraft:stone_brick_stairs", + "id": 109 + }, + { + "name": "minecraft:stone_button", + "id": 77 + }, + { + "name": "minecraft:stone_hoe", + "id": 333 + }, + { + "name": "minecraft:stone_pickaxe", + "id": 317 + }, + { + "name": "minecraft:stone_pressure_plate", + "id": 70 + }, + { + "name": "minecraft:stone_shovel", + "id": 316 + }, + { + "name": "minecraft:stone_stairs", + "id": 67 + }, + { + "name": "minecraft:stone_sword", + "id": 315 + }, + { + "name": "minecraft:stonebrick", + "id": 98 + }, + { + "name": "minecraft:stonecutter", + "id": 245 + }, + { + "name": "minecraft:stonecutter_block", + "id": -197 + }, + { + "name": "minecraft:stray_spawn_egg", + "id": 465 + }, + { + "name": "minecraft:strider_spawn_egg", + "id": 498 + }, + { + "name": "minecraft:string", + "id": 329 + }, + { + "name": "minecraft:stripped_acacia_log", + "id": -8 + }, + { + "name": "minecraft:stripped_bamboo_block", + "id": -528 + }, + { + "name": "minecraft:stripped_birch_log", + "id": -6 + }, + { + "name": "minecraft:stripped_cherry_log", + "id": -535 + }, + { + "name": "minecraft:stripped_cherry_wood", + "id": -545 + }, + { + "name": "minecraft:stripped_crimson_hyphae", + "id": -300 + }, + { + "name": "minecraft:stripped_crimson_stem", + "id": -240 + }, + { + "name": "minecraft:stripped_dark_oak_log", + "id": -9 + }, + { + "name": "minecraft:stripped_jungle_log", + "id": -7 + }, + { + "name": "minecraft:stripped_mangrove_log", + "id": -485 + }, + { + "name": "minecraft:stripped_mangrove_wood", + "id": -498 + }, + { + "name": "minecraft:stripped_oak_log", + "id": -10 + }, + { + "name": "minecraft:stripped_spruce_log", + "id": -5 + }, + { + "name": "minecraft:stripped_warped_hyphae", + "id": -301 + }, + { + "name": "minecraft:stripped_warped_stem", + "id": -241 + }, + { + "name": "minecraft:structure_block", + "id": 252 + }, + { + "name": "minecraft:structure_void", + "id": 217 + }, + { + "name": "minecraft:sugar", + "id": 419 + }, + { + "name": "minecraft:sugar_cane", + "id": 388 + }, + { + "name": "minecraft:suspicious_gravel", + "id": -573 + }, + { + "name": "minecraft:suspicious_sand", + "id": -529 + }, + { + "name": "minecraft:suspicious_stew", + "id": 599 + }, + { + "name": "minecraft:sweet_berries", + "id": 288 + }, + { + "name": "minecraft:sweet_berry_bush", + "id": -207 + }, + { + "name": "minecraft:tadpole_bucket", + "id": 639 + }, + { + "name": "minecraft:tadpole_spawn_egg", + "id": 638 + }, + { + "name": "minecraft:tallgrass", + "id": 31 + }, + { + "name": "minecraft:target", + "id": -239 + }, + { + "name": "minecraft:tide_armor_trim_smithing_template", + "id": 694 + }, + { + "name": "minecraft:tinted_glass", + "id": -334 + }, + { + "name": "minecraft:tnt", + "id": 46 + }, + { + "name": "minecraft:tnt_minecart", + "id": 534 + }, + { + "name": "minecraft:torch", + "id": 50 + }, + { + "name": "minecraft:torchflower", + "id": -568 + }, + { + "name": "minecraft:torchflower_crop", + "id": -567 + }, + { + "name": "minecraft:torchflower_seeds", + "id": 297 + }, + { + "name": "minecraft:totem_of_undying", + "id": 577 + }, + { + "name": "minecraft:trader_llama_spawn_egg", + "id": 657 + }, + { + "name": "minecraft:trapdoor", + "id": 96 + }, + { + "name": "minecraft:trapped_chest", + "id": 146 + }, + { + "name": "minecraft:trial_key", + "id": 705 + }, + { + "name": "minecraft:trial_spawner", + "id": -315 + }, + { + "name": "minecraft:trident", + "id": 555 + }, + { + "name": "minecraft:trip_wire", + "id": 132 + }, + { + "name": "minecraft:tripwire_hook", + "id": 131 + }, + { + "name": "minecraft:tropical_fish", + "id": 267 + }, + { + "name": "minecraft:tropical_fish_bucket", + "id": 369 + }, + { + "name": "minecraft:tropical_fish_spawn_egg", + "id": 482 + }, + { + "name": "minecraft:tube_coral", + "id": -131 + }, + { + "name": "minecraft:tuff", + "id": -333 + }, + { + "name": "minecraft:tuff_brick_double_slab", + "id": -756 + }, + { + "name": "minecraft:tuff_brick_slab", + "id": -755 + }, + { + "name": "minecraft:tuff_brick_stairs", + "id": -757 + }, + { + "name": "minecraft:tuff_brick_wall", + "id": -758 + }, + { + "name": "minecraft:tuff_bricks", + "id": -754 + }, + { + "name": "minecraft:tuff_double_slab", + "id": -745 + }, + { + "name": "minecraft:tuff_slab", + "id": -744 + }, + { + "name": "minecraft:tuff_stairs", + "id": -746 + }, + { + "name": "minecraft:tuff_wall", + "id": -747 + }, + { + "name": "minecraft:turtle_egg", + "id": -159 + }, + { + "name": "minecraft:turtle_helmet", + "id": 582 + }, + { + "name": "minecraft:turtle_scute", + "id": 581 + }, + { + "name": "minecraft:turtle_spawn_egg", + "id": 488 + }, + { + "name": "minecraft:twisting_vines", + "id": -287 + }, + { + "name": "minecraft:underwater_torch", + "id": 239 + }, + { + "name": "minecraft:undyed_shulker_box", + "id": 205 + }, + { + "name": "minecraft:unknown", + "id": -305 + }, + { + "name": "minecraft:unlit_redstone_torch", + "id": 75 + }, + { + "name": "minecraft:unpowered_comparator", + "id": 149 + }, + { + "name": "minecraft:unpowered_repeater", + "id": 93 + }, + { + "name": "minecraft:verdant_froglight", + "id": -470 + }, + { + "name": "minecraft:vex_armor_trim_smithing_template", + "id": 693 + }, + { + "name": "minecraft:vex_spawn_egg", + "id": 479 + }, + { + "name": "minecraft:villager_spawn_egg", + "id": 452 + }, + { + "name": "minecraft:vindicator_spawn_egg", + "id": 477 + }, + { + "name": "minecraft:vine", + "id": 106 + }, + { + "name": "minecraft:wall_banner", + "id": 177 + }, + { + "name": "minecraft:wall_sign", + "id": 68 + }, + { + "name": "minecraft:wandering_trader_spawn_egg", + "id": 495 + }, + { + "name": "minecraft:ward_armor_trim_smithing_template", + "id": 691 + }, + { + "name": "minecraft:warden_spawn_egg", + "id": 641 + }, + { + "name": "minecraft:warped_button", + "id": -261 + }, + { + "name": "minecraft:warped_door", + "id": 626 + }, + { + "name": "minecraft:warped_double_slab", + "id": -267 + }, + { + "name": "minecraft:warped_fence", + "id": -257 + }, + { + "name": "minecraft:warped_fence_gate", + "id": -259 + }, + { + "name": "minecraft:warped_fungus", + "id": -229 + }, + { + "name": "minecraft:warped_fungus_on_a_stick", + "id": 627 + }, + { + "name": "minecraft:warped_hanging_sign", + "id": -507 + }, + { + "name": "minecraft:warped_hyphae", + "id": -298 + }, + { + "name": "minecraft:warped_nylium", + "id": -233 + }, + { + "name": "minecraft:warped_planks", + "id": -243 + }, + { + "name": "minecraft:warped_pressure_plate", + "id": -263 + }, + { + "name": "minecraft:warped_roots", + "id": -224 + }, + { + "name": "minecraft:warped_sign", + "id": 624 + }, + { + "name": "minecraft:warped_slab", + "id": -265 + }, + { + "name": "minecraft:warped_stairs", + "id": -255 + }, + { + "name": "minecraft:warped_standing_sign", + "id": -251 + }, + { + "name": "minecraft:warped_stem", + "id": -226 + }, + { + "name": "minecraft:warped_trapdoor", + "id": -247 + }, + { + "name": "minecraft:warped_wall_sign", + "id": -253 + }, + { + "name": "minecraft:warped_wart_block", + "id": -227 + }, + { + "name": "minecraft:water", + "id": 9 + }, + { + "name": "minecraft:water_bucket", + "id": 365 + }, + { + "name": "minecraft:waterlily", + "id": 111 + }, + { + "name": "minecraft:waxed_chiseled_copper", + "id": -764 + }, + { + "name": "minecraft:waxed_copper", + "id": -344 + }, + { + "name": "minecraft:waxed_copper_bulb", + "id": -780 + }, + { + "name": "minecraft:waxed_copper_door", + "id": -788 + }, + { + "name": "minecraft:waxed_copper_grate", + "id": -772 + }, + { + "name": "minecraft:waxed_copper_trapdoor", + "id": -796 + }, + { + "name": "minecraft:waxed_cut_copper", + "id": -351 + }, + { + "name": "minecraft:waxed_cut_copper_slab", + "id": -365 + }, + { + "name": "minecraft:waxed_cut_copper_stairs", + "id": -358 + }, + { + "name": "minecraft:waxed_double_cut_copper_slab", + "id": -372 + }, + { + "name": "minecraft:waxed_exposed_chiseled_copper", + "id": -765 + }, + { + "name": "minecraft:waxed_exposed_copper", + "id": -345 + }, + { + "name": "minecraft:waxed_exposed_copper_bulb", + "id": -781 + }, + { + "name": "minecraft:waxed_exposed_copper_door", + "id": -789 + }, + { + "name": "minecraft:waxed_exposed_copper_grate", + "id": -773 + }, + { + "name": "minecraft:waxed_exposed_copper_trapdoor", + "id": -797 + }, + { + "name": "minecraft:waxed_exposed_cut_copper", + "id": -352 + }, + { + "name": "minecraft:waxed_exposed_cut_copper_slab", + "id": -366 + }, + { + "name": "minecraft:waxed_exposed_cut_copper_stairs", + "id": -359 + }, + { + "name": "minecraft:waxed_exposed_double_cut_copper_slab", + "id": -373 + }, + { + "name": "minecraft:waxed_oxidized_chiseled_copper", + "id": -766 + }, + { + "name": "minecraft:waxed_oxidized_copper", + "id": -446 + }, + { + "name": "minecraft:waxed_oxidized_copper_bulb", + "id": -783 + }, + { + "name": "minecraft:waxed_oxidized_copper_door", + "id": -791 + }, + { + "name": "minecraft:waxed_oxidized_copper_grate", + "id": -775 + }, + { + "name": "minecraft:waxed_oxidized_copper_trapdoor", + "id": -799 + }, + { + "name": "minecraft:waxed_oxidized_cut_copper", + "id": -447 + }, + { + "name": "minecraft:waxed_oxidized_cut_copper_slab", + "id": -449 + }, + { + "name": "minecraft:waxed_oxidized_cut_copper_stairs", + "id": -448 + }, + { + "name": "minecraft:waxed_oxidized_double_cut_copper_slab", + "id": -450 + }, + { + "name": "minecraft:waxed_weathered_chiseled_copper", + "id": -767 + }, + { + "name": "minecraft:waxed_weathered_copper", + "id": -346 + }, + { + "name": "minecraft:waxed_weathered_copper_bulb", + "id": -782 + }, + { + "name": "minecraft:waxed_weathered_copper_door", + "id": -790 + }, + { + "name": "minecraft:waxed_weathered_copper_grate", + "id": -774 + }, + { + "name": "minecraft:waxed_weathered_copper_trapdoor", + "id": -798 + }, + { + "name": "minecraft:waxed_weathered_cut_copper", + "id": -353 + }, + { + "name": "minecraft:waxed_weathered_cut_copper_slab", + "id": -367 + }, + { + "name": "minecraft:waxed_weathered_cut_copper_stairs", + "id": -360 + }, + { + "name": "minecraft:waxed_weathered_double_cut_copper_slab", + "id": -374 + }, + { + "name": "minecraft:wayfinder_armor_trim_smithing_template", + "id": 699 + }, + { + "name": "minecraft:weathered_chiseled_copper", + "id": -762 + }, + { + "name": "minecraft:weathered_copper", + "id": -342 + }, + { + "name": "minecraft:weathered_copper_bulb", + "id": -778 + }, + { + "name": "minecraft:weathered_copper_door", + "id": -786 + }, + { + "name": "minecraft:weathered_copper_grate", + "id": -770 + }, + { + "name": "minecraft:weathered_copper_trapdoor", + "id": -794 + }, + { + "name": "minecraft:weathered_cut_copper", + "id": -349 + }, + { + "name": "minecraft:weathered_cut_copper_slab", + "id": -363 + }, + { + "name": "minecraft:weathered_cut_copper_stairs", + "id": -356 + }, + { + "name": "minecraft:weathered_double_cut_copper_slab", + "id": -370 + }, + { + "name": "minecraft:web", + "id": 30 + }, + { + "name": "minecraft:weeping_vines", + "id": -231 + }, + { + "name": "minecraft:wheat", + "id": 337 + }, + { + "name": "minecraft:wheat_seeds", + "id": 292 + }, + { + "name": "minecraft:white_candle", + "id": -413 + }, + { + "name": "minecraft:white_candle_cake", + "id": -430 + }, + { + "name": "minecraft:white_carpet", + "id": 171 + }, + { + "name": "minecraft:white_concrete", + "id": 236 + }, + { + "name": "minecraft:white_concrete_powder", + "id": 237 + }, + { + "name": "minecraft:white_dye", + "id": 413 + }, + { + "name": "minecraft:white_glazed_terracotta", + "id": 220 + }, + { + "name": "minecraft:white_shulker_box", + "id": 218 + }, + { + "name": "minecraft:white_stained_glass", + "id": 241 + }, + { + "name": "minecraft:white_stained_glass_pane", + "id": 160 + }, + { + "name": "minecraft:white_terracotta", + "id": 159 + }, + { + "name": "minecraft:white_wool", + "id": 35 + }, + { + "name": "minecraft:wild_armor_trim_smithing_template", + "id": 690 + }, + { + "name": "minecraft:witch_spawn_egg", + "id": 455 + }, + { + "name": "minecraft:wither_rose", + "id": -216 + }, + { + "name": "minecraft:wither_skeleton_spawn_egg", + "id": 467 + }, + { + "name": "minecraft:wither_spawn_egg", + "id": 511 + }, + { + "name": "minecraft:wolf_armor", + "id": 708 + }, + { + "name": "minecraft:wolf_spawn_egg", + "id": 442 + }, + { + "name": "minecraft:wood", + "id": -212 + }, + { + "name": "minecraft:wooden_axe", + "id": 314 + }, + { + "name": "minecraft:wooden_button", + "id": 143 + }, + { + "name": "minecraft:wooden_door", + "id": 362 + }, + { + "name": "minecraft:wooden_hoe", + "id": 332 + }, + { + "name": "minecraft:wooden_pickaxe", + "id": 313 + }, + { + "name": "minecraft:wooden_pressure_plate", + "id": 72 + }, + { + "name": "minecraft:wooden_shovel", + "id": 312 + }, + { + "name": "minecraft:wooden_slab", + "id": 158 + }, + { + "name": "minecraft:wooden_sword", + "id": 311 + }, + { + "name": "minecraft:wool", + "id": 709 + }, + { + "name": "minecraft:writable_book", + "id": 519 + }, + { + "name": "minecraft:written_book", + "id": 520 + }, + { + "name": "minecraft:yellow_candle", + "id": -417 + }, + { + "name": "minecraft:yellow_candle_cake", + "id": -434 + }, + { + "name": "minecraft:yellow_carpet", + "id": -600 + }, + { + "name": "minecraft:yellow_concrete", + "id": -631 + }, + { + "name": "minecraft:yellow_concrete_powder", + "id": -712 + }, + { + "name": "minecraft:yellow_dye", + "id": 409 + }, + { + "name": "minecraft:yellow_flower", + "id": 37 + }, + { + "name": "minecraft:yellow_glazed_terracotta", + "id": 224 + }, + { + "name": "minecraft:yellow_shulker_box", + "id": -616 + }, + { + "name": "minecraft:yellow_stained_glass", + "id": -676 + }, + { + "name": "minecraft:yellow_stained_glass_pane", + "id": -646 + }, + { + "name": "minecraft:yellow_terracotta", + "id": -727 + }, + { + "name": "minecraft:yellow_wool", + "id": -558 + }, + { + "name": "minecraft:zoglin_spawn_egg", + "id": 501 + }, + { + "name": "minecraft:zombie_horse_spawn_egg", + "id": 471 + }, + { + "name": "minecraft:zombie_pigman_spawn_egg", + "id": 451 + }, + { + "name": "minecraft:zombie_spawn_egg", + "id": 450 + }, + { + "name": "minecraft:zombie_villager_spawn_egg", + "id": 480 + } +] \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d3e425239..14a224a3a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,10 +9,10 @@ netty = "4.1.103.Final" guava = "29.0-jre" gson = "2.3.1" # Provided by Spigot 1.8.8 websocket = "1.5.1" -protocol = "3.0.0.Beta1-20231206.150507-114" -protocol-connection = "3.0.0.Beta1-20231206.150507-113" +protocol = "3.0.0.Beta1-20240204.134050-120" +protocol-connection = "3.0.0.Beta1-20240204.134050-119" raknet = "1.0.0.CR1-20231206.145325-12" -blockstateupdater="1.20.50-20231106.161340-1" +blockstateupdater="1.20.60-20240129.140535-1" mcauthlib = "d9d773e" mcprotocollib = "1.20.4-2-20240116.220521-7" adventure = "4.14.0" From fa339d37b52f633f25b4e7dabeea1ca91fabef43 Mon Sep 17 00:00:00 2001 From: chris Date: Wed, 7 Feb 2024 08:32:04 +0100 Subject: [PATCH 181/344] Update version in readme (#4420) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bdd8cbe98..d58e2eb58 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,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.20.40 - 1.20.51 and Minecraft Java 1.20.4 +### Currently supporting Minecraft Bedrock 1.20.40 - 1.20.61 and Minecraft Java 1.20.4 ## Setting Up Take a look [here](https://wiki.geysermc.org/geyser/setup/) for how to set up Geyser. From e6636ec9fe454d4891d4f56aba8d3e43aeeee17d Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Wed, 7 Feb 2024 06:15:36 -0800 Subject: [PATCH 182/344] Weapon component is deprecated (#4417) --- .../geyser/registry/populator/CustomItemRegistryPopulator.java | 1 - 1 file changed, 1 deletion(-) 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 e1d67399f..433b732a8 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 @@ -348,7 +348,6 @@ public class CustomItemRegistryPopulator { if (toolType.equals("sword")) { miningSpeed = 1.5f; canDestroyInCreative = false; - componentBuilder.putCompound("minecraft:weapon", NbtMap.EMPTY); } itemProperties.putBoolean("hand_equipped", true); From 63fd97ab322faa52fbb1e201d274f0036b5db50c Mon Sep 17 00:00:00 2001 From: chris Date: Wed, 7 Feb 2024 18:17:51 +0100 Subject: [PATCH 183/344] Fix: Crashing due to custom bows/crossbows/tridents (#4421) * initial stab at fixing crashing due to removal of the chargeable component * remove hardcoded animation --- .../CustomItemRegistryPopulator.java | 86 +++++++++++++++++-- 1 file changed, 77 insertions(+), 9 deletions(-) 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 433b732a8..c1f1bb10c 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 @@ -177,7 +177,7 @@ public class CustomItemRegistryPopulator { itemProperties.putBoolean("can_destroy_in_creative", canDestroyInCreative); if (mapping.getArmorType() != null) { - computeArmorProperties(mapping.getArmorType(), mapping.getProtectionValue(), componentBuilder); + computeArmorProperties(mapping.getArmorType(), mapping.getProtectionValue(), itemProperties, componentBuilder); } if (mapping.getFirstBlockRuntimeId() != null) { @@ -194,7 +194,7 @@ public class CustomItemRegistryPopulator { switch (mapping.getBedrockIdentifier()) { case "minecraft:fire_charge", "minecraft:flint_and_steel" -> computeBlockItemProperties("minecraft:fire", componentBuilder); - case "minecraft:bow", "minecraft:crossbow", "minecraft:trident" -> computeChargeableProperties(itemProperties, componentBuilder); + case "minecraft:bow", "minecraft:crossbow", "minecraft:trident" -> computeChargeableProperties(itemProperties, componentBuilder, mapping.getBedrockIdentifier(), protocolVersion); case "minecraft:honey_bottle", "minecraft:milk_bucket", "minecraft:potion" -> computeConsumableProperties(itemProperties, componentBuilder, 2, true); case "minecraft:experience_bottle", "minecraft:egg", "minecraft:ender_pearl", "minecraft:ender_eye", "minecraft:lingering_potion", "minecraft:snowball", "minecraft:splash_potion" -> computeThrowableProperties(componentBuilder); @@ -223,13 +223,13 @@ public class CustomItemRegistryPopulator { boolean canDestroyInCreative = true; if (customItemData.toolType() != null) { // This is not using the isTool boolean because it is not just a render type here. - canDestroyInCreative = computeToolProperties(customItemData.toolType(), itemProperties, componentBuilder); + canDestroyInCreative = computeToolProperties(Objects.requireNonNull(customItemData.toolType()), itemProperties, componentBuilder); } itemProperties.putBoolean("can_destroy_in_creative", canDestroyInCreative); String armorType = customItemData.armorType(); if (armorType != null) { - computeArmorProperties(armorType, customItemData.protectionValue(), componentBuilder); + computeArmorProperties(armorType, customItemData.protectionValue(), itemProperties, componentBuilder); } if (customItemData.isEdible()) { @@ -237,7 +237,11 @@ public class CustomItemRegistryPopulator { } if (customItemData.isChargeable()) { - computeChargeableProperties(itemProperties, componentBuilder); + String tooltype = customItemData.toolType(); + if (tooltype == null) { + throw new IllegalArgumentException("tool type must be set if the custom item is chargeable!"); + } + computeChargeableProperties(itemProperties, componentBuilder, "minecraft:" + tooltype, protocolVersion); } computeRenderOffsets(isHat, customItemData, componentBuilder); @@ -353,10 +357,14 @@ public class CustomItemRegistryPopulator { itemProperties.putBoolean("hand_equipped", true); itemProperties.putFloat("mining_speed", miningSpeed); + // This allows custom tools - shears, swords, shovels, axes etc to be enchanted or combined in the anvil + itemProperties.putInt("enchantable_value", 1); + itemProperties.putString("enchantable_slot", toolType); + return canDestroyInCreative; } - private static void computeArmorProperties(String armorType, int protectionValue, NbtMapBuilder componentBuilder) { + private static void computeArmorProperties(String armorType, int protectionValue, NbtMapBuilder itemProperties, NbtMapBuilder componentBuilder) { switch (armorType) { case "boots" -> { componentBuilder.putString("minecraft:render_offsets", "boots"); @@ -390,13 +398,73 @@ public class CustomItemRegistryPopulator { componentBuilder.putCompound("minecraft:block_placer", NbtMap.builder().putString("block", blockItem).build()); } - private static void computeChargeableProperties(NbtMapBuilder itemProperties, NbtMapBuilder componentBuilder) { + private static void computeChargeableProperties(NbtMapBuilder itemProperties, NbtMapBuilder componentBuilder, String mapping, int protocolVersion) { // setting high use_duration prevents the consume animation from playing itemProperties.putInt("use_duration", Integer.MAX_VALUE); // display item as tool (mainly for crossbow and bow) itemProperties.putBoolean("hand_equipped", true); - // ensure client moves at slow speed while charging (note: this was calculated by hand as the movement modifer value does not seem to scale linearly) - componentBuilder.putCompound("minecraft:chargeable", NbtMap.builder().putFloat("movement_modifier", 0.35F).build()); + // Make bows, tridents, and crossbows enchantable + itemProperties.putInt("enchantable_value", 1); + + if (GameProtocol.is1_20_60orHigher(protocolVersion)) { + componentBuilder.putCompound("minecraft:use_modifiers", NbtMap.builder() + .putFloat("use_duration", 100F) + .putFloat("movement_modifier", 0.35F) + .build()); + + switch (mapping) { + case "minecraft:bow" -> { + itemProperties.putString("enchantable_slot", "bow"); + itemProperties.putInt("frame_count", 3); + + componentBuilder.putCompound("minecraft:shooter", NbtMap.builder() + .putList("ammunition", NbtType.COMPOUND, List.of( + NbtMap.builder() + .putCompound("item", NbtMap.builder() + .putString("name", "minecraft:arrow") + .build()) + .putBoolean("use_offhand", true) + .putBoolean("search_inventory", true) + .build() + )) + .putFloat("max_draw_duration", 0f) + .putBoolean("charge_on_draw", true) + .putBoolean("scale_power_by_draw_duration", true) + .build()); + componentBuilder.putInt("minecraft:use_duration", 999); + } + case "minecraft:trident" -> { + itemProperties.putString("enchantable_slot", "trident"); + componentBuilder.putInt("minecraft:use_duration", 999); + } + case "minecraft:crossbow" -> { + itemProperties.putString("enchantable_slot", "crossbow"); + itemProperties.putInt("frame_count", 10); + + componentBuilder.putCompound("minecraft:shooter", NbtMap.builder() + .putList("ammunition", NbtType.COMPOUND, List.of( + NbtMap.builder() + .putCompound("item", NbtMap.builder() + .putString("name", "minecraft:arrow") + .build()) + .putBoolean("use_offhand", true) + .putBoolean("search_inventory", true) + .build() + )) + .putFloat("max_draw_duration", 1f) + .putBoolean("charge_on_draw", true) + .putBoolean("scale_power_by_draw_duration", true) + .build()); + componentBuilder.putInt("minecraft:use_duration", 999); + } + } + } else { + // ensure client moves at slow speed while charging (note: this was calculated by hand as the movement modifer value does not seem to scale linearly) + componentBuilder.putCompound("minecraft:chargeable", NbtMap.builder().putFloat("movement_modifier", 0.35F).build()); + + // keep item enchantable; also works on 1.20.50 + itemProperties.putString("enchantable_slot", mapping.replace("minecraft:", "")); + } } private static void computeConsumableProperties(NbtMapBuilder itemProperties, NbtMapBuilder componentBuilder, int useAnimation, boolean canAlwaysEat) { From 19c6648bc22200bb939936a9dbbbed5922c74372 Mon Sep 17 00:00:00 2001 From: chris Date: Thu, 8 Feb 2024 17:30:01 +0100 Subject: [PATCH 184/344] Fix: Nametags not showing up (#4427) --- .../org/geysermc/geyser/entity/type/player/PlayerEntity.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java index 37e408502..3578ac82b 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java @@ -120,6 +120,9 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity { super.initializeMetadata(); // For the OptionalPack, set all bits as invisible by default as this matches Java Edition behavior dirtyMetadata.put(EntityDataTypes.MARK_VARIANT, 0xff); + // Since 1.20.60, the nametag does not show properly if this is not set :/ + // The nametag does disappear properly when the player is invisible though. + dirtyMetadata.put(EntityDataTypes.NAMETAG_ALWAYS_SHOW, (byte) 1); } @Override From 6a51d8298f75cd17cfca66726a0d5e550c3e316c Mon Sep 17 00:00:00 2001 From: chris Date: Wed, 14 Feb 2024 12:50:50 +0100 Subject: [PATCH 185/344] Feature: Rework startup logic (#4377) * This makes `geyser reload` work the same across all platforms. For example, it ensures that we reload the config to the greatest extent possible (with the exception of compression/injection settings). Additionally, this clears up issues where Extensions were previously disabled during reloading - instead, the new Pre and Post reload events allow extensions to reload whatever necessary on their own. --- .../lifecycle/GeyserPostReloadEvent.java | 42 +++ .../event/lifecycle/GeyserPreReloadEvent.java | 42 +++ .../bungeecord/GeyserBungeePlugin.java | 163 +++++++----- .../platform/fabric/GeyserFabricMod.java | 122 ++++----- .../command/GeyserFabricCommandExecutor.java | 4 - .../mixin/client/IntegratedServerMixin.java | 3 +- .../platform/spigot/GeyserSpigotPlugin.java | 248 +++++++++--------- .../standalone/GeyserStandaloneBootstrap.java | 51 ++-- .../standalone/GeyserStandaloneLogger.java | 2 +- .../velocity/GeyserVelocityPlugin.java | 119 +++++---- .../org/geysermc/geyser/GeyserBootstrap.java | 22 +- .../java/org/geysermc/geyser/GeyserImpl.java | 68 +++-- .../geyser/command/GeyserCommandManager.java | 2 +- .../command/defaults/ReloadCommand.java | 2 +- .../geyser/command/defaults/StopCommand.java | 2 +- .../geyser/network/UpstreamPacketHandler.java | 2 +- .../geyser/scoreboard/ScoreboardUpdater.java | 2 +- .../org/geysermc/geyser/util/EntityUtils.java | 1 + 18 files changed, 539 insertions(+), 358 deletions(-) create mode 100644 api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserPostReloadEvent.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserPreReloadEvent.java diff --git a/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserPostReloadEvent.java b/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserPostReloadEvent.java new file mode 100644 index 000000000..c421cda37 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserPostReloadEvent.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019-2024 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.api.event.lifecycle; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.event.Event; +import org.geysermc.geyser.api.event.EventBus; +import org.geysermc.geyser.api.event.EventRegistrar; +import org.geysermc.geyser.api.extension.ExtensionManager; + +/** + * Called when Geyser finished reloading and is accepting Bedrock connections again. + * Equivalent to the {@link GeyserPostInitializeEvent} + * + * @param extensionManager the extension manager + * @param eventBus the event bus + */ +public record GeyserPostReloadEvent(@NonNull ExtensionManager extensionManager, @NonNull EventBus eventBus) implements Event { +} diff --git a/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserPreReloadEvent.java b/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserPreReloadEvent.java new file mode 100644 index 000000000..16d5058da --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserPreReloadEvent.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019-2024 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.api.event.lifecycle; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.event.Event; +import org.geysermc.geyser.api.event.EventBus; +import org.geysermc.geyser.api.event.EventRegistrar; +import org.geysermc.geyser.api.extension.ExtensionManager; + +/** + * Called when Geyser is about to reload. Primarily aimed at extensions, so they can decide on their own what to reload. + * After this event is fired, some lifecycle events can be fired again - such as the {@link GeyserLoadResourcePacksEvent}. + * + * @param extensionManager the extension manager + * @param eventBus the event bus + */ +public record GeyserPreReloadEvent(@NonNull ExtensionManager extensionManager, @NonNull EventBus eventBus) implements Event { +} diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java index c5d5cdacc..4191c8578 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java @@ -32,11 +32,11 @@ import net.md_5.bungee.api.plugin.Plugin; import net.md_5.bungee.protocol.ProtocolConstants; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; -import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.command.Command; import org.geysermc.geyser.api.extension.Extension; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.command.GeyserCommandManager; import org.geysermc.geyser.configuration.GeyserConfiguration; import org.geysermc.geyser.dump.BootstrapDumpInfo; @@ -70,11 +70,13 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { private GeyserImpl geyser; - private static boolean INITIALIZED = false; - - @SuppressWarnings({"JavaReflectionMemberAccess", "ResultOfMethodCallIgnored"}) @Override public void onLoad() { + onGeyserInitialize(); + } + + @Override + public void onGeyserInitialize() { GeyserLocale.init(this); // Copied from ViaVersion. @@ -91,29 +93,62 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { getLogger().warning("/_____________\\"); } - if (!getDataFolder().exists()) - getDataFolder().mkdir(); - - try { - if (!getDataFolder().exists()) - getDataFolder().mkdir(); - File configFile = FileUtils.fileOrCopiedFromResource(new File(getDataFolder(), "config.yml"), - "config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this); - this.geyserConfig = FileUtils.loadConfig(configFile, GeyserBungeeConfiguration.class); - } catch (IOException ex) { - getLogger().log(Level.SEVERE, GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex); - ex.printStackTrace(); + if (!this.loadConfig()) { return; } - this.geyserLogger = new GeyserBungeeLogger(getLogger(), geyserConfig.isDebugMode()); GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); - this.geyser = GeyserImpl.load(PlatformType.BUNGEECORD, this); + this.geyserInjector = new GeyserBungeeInjector(this); } @Override public void onEnable() { + // Big hack - Bungee does not provide us an event to listen to, so schedule a repeating + // task that waits for a field to be filled which is set after the plugin enable + // process is complete + this.awaitStartupCompletion(0); + } + + @SuppressWarnings("unchecked") + private void awaitStartupCompletion(int tries) { + // After 20 tries give up waiting. This will happen just after 3 minutes approximately + if (tries >= 20) { + this.geyserLogger.warning("BungeeCord plugin startup is taking abnormally long, so Geyser is starting now. " + + "If all your plugins are loaded properly, this is a bug! " + + "If not, consider cutting down the amount of plugins on your proxy as it is causing abnormally slow starting times."); + this.onGeyserEnable(); + return; + } + + try { + Field listenersField = BungeeCord.getInstance().getClass().getDeclaredField("listeners"); + listenersField.setAccessible(true); + + Collection listeners = (Collection) listenersField.get(BungeeCord.getInstance()); + if (listeners.isEmpty()) { + this.getProxy().getScheduler().schedule(this, this::onGeyserEnable, tries, TimeUnit.SECONDS); + } else { + this.awaitStartupCompletion(++tries); + } + } catch (NoSuchFieldException | IllegalAccessException ex) { + ex.printStackTrace(); + } + } + + public void onGeyserEnable() { + if (GeyserImpl.getInstance().isReloading()) { + if (!loadConfig()) { + return; + } + this.geyserLogger.setDebug(geyserConfig.isDebugMode()); + GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); + } else { + // For consistency with other platforms - create command manager before GeyserImpl#start() + // This ensures the command events are called before the item/block ones are + this.geyserCommandManager = new GeyserCommandManager(geyser); + this.geyserCommandManager.init(); + } // Force-disable query if enabled, or else Geyser won't enable for (ListenerInfo info : getProxy().getConfig().getListeners()) { @@ -133,54 +168,20 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { } } - // Big hack - Bungee does not provide us an event to listen to, so schedule a repeating - // task that waits for a field to be filled which is set after the plugin enable - // process is complete - if (!INITIALIZED) { - this.awaitStartupCompletion(0); - } else { - // No need to "wait" for startup completion, just start Geyser - we're reloading. - this.postStartup(); - } - } + GeyserImpl.start(); - @SuppressWarnings("unchecked") - private void awaitStartupCompletion(int tries) { - // After 20 tries give up waiting. This will happen - // just after 3 minutes approximately - if (tries >= 20) { - this.geyserLogger.warning("BungeeCord plugin startup is taking abnormally long, so Geyser is starting now. " + - "If all your plugins are loaded properly, this is a bug! " + - "If not, consider cutting down the amount of plugins on your proxy as it is causing abnormally slow starting times."); - this.postStartup(); + if (geyserConfig.isLegacyPingPassthrough()) { + this.geyserBungeePingPassthrough = GeyserLegacyPingPassthrough.init(geyser); + } else { + this.geyserBungeePingPassthrough = new GeyserBungeePingPassthrough(getProxy()); + } + + // No need to re-register commands or re-init injector when reloading + if (GeyserImpl.getInstance().isReloading()) { return; } - try { - Field listenersField = BungeeCord.getInstance().getClass().getDeclaredField("listeners"); - listenersField.setAccessible(true); - - Collection listeners = (Collection) listenersField.get(BungeeCord.getInstance()); - if (listeners.isEmpty()) { - this.getProxy().getScheduler().schedule(this, this::postStartup, tries, TimeUnit.SECONDS); - } else { - this.awaitStartupCompletion(++tries); - } - } catch (NoSuchFieldException | IllegalAccessException ex) { - ex.printStackTrace(); - } - } - - private void postStartup() { - GeyserImpl.start(); - - if (!INITIALIZED) { - this.geyserInjector = new GeyserBungeeInjector(this); - this.geyserInjector.initializeLocalChannel(this); - } - - this.geyserCommandManager = new GeyserCommandManager(geyser); - this.geyserCommandManager.init(); + this.geyserInjector.initializeLocalChannel(this); this.getProxy().getPluginManager().registerCommand(this, new GeyserBungeeCommandExecutor("geyser", this.geyser, this.geyserCommandManager.getCommands())); for (Map.Entry> entry : this.geyserCommandManager.extensionCommands().entrySet()) { @@ -191,18 +192,17 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { this.getProxy().getPluginManager().registerCommand(this, new GeyserBungeeCommandExecutor(entry.getKey().description().id(), this.geyser, commands)); } - - if (geyserConfig.isLegacyPingPassthrough()) { - this.geyserBungeePingPassthrough = GeyserLegacyPingPassthrough.init(geyser); - } else { - this.geyserBungeePingPassthrough = new GeyserBungeePingPassthrough(getProxy()); - } - - INITIALIZED = true; } @Override - public void onDisable() { + public void onGeyserDisable() { + if (geyser != null) { + geyser.disable(); + } + } + + @Override + public void onGeyserShutdown() { if (geyser != null) { geyser.shutdown(); } @@ -211,6 +211,11 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { } } + @Override + public void onDisable() { + this.onGeyserShutdown(); + } + @Override public GeyserBungeeConfiguration getGeyserConfig() { return geyserConfig; @@ -278,4 +283,20 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { .map(info -> (InetSocketAddress) info.getSocketAddress()) .findFirst(); } + + @SuppressWarnings("BooleanMethodIsAlwaysInverted") + private boolean loadConfig() { + try { + if (!getDataFolder().exists()) //noinspection ResultOfMethodCallIgnored + getDataFolder().mkdir(); + File configFile = FileUtils.fileOrCopiedFromResource(new File(getDataFolder(), "config.yml"), + "config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this); + this.geyserConfig = FileUtils.loadConfig(configFile, GeyserBungeeConfiguration.class); + } catch (IOException ex) { + getLogger().log(Level.SEVERE, GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex); + ex.printStackTrace(); + return false; + } + return true; + } } diff --git a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMod.java b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMod.java index 071409046..756063af7 100644 --- a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMod.java +++ b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMod.java @@ -27,6 +27,8 @@ package org.geysermc.geyser.platform.fabric; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import lombok.Getter; +import lombok.Setter; import net.fabricmc.api.EnvType; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; @@ -66,13 +68,14 @@ import java.util.Optional; import java.util.UUID; public class GeyserFabricMod implements ModInitializer, GeyserBootstrap { + + @Getter private static GeyserFabricMod instance; - - private boolean reloading; - private GeyserImpl geyser; private ModContainer mod; private Path dataFolder; + + @Setter private MinecraftServer server; private GeyserCommandManager geyserCommandManager; @@ -85,64 +88,45 @@ public class GeyserFabricMod implements ModInitializer, GeyserBootstrap { public void onInitialize() { instance = this; mod = FabricLoader.getInstance().getModContainer("geyser-fabric").orElseThrow(); - - this.onEnable(); - if (FabricLoader.getInstance().getEnvironmentType() == EnvType.SERVER) { - // Set as an event so we can get the proper IP and port if needed - ServerLifecycleEvents.SERVER_STARTED.register(this::startGeyser); - } + onGeyserInitialize(); } @Override - public void onEnable() { - dataFolder = FabricLoader.getInstance().getConfigDir().resolve("Geyser-Fabric"); - if (!dataFolder.toFile().exists()) { - //noinspection ResultOfMethodCallIgnored - dataFolder.toFile().mkdir(); + public void onGeyserInitialize() { + if (FabricLoader.getInstance().getEnvironmentType() == EnvType.SERVER) { + // Set as an event, so we can get the proper IP and port if needed + ServerLifecycleEvents.SERVER_STARTED.register((server) -> { + this.server = server; + onGeyserEnable(); + }); } - // Init dataFolder first as local language overrides call getConfigFolder() - GeyserLocale.init(this); + // These are only registered once + ServerLifecycleEvents.SERVER_STOPPING.register((server) -> onGeyserShutdown()); + ServerPlayConnectionEvents.JOIN.register((handler, $, $$) -> GeyserFabricUpdateListener.onPlayReady(handler)); - try { - File configFile = FileUtils.fileOrCopiedFromResource(dataFolder.resolve("config.yml").toFile(), "config.yml", - (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this); - this.geyserConfig = FileUtils.loadConfig(configFile, GeyserFabricConfiguration.class); - } catch (IOException ex) { - LogManager.getLogger("geyser-fabric").error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex); - ex.printStackTrace(); + dataFolder = FabricLoader.getInstance().getConfigDir().resolve("Geyser-Fabric"); + GeyserLocale.init(this); + if (!loadConfig()) { return; } - this.geyserLogger = new GeyserFabricLogger(geyserConfig.isDebugMode()); - GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); - this.geyser = GeyserImpl.load(PlatformType.FABRIC, this); - - if (server == null) { - // Server has yet to start - // Register onDisable so players are properly kicked - ServerLifecycleEvents.SERVER_STOPPING.register((server) -> onDisable()); - - ServerPlayConnectionEvents.JOIN.register((handler, $, $$) -> GeyserFabricUpdateListener.onPlayReady(handler)); - } else { - // Server has started and this is a reload - startGeyser(this.server); - reloading = false; - } } - /** - * Initialize core Geyser. - * A function, as it needs to be called in different places depending on if Geyser is being reloaded or not. - * - * @param server The minecraft server. - */ - public void startGeyser(MinecraftServer server) { - this.server = server; - - GeyserImpl.start(); + @Override + public void onGeyserEnable() { + if (GeyserImpl.getInstance().isReloading()) { + if (!loadConfig()) { + return; + } + this.geyserLogger.setDebug(geyserConfig.isDebugMode()); + GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); + } else { + this.geyserCommandManager = new GeyserCommandManager(geyser); + this.geyserCommandManager.init(); + } if (geyserConfig.isLegacyPingPassthrough()) { this.geyserPingPassthrough = GeyserLegacyPingPassthrough.init(geyser); @@ -150,8 +134,12 @@ public class GeyserFabricMod implements ModInitializer, GeyserBootstrap { this.geyserPingPassthrough = new ModPingPassthrough(server, geyserLogger); } - this.geyserCommandManager = new GeyserCommandManager(geyser); - this.geyserCommandManager.init(); + GeyserImpl.start(); + + // No need to re-register commands, or re-recreate the world manager when reloading + if (GeyserImpl.getInstance().isReloading()) { + return; + } this.geyserWorldManager = new GeyserFabricWorldManager(server); @@ -201,14 +189,19 @@ public class GeyserFabricMod implements ModInitializer, GeyserBootstrap { } @Override - public void onDisable() { + public void onGeyserDisable() { + if (geyser != null) { + geyser.disable(); + } + } + + @Override + public void onGeyserShutdown() { if (geyser != null) { geyser.shutdown(); geyser = null; } - if (!reloading) { - this.server = null; - } + this.server = null; } @Override @@ -291,11 +284,22 @@ public class GeyserFabricMod implements ModInitializer, GeyserBootstrap { } } - public void setReloading(boolean reloading) { - this.reloading = reloading; - } + @SuppressWarnings("BooleanMethodIsAlwaysInverted") + private boolean loadConfig() { + try { + if (!dataFolder.toFile().exists()) { + //noinspection ResultOfMethodCallIgnored + dataFolder.toFile().mkdir(); + } - public static GeyserFabricMod getInstance() { - return instance; + File configFile = FileUtils.fileOrCopiedFromResource(dataFolder.resolve("config.yml").toFile(), "config.yml", + (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this); + this.geyserConfig = FileUtils.loadConfig(configFile, GeyserFabricConfiguration.class); + return true; + } catch (IOException ex) { + LogManager.getLogger("geyser-fabric").error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex); + ex.printStackTrace(); + return false; + } } } diff --git a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/command/GeyserFabricCommandExecutor.java b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/command/GeyserFabricCommandExecutor.java index 732b28ca7..86b50d431 100644 --- a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/command/GeyserFabricCommandExecutor.java +++ b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/command/GeyserFabricCommandExecutor.java @@ -32,7 +32,6 @@ import net.minecraft.commands.CommandSourceStack; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.command.GeyserCommand; import org.geysermc.geyser.command.GeyserCommandExecutor; -import org.geysermc.geyser.platform.fabric.GeyserFabricMod; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.GeyserLocale; @@ -64,9 +63,6 @@ public class GeyserFabricCommandExecutor extends GeyserCommandExecutor implement sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.permission_fail", sender.locale())); return 0; } - if (this.command.name().equals("reload")) { - GeyserFabricMod.getInstance().setReloading(true); - } if (command.isBedrockOnly() && session == null) { sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.bedrock_only", sender.locale())); diff --git a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/mixin/client/IntegratedServerMixin.java b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/mixin/client/IntegratedServerMixin.java index af11174dc..999a077bb 100644 --- a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/mixin/client/IntegratedServerMixin.java +++ b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/mixin/client/IntegratedServerMixin.java @@ -57,7 +57,8 @@ public class IntegratedServerMixin implements GeyserServerPortGetter { private void onOpenToLan(GameType gameType, boolean cheatsAllowed, int port, CallbackInfoReturnable cir) { if (cir.getReturnValueZ()) { // If the LAN is opened, starts Geyser. - GeyserFabricMod.getInstance().startGeyser((MinecraftServer) (Object) this); + GeyserFabricMod.getInstance().setServer((MinecraftServer) (Object) this); + GeyserFabricMod.getInstance().onGeyserEnable(); // Ensure player locale has been loaded, in case it's different from Java system language GeyserLocale.loadGeyserLocale(this.minecraft.options.languageCode); // Give indication that Geyser is loaded diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java index a2a08c3bf..1bc1718d7 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java @@ -81,10 +81,6 @@ import java.util.UUID; import java.util.logging.Level; public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { - /** - * Determines if the plugin has been ran once before, including before /geyser reload. - */ - private static boolean INITIALIZED = false; private GeyserSpigotCommandManager geyserCommandManager; private GeyserSpigotConfiguration geyserConfig; @@ -102,6 +98,11 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { @Override public void onLoad() { + onGeyserInitialize(); + } + + @Override + public void onGeyserInitialize() { GeyserLocale.init(this); try { @@ -118,6 +119,7 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { getLogger().severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_server.message", "1.13.2")); getLogger().severe(""); getLogger().severe("*********************************************"); + Bukkit.getPluginManager().disablePlugin(this); return; } @@ -131,6 +133,7 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { getLogger().severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_server_type.message", "Paper")); getLogger().severe(""); getLogger().severe("*********************************************"); + Bukkit.getPluginManager().disablePlugin(this); return; } } @@ -143,86 +146,72 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { getLogger().severe("This version of Spigot is using an outdated version of netty. Please use Paper instead!"); getLogger().severe(""); getLogger().severe("*********************************************"); - return; - } - - // This is manually done instead of using Bukkit methods to save the config because otherwise comments get removed - try { - if (!getDataFolder().exists()) { - //noinspection ResultOfMethodCallIgnored - getDataFolder().mkdir(); - } - File configFile = FileUtils.fileOrCopiedFromResource(new File(getDataFolder(), "config.yml"), "config.yml", - (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this); - this.geyserConfig = FileUtils.loadConfig(configFile, GeyserSpigotConfiguration.class); - } catch (IOException ex) { - getLogger().log(Level.SEVERE, GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex); - ex.printStackTrace(); Bukkit.getPluginManager().disablePlugin(this); return; } + if (!loadConfig()) { + return; + } this.geyserLogger = GeyserPaperLogger.supported() ? new GeyserPaperLogger(this, getLogger(), geyserConfig.isDebugMode()) : new GeyserSpigotLogger(getLogger(), geyserConfig.isDebugMode()); - GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); + // Turn "(MC: 1.16.4)" into 1.16.4. + this.minecraftVersion = Bukkit.getServer().getVersion().split("\\(MC: ")[1].split("\\)")[0]; + this.geyser = GeyserImpl.load(PlatformType.SPIGOT, this); } @Override public void onEnable() { - if (this.geyserConfig == null) { - // We failed to initialize correctly - Bukkit.getPluginManager().disablePlugin(this); - return; - } - this.geyserCommandManager = new GeyserSpigotCommandManager(geyser); this.geyserCommandManager.init(); - if (!INITIALIZED) { - // Needs to be an anonymous inner class otherwise Bukkit complains about missing classes - Bukkit.getPluginManager().registerEvents(new Listener() { + // Because Bukkit locks its command map upon startup, we need to + // add our plugin commands in onEnable, but populating the executor + // can happen at any time (later in #onGeyserEnable()) + CommandMap commandMap = GeyserSpigotCommandManager.getCommandMap(); + for (Extension extension : this.geyserCommandManager.extensionCommands().keySet()) { + // Thanks again, Bukkit + try { + Constructor constructor = PluginCommand.class.getDeclaredConstructor(String.class, Plugin.class); + constructor.setAccessible(true); - @EventHandler - public void onServerLoaded(ServerLoadEvent event) { - // Wait until all plugins have loaded so Geyser can start - postStartup(); - } - }, this); + PluginCommand pluginCommand = constructor.newInstance(extension.description().id(), this); + pluginCommand.setDescription("The main command for the " + extension.name() + " Geyser extension!"); - // Because Bukkit locks its command map upon startup, we need to - // add our plugin commands in onEnable, but populating the executor - // can happen at any time - CommandMap commandMap = GeyserSpigotCommandManager.getCommandMap(); - for (Extension extension : this.geyserCommandManager.extensionCommands().keySet()) { - // Thanks again, Bukkit - try { - Constructor constructor = PluginCommand.class.getDeclaredConstructor(String.class, Plugin.class); - constructor.setAccessible(true); - - PluginCommand pluginCommand = constructor.newInstance(extension.description().id(), this); - pluginCommand.setDescription("The main command for the " + extension.name() + " Geyser extension!"); - - commandMap.register(extension.description().id(), "geyserext", pluginCommand); - } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException ex) { - this.geyserLogger.error("Failed to construct PluginCommand for extension " + extension.name(), ex); - } + commandMap.register(extension.description().id(), "geyserext", pluginCommand); + } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException ex) { + this.geyserLogger.error("Failed to construct PluginCommand for extension " + extension.name(), ex); } } - if (INITIALIZED) { - // Reload; continue with post startup - postStartup(); - } + // Needs to be an anonymous inner class otherwise Bukkit complains about missing classes + Bukkit.getPluginManager().registerEvents(new Listener() { + + @EventHandler + public void onServerLoaded(ServerLoadEvent event) { + if (event.getType() == ServerLoadEvent.LoadType.RELOAD) { + geyser.setShuttingDown(false); + } + onGeyserEnable(); + } + }, this); } - private void postStartup() { - GeyserImpl.start(); + public void onGeyserEnable() { + // Configs are loaded once early - so we can create the logger, then load extensions and finally register + // extension commands in #onEnable. To ensure reloading geyser also reloads the geyser config, this exists + if (GeyserImpl.getInstance().isReloading()) { + if (!loadConfig()) { + return; + } + this.geyserLogger.setDebug(this.geyserConfig.isDebugMode()); + GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); + } - // Turn "(MC: 1.16.4)" into 1.16.4. - this.minecraftVersion = Bukkit.getServer().getVersion().split("\\(MC: ")[1].split("\\)")[0]; + GeyserImpl.start(); if (geyserConfig.isLegacyPingPassthrough()) { this.geyserSpigotPingPassthrough = GeyserLegacyPingPassthrough.init(geyser); @@ -238,20 +227,16 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { } geyserLogger.debug("Spigot ping passthrough type: " + (this.geyserSpigotPingPassthrough == null ? null : this.geyserSpigotPingPassthrough.getClass())); - boolean isViaVersion = Bukkit.getPluginManager().getPlugin("ViaVersion") != null; - if (isViaVersion) { - try { - // Ensure that we have the latest 4.0.0 changes and not an older ViaVersion version - Class.forName("com.viaversion.viaversion.api.ViaManager"); - } catch (ClassNotFoundException e) { - GeyserSpigotVersionChecker.sendOutdatedViaVersionMessage(geyserLogger); - isViaVersion = false; - if (this.geyserConfig.isDebugMode()) { - e.printStackTrace(); - } - } + // Don't need to re-create the world manager/re-register commands/reinject when reloading + if (GeyserImpl.getInstance().isReloading()) { + return; } + boolean isViaVersion = Bukkit.getPluginManager().getPlugin("ViaVersion") != null; + + // Check to ensure the current setup can support the protocol version Geyser uses + GeyserSpigotVersionChecker.checkForSupportedProtocol(geyserLogger, isViaVersion); + // We want to do this late in the server startup process to allow plugins such as ViaVersion and ProtocolLib // To do their job injecting, then connect into *that* this.geyserInjector = new GeyserSpigotInjector(isViaVersion); @@ -278,6 +263,7 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { } else { geyserLogger.debug("Not using NMS adapter as it is disabled via system property."); } + if (this.geyserWorldManager == null) { // No NMS adapter this.geyserWorldManager = new GeyserSpigotWorldManager(this); @@ -302,72 +288,72 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { command.setExecutor(new GeyserSpigotCommandExecutor(this.geyser, commands)); } - if (!INITIALIZED) { - // Register permissions so they appear in, for example, LuckPerms' UI - // Re-registering permissions throws an error - for (Map.Entry entry : geyserCommandManager.commands().entrySet()) { + // Register permissions so they appear in, for example, LuckPerms' UI + // Re-registering permissions throws an error + for (Map.Entry entry : geyserCommandManager.commands().entrySet()) { + Command command = entry.getValue(); + if (command.aliases().contains(entry.getKey())) { + // Don't register aliases + continue; + } + + Bukkit.getPluginManager().addPermission(new Permission(command.permission(), + GeyserLocale.getLocaleStringLog(command.description()), + command.isSuggestedOpOnly() ? PermissionDefault.OP : PermissionDefault.TRUE)); + } + + // Register permissions for extension commands + for (Map.Entry> commandEntry : this.geyserCommandManager.extensionCommands().entrySet()) { + for (Map.Entry entry : commandEntry.getValue().entrySet()) { Command command = entry.getValue(); if (command.aliases().contains(entry.getKey())) { // Don't register aliases continue; } + if (command.permission().isBlank()) { + continue; + } + + // Avoid registering the same permission twice, e.g. for the extension help commands + if (Bukkit.getPluginManager().getPermission(command.permission()) != null) { + GeyserImpl.getInstance().getLogger().debug("Skipping permission " + command.permission() + " as it is already registered"); + continue; + } + Bukkit.getPluginManager().addPermission(new Permission(command.permission(), GeyserLocale.getLocaleStringLog(command.description()), command.isSuggestedOpOnly() ? PermissionDefault.OP : PermissionDefault.TRUE)); } - - // Register permissions for extension commands - for (Map.Entry> commandEntry : this.geyserCommandManager.extensionCommands().entrySet()) { - for (Map.Entry entry : commandEntry.getValue().entrySet()) { - Command command = entry.getValue(); - if (command.aliases().contains(entry.getKey())) { - // Don't register aliases - continue; - } - - if (command.permission().isBlank()) { - continue; - } - - // Avoid registering the same permission twice, e.g. for the extension help commands - if (Bukkit.getPluginManager().getPermission(command.permission()) != null) { - GeyserImpl.getInstance().getLogger().debug("Skipping permission " + command.permission() + " as it is already registered"); - continue; - } - - Bukkit.getPluginManager().addPermission(new Permission(command.permission(), - GeyserLocale.getLocaleStringLog(command.description()), - command.isSuggestedOpOnly() ? PermissionDefault.OP : PermissionDefault.TRUE)); - } - } - - Bukkit.getPluginManager().addPermission(new Permission(Constants.UPDATE_PERMISSION, - "Whether update notifications can be seen", PermissionDefault.OP)); - - // Events cannot be unregistered - re-registering results in duplicate firings - GeyserSpigotBlockPlaceListener blockPlaceListener = new GeyserSpigotBlockPlaceListener(geyser, this.geyserWorldManager); - Bukkit.getServer().getPluginManager().registerEvents(blockPlaceListener, this); - - Bukkit.getServer().getPluginManager().registerEvents(new GeyserPistonListener(geyser, this.geyserWorldManager), this); - - Bukkit.getServer().getPluginManager().registerEvents(new GeyserSpigotUpdateListener(), this); } + Bukkit.getPluginManager().addPermission(new Permission(Constants.UPDATE_PERMISSION, + "Whether update notifications can be seen", PermissionDefault.OP)); + + // Events cannot be unregistered - re-registering results in duplicate firings + GeyserSpigotBlockPlaceListener blockPlaceListener = new GeyserSpigotBlockPlaceListener(geyser, this.geyserWorldManager); + Bukkit.getServer().getPluginManager().registerEvents(blockPlaceListener, this); + + Bukkit.getServer().getPluginManager().registerEvents(new GeyserPistonListener(geyser, this.geyserWorldManager), this); + + Bukkit.getServer().getPluginManager().registerEvents(new GeyserSpigotUpdateListener(), this); + boolean brigadierSupported = CommodoreProvider.isSupported(); geyserLogger.debug("Brigadier supported? " + brigadierSupported); if (brigadierSupported) { GeyserBrigadierSupport.loadBrigadier(this, geyserCommand); } - - // Check to ensure the current setup can support the protocol version Geyser uses - GeyserSpigotVersionChecker.checkForSupportedProtocol(geyserLogger, isViaVersion); - - INITIALIZED = true; } @Override - public void onDisable() { + public void onGeyserDisable() { + if (geyser != null) { + geyser.disable(); + } + } + + @Override + public void onGeyserShutdown() { if (geyser != null) { geyser.shutdown(); } @@ -376,6 +362,11 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { } } + @Override + public void onDisable() { + this.onGeyserShutdown(); + } + @Override public GeyserSpigotConfiguration getGeyserConfig() { return geyserConfig; @@ -470,4 +461,25 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { } return false; } + + @SuppressWarnings("BooleanMethodIsAlwaysInverted") + private boolean loadConfig() { + // This is manually done instead of using Bukkit methods to save the config because otherwise comments get removed + try { + if (!getDataFolder().exists()) { + //noinspection ResultOfMethodCallIgnored + getDataFolder().mkdir(); + } + File configFile = FileUtils.fileOrCopiedFromResource(new File(getDataFolder(), "config.yml"), "config.yml", + (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this); + this.geyserConfig = FileUtils.loadConfig(configFile, GeyserSpigotConfiguration.class); + } catch (IOException ex) { + getLogger().log(Level.SEVERE, GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex); + ex.printStackTrace(); + Bukkit.getPluginManager().disablePlugin(this); + return false; + } + + return true; + } } diff --git a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java index 9f2208ea8..039004867 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java @@ -39,9 +39,9 @@ import org.apache.logging.log4j.core.Appender; import org.apache.logging.log4j.core.Logger; import org.apache.logging.log4j.core.appender.ConsoleAppender; import org.checkerframework.checker.nullness.qual.NonNull; -import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.command.GeyserCommandManager; import org.geysermc.geyser.configuration.GeyserConfiguration; import org.geysermc.geyser.configuration.GeyserJacksonConfiguration; @@ -59,7 +59,12 @@ import java.lang.reflect.Method; import java.nio.file.Path; import java.nio.file.Paths; import java.text.MessageFormat; -import java.util.*; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.UUID; import java.util.stream.Collectors; public class GeyserStandaloneBootstrap implements GeyserBootstrap { @@ -68,11 +73,10 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap { private GeyserStandaloneConfiguration geyserConfig; private GeyserStandaloneLogger geyserLogger; private IGeyserPingPassthrough geyserPingPassthrough; - private GeyserStandaloneGUI gui; - @Getter private boolean useGui = System.console() == null && !isHeadless(); + private Logger log4jLogger; private String configFilename = "config.yml"; private GeyserImpl geyser; @@ -161,23 +165,19 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap { } } } - bootstrap.onEnable(useGuiOpts, configFilenameOpt); - } - - public void onEnable(boolean useGui, String configFilename) { - this.configFilename = configFilename; - this.useGui = useGui; - this.onEnable(); + bootstrap.useGui = useGuiOpts; + bootstrap.configFilename = configFilenameOpt; + bootstrap.onGeyserInitialize(); } @Override - public void onEnable() { - Logger logger = (Logger) LogManager.getRootLogger(); - for (Appender appender : logger.getAppenders().values()) { + public void onGeyserInitialize() { + log4jLogger = (Logger) LogManager.getRootLogger(); + for (Appender appender : log4jLogger.getAppenders().values()) { // Remove the appender that is not in use // Prevents multiple appenders/double logging and removes harmless errors if ((useGui && appender instanceof TerminalConsoleAppender) || (!useGui && appender instanceof ConsoleAppender)) { - logger.removeAppender(appender); + log4jLogger.removeAppender(appender); } } @@ -190,7 +190,12 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap { } LoopbackUtil.checkAndApplyLoopback(geyserLogger); - + + this.onGeyserEnable(); + } + + @Override + public void onGeyserEnable() { try { File configFile = FileUtils.fileOrCopiedFromResource(new File(configFilename), "config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this); @@ -215,14 +220,15 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap { GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); // Allow libraries like Protocol to have their debug information passthrough - logger.get().setLevel(geyserConfig.isDebugMode() ? Level.DEBUG : Level.INFO); + log4jLogger.get().setLevel(geyserConfig.isDebugMode() ? Level.DEBUG : Level.INFO); geyser = GeyserImpl.load(PlatformType.STANDALONE, this); - GeyserImpl.start(); geyserCommandManager = new GeyserCommandManager(geyser); geyserCommandManager.init(); + GeyserImpl.start(); + if (gui != null) { gui.enableCommands(geyser.getScheduledThread(), geyserCommandManager); } @@ -250,7 +256,14 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap { } @Override - public void onDisable() { + public void onGeyserDisable() { + // We can re-register commands on standalone, so why not + GeyserImpl.getInstance().commandManager().getCommands().clear(); + geyser.disable(); + } + + @Override + public void onGeyserShutdown() { geyser.shutdown(); System.exit(0); } diff --git a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneLogger.java b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneLogger.java index 3c29bc648..3a34920ce 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneLogger.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneLogger.java @@ -49,7 +49,7 @@ public class GeyserStandaloneLogger extends SimpleTerminalConsole implements Gey @Override protected void shutdown() { - GeyserImpl.getInstance().getBootstrap().onDisable(); + GeyserImpl.getInstance().getBootstrap().onGeyserShutdown(); } @Override diff --git a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java index bd3d6085a..347a47d63 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java @@ -32,10 +32,10 @@ import com.velocitypowered.api.event.proxy.ListenerBoundEvent; import com.velocitypowered.api.event.proxy.ProxyInitializeEvent; import com.velocitypowered.api.event.proxy.ProxyShutdownEvent; import com.velocitypowered.api.network.ListenerType; +import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.api.plugin.Plugin; import com.velocitypowered.api.proxy.ProxyServer; import lombok.Getter; -import net.kyori.adventure.util.Codec; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.GeyserBootstrap; @@ -46,6 +46,7 @@ import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.command.GeyserCommandManager; import org.geysermc.geyser.configuration.GeyserConfiguration; import org.geysermc.geyser.dump.BootstrapDumpInfo; +import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough; import org.geysermc.geyser.ping.IGeyserPingPassthrough; import org.geysermc.geyser.platform.velocity.command.GeyserVelocityCommandExecutor; @@ -63,12 +64,6 @@ import java.util.UUID; @Plugin(id = "geyser", name = GeyserImpl.NAME + "-Velocity", version = GeyserImpl.VERSION, url = "https://geysermc.org", authors = "GeyserMC") public class GeyserVelocityPlugin implements GeyserBootstrap { - - /** - * Determines if the plugin has been ran once before, including before /geyser reload. - */ - private static boolean INITIALIZED = false; - @Inject private Logger logger; @@ -90,52 +85,54 @@ public class GeyserVelocityPlugin implements GeyserBootstrap { private final Path configFolder = Paths.get("plugins/" + GeyserImpl.NAME + "-Velocity/"); @Override - public void onEnable() { - try { - Codec.class.getMethod("codec", Codec.Decoder.class, Codec.Encoder.class); - } catch (NoSuchMethodException e) { - // velocitypowered.com has a build that is very outdated - logger.error("Please download Velocity from https://papermc.io/downloads#Velocity - the 'stable' Velocity version " + - "that has likely been downloaded is very outdated and does not support 1.19."); - return; - } - + public void onGeyserInitialize() { GeyserLocale.init(this); - try { - if (!configFolder.toFile().exists()) - //noinspection ResultOfMethodCallIgnored - configFolder.toFile().mkdirs(); - File configFile = FileUtils.fileOrCopiedFromResource(configFolder.resolve("config.yml").toFile(), - "config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this); - this.geyserConfig = FileUtils.loadConfig(configFile, GeyserVelocityConfiguration.class); - } catch (IOException ex) { - logger.error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex); - ex.printStackTrace(); - return; + if (!ProtocolVersion.isSupported(GameProtocol.getJavaProtocolVersion())) { + logger.error(" / \\"); + logger.error(" / \\"); + logger.error(" / | \\"); + logger.error(" / | \\ " + GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_proxy", proxyServer.getVersion().getName())); + logger.error(" / \\ " + GeyserLocale.getLocaleStringLog("geyser.may_not_work_as_intended_all_caps")); + logger.error(" / o \\"); + logger.error("/_____________\\"); } + if (!loadConfig()) { + return; + } this.geyserLogger = new GeyserVelocityLogger(logger, geyserConfig.isDebugMode()); GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); this.geyser = GeyserImpl.load(PlatformType.VELOCITY, this); - - // Hack: Normally triggered by ListenerBoundEvent, but that doesn't fire on /geyser reload - if (INITIALIZED) { - this.postStartup(); - } + this.geyserInjector = new GeyserVelocityInjector(proxyServer); } - private void postStartup() { - GeyserImpl.start(); - - if (!INITIALIZED) { - this.geyserInjector = new GeyserVelocityInjector(proxyServer); - // Will be initialized after the proxy has been bound + @Override + public void onGeyserEnable() { + if (GeyserImpl.getInstance().isReloading()) { + if (!loadConfig()) { + return; + } + this.geyserLogger.setDebug(geyserConfig.isDebugMode()); + GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); + } else { + this.geyserCommandManager = new GeyserCommandManager(geyser); + this.geyserCommandManager.init(); } - this.geyserCommandManager = new GeyserCommandManager(geyser); - this.geyserCommandManager.init(); + GeyserImpl.start(); + + if (geyserConfig.isLegacyPingPassthrough()) { + this.geyserPingPassthrough = GeyserLegacyPingPassthrough.init(geyser); + } else { + this.geyserPingPassthrough = new GeyserVelocityPingPassthrough(proxyServer); + } + + // No need to re-register commands when reloading + if (GeyserImpl.getInstance().isReloading()) { + return; + } this.commandManager.register("geyser", new GeyserVelocityCommandExecutor(geyser, geyserCommandManager.getCommands())); for (Map.Entry> entry : this.geyserCommandManager.extensionCommands().entrySet()) { @@ -147,17 +144,18 @@ public class GeyserVelocityPlugin implements GeyserBootstrap { this.commandManager.register(entry.getKey().description().id(), new GeyserVelocityCommandExecutor(this.geyser, commands)); } - if (geyserConfig.isLegacyPingPassthrough()) { - this.geyserPingPassthrough = GeyserLegacyPingPassthrough.init(geyser); - } else { - this.geyserPingPassthrough = new GeyserVelocityPingPassthrough(proxyServer); - } - proxyServer.getEventManager().register(this, new GeyserVelocityUpdateListener()); } @Override - public void onDisable() { + public void onGeyserDisable() { + if (geyser != null) { + geyser.disable(); + } + } + + @Override + public void onGeyserShutdown() { if (geyser != null) { geyser.shutdown(); } @@ -188,26 +186,24 @@ public class GeyserVelocityPlugin implements GeyserBootstrap { @Subscribe public void onInit(ProxyInitializeEvent event) { - onEnable(); + this.onGeyserInitialize(); } @Subscribe public void onShutdown(ProxyShutdownEvent event) { - onDisable(); + this.onGeyserShutdown(); } @Subscribe public void onProxyBound(ListenerBoundEvent event) { if (event.getListenerType() == ListenerType.MINECRAFT) { // Once listener is bound, do our startup process - this.postStartup(); + this.onGeyserEnable(); if (geyserInjector != null) { // After this bound, we know that the channel initializer cannot change without it being ineffective for Velocity, too geyserInjector.initializeLocalChannel(this); } - - INITIALIZED = true; } } @@ -242,4 +238,21 @@ public class GeyserVelocityPlugin implements GeyserBootstrap { } return false; } + + @SuppressWarnings("BooleanMethodIsAlwaysInverted") + private boolean loadConfig() { + try { + if (!configFolder.toFile().exists()) + //noinspection ResultOfMethodCallIgnored + configFolder.toFile().mkdirs(); + File configFile = FileUtils.fileOrCopiedFromResource(configFolder.resolve("config.yml").toFile(), + "config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this); + this.geyserConfig = FileUtils.loadConfig(configFile, GeyserVelocityConfiguration.class); + } catch (IOException ex) { + logger.error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex); + ex.printStackTrace(); + return false; + } + return true; + } } diff --git a/core/src/main/java/org/geysermc/geyser/GeyserBootstrap.java b/core/src/main/java/org/geysermc/geyser/GeyserBootstrap.java index 4dbc1dca3..a9414d9d0 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserBootstrap.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserBootstrap.java @@ -44,14 +44,28 @@ public interface GeyserBootstrap { GeyserWorldManager DEFAULT_CHUNK_MANAGER = new GeyserWorldManager(); /** - * Called when the GeyserBootstrap is enabled + * Called when the GeyserBootstrap is initialized. + * This will only be called once, when Geyser is loading. Calling this must + * happen before {@link #onGeyserEnable()}, since this "sets up" Geyser. */ - void onEnable(); + void onGeyserInitialize(); /** - * Called when the GeyserBootstrap is disabled + * Called when the GeyserBootstrap is enabled/reloaded. + * This starts Geyser, after which, Geyser is in a player-accepting state. */ - void onDisable(); + void onGeyserEnable(); + + /** + * Called when the GeyserBootstrap is disabled - either before a reload, + * of before fully shutting down. + */ + void onGeyserDisable(); + + /** + * Called when the GeyserBootstrap is shutting down. + */ + void onGeyserShutdown(); /** * Returns the current GeyserConfiguration diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index e9ea08260..5ed0c3947 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -58,9 +58,7 @@ import org.geysermc.floodgate.news.NewsItemAction; import org.geysermc.geyser.api.GeyserApi; import org.geysermc.geyser.api.event.EventBus; import org.geysermc.geyser.api.event.EventRegistrar; -import org.geysermc.geyser.api.event.lifecycle.GeyserPostInitializeEvent; -import org.geysermc.geyser.api.event.lifecycle.GeyserPreInitializeEvent; -import org.geysermc.geyser.api.event.lifecycle.GeyserShutdownEvent; +import org.geysermc.geyser.api.event.lifecycle.*; import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.api.network.BedrockListener; import org.geysermc.geyser.api.network.RemoteServer; @@ -145,6 +143,7 @@ public class GeyserImpl implements GeyserApi { private UnixSocketClientListener erosionUnixListener; + @Setter private volatile boolean shuttingDown = false; private ScheduledExecutorService scheduledThread; @@ -162,8 +161,14 @@ public class GeyserImpl implements GeyserApi { @Getter(AccessLevel.NONE) private Map savedRefreshTokens; + @Getter private static GeyserImpl instance; + /** + * Determines if we're currently reloading. Replaces per-bootstrap reload checks + */ + private volatile boolean isReloading; + private GeyserImpl(PlatformType platformType, GeyserBootstrap bootstrap) { instance = this; @@ -172,13 +177,16 @@ public class GeyserImpl implements GeyserApi { this.platformType = platformType; this.bootstrap = bootstrap; - GeyserLocale.finalizeDefaultLocale(this); - /* Initialize event bus */ this.eventBus = new GeyserEventBus(); - /* Load Extensions */ + /* Create Extension Manager */ this.extensionManager = new GeyserExtensionManager(); + + /* Finalize locale loading now that we know the default locale from the config */ + GeyserLocale.finalizeDefaultLocale(this); + + /* Load Extensions */ this.extensionManager.init(); this.eventBus.fire(new GeyserPreInitializeEvent(this.extensionManager, this.eventBus)); } @@ -236,11 +244,17 @@ public class GeyserImpl implements GeyserApi { } else if (config.getRemote().authType() == AuthType.FLOODGATE) { VersionCheckUtils.checkForOutdatedFloodgate(logger); } + + VersionCheckUtils.checkForOutdatedJava(logger); } private void startInstance() { this.scheduledThread = Executors.newSingleThreadScheduledExecutor(new DefaultThreadFactory("Geyser Scheduled Thread")); + if (isReloading) { + // If we're reloading, the default locale in the config might have changed. + GeyserLocale.finalizeDefaultLocale(this); + } GeyserLogger logger = bootstrap.getGeyserLogger(); GeyserConfiguration config = bootstrap.getGeyserConfig(); @@ -536,12 +550,15 @@ public class GeyserImpl implements GeyserApi { newsHandler.handleNews(null, NewsItemAction.ON_SERVER_STARTED); - this.eventBus.fire(new GeyserPostInitializeEvent(this.extensionManager, this.eventBus)); + if (isReloading) { + this.eventBus.fire(new GeyserPostReloadEvent(this.extensionManager, this.eventBus)); + } else { + this.eventBus.fire(new GeyserPostInitializeEvent(this.extensionManager, this.eventBus)); + } + if (config.isNotifyOnNewBedrockUpdate()) { VersionCheckUtils.checkForGeyserUpdate(this::getLogger); } - - VersionCheckUtils.checkForOutdatedJava(logger); } @Override @@ -600,9 +617,8 @@ public class GeyserImpl implements GeyserApi { return session.transfer(address, port); } - public void shutdown() { + public void disable() { bootstrap.getGeyserLogger().info(GeyserLocale.getLocaleStringLog("geyser.core.shutdown")); - shuttingDown = true; if (sessionManager.size() >= 1) { bootstrap.getGeyserLogger().info(GeyserLocale.getLocaleStringLog("geyser.core.shutdown.kick.log", sessionManager.size())); @@ -616,7 +632,6 @@ public class GeyserImpl implements GeyserApi { skinUploader.close(); } newsHandler.shutdown(); - this.commandManager().getCommands().clear(); if (this.erosionUnixListener != null) { this.erosionUnixListener.close(); @@ -624,16 +639,29 @@ public class GeyserImpl implements GeyserApi { Registries.RESOURCE_PACKS.get().clear(); + bootstrap.getGeyserLogger().info(GeyserLocale.getLocaleStringLog("geyser.core.shutdown.done")); + } + + public void shutdown() { + shuttingDown = true; + this.disable(); + this.commandManager().getCommands().clear(); + + // Disable extensions, fire the shutdown event this.eventBus.fire(new GeyserShutdownEvent(this.extensionManager, this.eventBus)); this.extensionManager.disableExtensions(); bootstrap.getGeyserLogger().info(GeyserLocale.getLocaleStringLog("geyser.core.shutdown.done")); } - public void reload() { - shutdown(); - this.extensionManager.enableExtensions(); - bootstrap.onEnable(); + public void reloadGeyser() { + isReloading = true; + this.eventBus.fire(new GeyserPreReloadEvent(this.extensionManager, this.eventBus)); + + bootstrap.onGeyserDisable(); + bootstrap.onGeyserEnable(); + + isReloading = false; } /** @@ -744,9 +772,7 @@ public class GeyserImpl implements GeyserApi { throw new RuntimeException("Geyser has not been loaded yet!"); } - // We've been reloaded - if (instance.isShuttingDown()) { - instance.shuttingDown = false; + if (getInstance().isReloading()) { instance.startInstance(); } else { instance.initialize(); @@ -797,8 +823,4 @@ public class GeyserImpl implements GeyserApi { } }); } - - public static GeyserImpl getInstance() { - return instance; - } } diff --git a/core/src/main/java/org/geysermc/geyser/command/GeyserCommandManager.java b/core/src/main/java/org/geysermc/geyser/command/GeyserCommandManager.java index d646845c7..72ed22381 100644 --- a/core/src/main/java/org/geysermc/geyser/command/GeyserCommandManager.java +++ b/core/src/main/java/org/geysermc/geyser/command/GeyserCommandManager.java @@ -86,7 +86,7 @@ public class GeyserCommandManager { registerBuiltInCommand(new StopCommand(geyser, "stop", "geyser.commands.stop.desc", "geyser.command.stop")); } - if (this.geyser.extensionManager().extensions().size() > 0) { + if (!this.geyser.extensionManager().extensions().isEmpty()) { registerBuiltInCommand(new ExtensionsCommand(this.geyser, "extensions", "geyser.commands.extensions.desc", "geyser.command.extensions")); } diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/ReloadCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/ReloadCommand.java index a3cd8fa4c..987860238 100644 --- a/core/src/main/java/org/geysermc/geyser/command/defaults/ReloadCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/ReloadCommand.java @@ -55,7 +55,7 @@ public class ReloadCommand extends GeyserCommand { geyser.getSessionManager().disconnectAll("geyser.commands.reload.kick"); //FIXME Without the tiny wait, players do not get kicked - same happens when Geyser tries to disconnect all sessions on shutdown - geyser.getScheduledThread().schedule(geyser::reload, 10, TimeUnit.MILLISECONDS); + geyser.getScheduledThread().schedule(geyser::reloadGeyser, 10, TimeUnit.MILLISECONDS); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/StopCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/StopCommand.java index 7db539cc5..1cd3050c9 100644 --- a/core/src/main/java/org/geysermc/geyser/command/defaults/StopCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/StopCommand.java @@ -52,7 +52,7 @@ public class StopCommand extends GeyserCommand { return; } - geyser.getBootstrap().onDisable(); + geyser.getBootstrap().onGeyserShutdown(); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java index df5eb36f7..59485b2cd 100644 --- a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java +++ b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java @@ -166,7 +166,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { @Override public PacketSignal handle(LoginPacket loginPacket) { - if (geyser.isShuttingDown()) { + if (geyser.isShuttingDown() || geyser.isReloading()) { // Don't allow new players in if we're no longer operating session.disconnect(GeyserLocale.getLocaleStringLog("geyser.core.shutdown.kick.message")); return PacketSignal.HANDLED; diff --git a/core/src/main/java/org/geysermc/geyser/scoreboard/ScoreboardUpdater.java b/core/src/main/java/org/geysermc/geyser/scoreboard/ScoreboardUpdater.java index 8c1ef5296..395eb9576 100644 --- a/core/src/main/java/org/geysermc/geyser/scoreboard/ScoreboardUpdater.java +++ b/core/src/main/java/org/geysermc/geyser/scoreboard/ScoreboardUpdater.java @@ -62,7 +62,7 @@ public final class ScoreboardUpdater extends Thread { @Override public void run() { - while (!geyser.isShuttingDown()) { + while (!geyser.isShuttingDown() && !geyser.isReloading()) { try { long timeTillAction = getTimeTillNextAction(); if (timeTillAction > 0) { diff --git a/core/src/main/java/org/geysermc/geyser/util/EntityUtils.java b/core/src/main/java/org/geysermc/geyser/util/EntityUtils.java index 583e15c23..f040fd0ba 100644 --- a/core/src/main/java/org/geysermc/geyser/util/EntityUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/EntityUtils.java @@ -266,6 +266,7 @@ public final class EntityUtils { * Convert Java GameMode to Bedrock GameType * Needed to account for ordinal differences (spectator is 3 in Java, 6 in Bedrock) */ + @SuppressWarnings("deprecation") // Must use survival_viewer due to limitations on Bedrock's spectator gamemode public static GameType toBedrockGamemode(GameMode gamemode) { return switch (gamemode) { case CREATIVE -> GameType.CREATIVE; From e97258f6253291d4d7a03c13fc6a39c462545e8d Mon Sep 17 00:00:00 2001 From: byquanton <32410361+byquanton@users.noreply.github.com> Date: Thu, 15 Feb 2024 14:57:51 +0100 Subject: [PATCH 186/344] Fix: Nametags not showing up after respawn (#4445) --- .../org/geysermc/geyser/entity/type/player/PlayerEntity.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java index 3578ac82b..c3b04402b 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java @@ -377,6 +377,7 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity { if (needsUpdate) { dirtyMetadata.put(EntityDataTypes.NAME, this.nametag); + dirtyMetadata.put(EntityDataTypes.NAMETAG_ALWAYS_SHOW, (byte) 1); } } From 8b170d656e6842df0ca02c394c2355ebcfbf69ef Mon Sep 17 00:00:00 2001 From: byquanton <32410361+byquanton@users.noreply.github.com> Date: Thu, 15 Feb 2024 22:22:46 +0100 Subject: [PATCH 187/344] Fix: Nametags are not shown in some other cases (#4447) --- .../geysermc/geyser/entity/type/player/PlayerEntity.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java index c3b04402b..9e3888138 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java @@ -120,9 +120,6 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity { super.initializeMetadata(); // For the OptionalPack, set all bits as invisible by default as this matches Java Edition behavior dirtyMetadata.put(EntityDataTypes.MARK_VARIANT, 0xff); - // Since 1.20.60, the nametag does not show properly if this is not set :/ - // The nametag does disappear properly when the player is invisible though. - dirtyMetadata.put(EntityDataTypes.NAMETAG_ALWAYS_SHOW, (byte) 1); } @Override @@ -154,6 +151,10 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity { addPlayerPacket.setGameType(GameType.SURVIVAL); //TODO addPlayerPacket.setAbilityLayers(BASE_ABILITY_LAYER); // Recommended to be added since 1.19.10, but only needed here for permissions viewing addPlayerPacket.getMetadata().putFlags(flags); + + // Since 1.20.60, the nametag does not show properly if this is not set :/ + // The nametag does disappear properly when the player is invisible though. + dirtyMetadata.put(EntityDataTypes.NAMETAG_ALWAYS_SHOW, (byte) 1); dirtyMetadata.apply(addPlayerPacket.getMetadata()); setFlagsDirty(false); @@ -377,7 +378,6 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity { if (needsUpdate) { dirtyMetadata.put(EntityDataTypes.NAME, this.nametag); - dirtyMetadata.put(EntityDataTypes.NAMETAG_ALWAYS_SHOW, (byte) 1); } } From aca368e33230e25eb4a80a929d6f833bf1d9899f Mon Sep 17 00:00:00 2001 From: RK_01 <50594595+RaphiMC@users.noreply.github.com> Date: Mon, 19 Feb 2024 22:25:49 +0100 Subject: [PATCH 188/344] Implemented ViaProxy bootstrap (#4201) * Implemented ViaProxy bootstrap * Applied requested changes to code * Override indra settings to Java 17 * Removed explicit java source/target version * Added ViaProxy artifact to build.yml * Added ViaProxy artifact to pullrequest.yml * Updated ViaProxy API usage * Implemented floodgate support for ViaProxy * Depend on stable ViaProxy release * Initialize command manager and ping passthrough before Geyser#start * Revert "Initialize command manager and ping passthrough before Geyser#start" This reverts commit 39356071c4d59d82469477f160919365f88d39c7. * Some ping passthrough improvements * Merged code properly * Updated ViaProxy API usage * Implemented better command handling * Updated ViaProxy and Geyser API usage * Combine bootstrap and plugin into one class * Minor code improvements * Call Geyser shutdown on plugin disable * Only call disable if Geyser was enabled once * Don't send two shutdown done messages * Use setter for enabled boolean --- .github/workflows/build.yml | 7 + .github/workflows/pullrequest.yml | 7 + .../geyser/api/util/PlatformType.java | 1 + bootstrap/viaproxy/build.gradle.kts | 26 ++ .../viaproxy/GeyserViaProxyConfiguration.java | 53 +++++ .../viaproxy/GeyserViaProxyDumpInfo.java | 67 ++++++ .../viaproxy/GeyserViaProxyLogger.java | 88 +++++++ .../platform/viaproxy/GeyserViaProxyMain.java | 45 ++++ .../viaproxy/GeyserViaProxyPlugin.java | 224 ++++++++++++++++++ .../viaproxy/src/main/resources/viaproxy.yml | 5 + .../kotlin/geyser.base-conventions.gradle.kts | 6 +- build.gradle.kts | 3 +- .../java/org/geysermc/geyser/GeyserImpl.java | 39 +-- .../java/JavaLoginDisconnectTranslator.java | 2 +- gradle/libs.versions.toml | 2 + settings.gradle.kts | 4 +- 16 files changed, 559 insertions(+), 20 deletions(-) create mode 100644 bootstrap/viaproxy/build.gradle.kts create mode 100644 bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyConfiguration.java create mode 100644 bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyDumpInfo.java create mode 100644 bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyLogger.java create mode 100644 bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyMain.java create mode 100644 bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyPlugin.java create mode 100644 bootstrap/viaproxy/src/main/resources/viaproxy.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6c5c15248..827136b4a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -77,6 +77,13 @@ jobs: name: Geyser Velocity path: bootstrap/velocity/build/libs/Geyser-Velocity.jar if-no-files-found: error + - name: Archive artifacts (Geyser ViaProxy) + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 + if: success() + with: + name: Geyser ViaProxy + path: bootstrap/viaproxy/build/libs/Geyser-ViaProxy.jar + if-no-files-found: error - name: Publish to Maven Repository if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 797d68767..f2c8f5d8d 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -87,3 +87,10 @@ jobs: name: Geyser Velocity path: geyser/bootstrap/velocity/build/libs/Geyser-Velocity.jar if-no-files-found: error + - name: Archive artifacts (Geyser ViaProxy) + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 + if: success() + with: + name: Geyser ViaProxy + path: geyser/bootstrap/viaproxy/build/libs/Geyser-ViaProxy.jar + if-no-files-found: error diff --git a/api/src/main/java/org/geysermc/geyser/api/util/PlatformType.java b/api/src/main/java/org/geysermc/geyser/api/util/PlatformType.java index 815381d6b..1abdc0230 100644 --- a/api/src/main/java/org/geysermc/geyser/api/util/PlatformType.java +++ b/api/src/main/java/org/geysermc/geyser/api/util/PlatformType.java @@ -40,4 +40,5 @@ public record PlatformType(String platformName) { public static final PlatformType SPONGE = new PlatformType("Sponge"); public static final PlatformType STANDALONE = new PlatformType("Standalone"); public static final PlatformType VELOCITY = new PlatformType("Velocity"); + public static final PlatformType VIAPROXY = new PlatformType("ViaProxy"); } diff --git a/bootstrap/viaproxy/build.gradle.kts b/bootstrap/viaproxy/build.gradle.kts new file mode 100644 index 000000000..4d5d4f949 --- /dev/null +++ b/bootstrap/viaproxy/build.gradle.kts @@ -0,0 +1,26 @@ +dependencies { + api(projects.core) +} + +platformRelocate("net.kyori") +platformRelocate("org.yaml") +platformRelocate("it.unimi.dsi.fastutil") +platformRelocate("org.cloudburstmc.netty") + +// These dependencies are already present on the platform +provided(libs.viaproxy) + +application { + mainClass.set("org.geysermc.geyser.platform.viaproxy.GeyserViaProxyMain") +} + +tasks.withType { + archiveBaseName.set("Geyser-ViaProxy") + + dependencies { + exclude(dependency("com.google.*:.*")) + exclude(dependency("io.netty:.*")) + exclude(dependency("org.slf4j:.*")) + exclude(dependency("org.ow2.asm:.*")) + } +} diff --git a/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyConfiguration.java b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyConfiguration.java new file mode 100644 index 000000000..ad249eb3b --- /dev/null +++ b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyConfiguration.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2019-2023 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.platform.viaproxy; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import net.raphimc.vialegacy.api.LegacyProtocolVersion; +import net.raphimc.viaproxy.cli.options.Options; +import org.geysermc.geyser.configuration.GeyserJacksonConfiguration; + +import java.io.File; +import java.nio.file.Path; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class GeyserViaProxyConfiguration extends GeyserJacksonConfiguration { + + @Override + public Path getFloodgateKeyPath() { + return new File(GeyserViaProxyPlugin.ROOT_FOLDER, this.getFloodgateKeyFile()).toPath(); + } + + @Override + public int getPingPassthroughInterval() { + int interval = super.getPingPassthroughInterval(); + if (interval < 15 && Options.PROTOCOL_VERSION != null && Options.PROTOCOL_VERSION.olderThanOrEqualTo(LegacyProtocolVersion.r1_6_4)) { + // <= 1.6.4 servers sometimes block incoming connections from an IP address if too many connections are made + interval = 15; + } + return interval; + } + +} diff --git a/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyDumpInfo.java b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyDumpInfo.java new file mode 100644 index 000000000..08f3d5371 --- /dev/null +++ b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyDumpInfo.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2019-2023 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.platform.viaproxy; + +import lombok.Getter; +import net.raphimc.viaproxy.ViaProxy; +import net.raphimc.viaproxy.cli.options.Options; +import net.raphimc.viaproxy.plugins.ViaProxyPlugin; +import org.geysermc.geyser.dump.BootstrapDumpInfo; +import org.geysermc.geyser.text.AsteriskSerializer; + +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +@Getter +public class GeyserViaProxyDumpInfo extends BootstrapDumpInfo { + + private final String platformVersion; + private final boolean onlineMode; + + @AsteriskSerializer.Asterisk(isIp = true) + private final String serverIP; + private final int serverPort; + private final List plugins; + + public GeyserViaProxyDumpInfo() { + this.platformVersion = ViaProxy.VERSION; + this.onlineMode = Options.ONLINE_MODE; + if (Options.BIND_ADDRESS instanceof InetSocketAddress inetSocketAddress) { + this.serverIP = inetSocketAddress.getHostString(); + this.serverPort = inetSocketAddress.getPort(); + } else { + this.serverIP = "unsupported"; + this.serverPort = 0; + } + this.plugins = new ArrayList<>(); + + for (ViaProxyPlugin plugin : ViaProxy.getPluginManager().getPlugins()) { + this.plugins.add(new PluginInfo(true, plugin.getName(), plugin.getVersion(), "unknown", Collections.singletonList(plugin.getAuthor()))); + } + } + +} diff --git a/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyLogger.java b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyLogger.java new file mode 100644 index 000000000..10f414b51 --- /dev/null +++ b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyLogger.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2019-2023 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.platform.viaproxy; + +import net.raphimc.viaproxy.cli.ConsoleFormatter; +import org.apache.logging.log4j.Logger; +import org.geysermc.geyser.GeyserLogger; +import org.geysermc.geyser.command.GeyserCommandSource; + +public class GeyserViaProxyLogger implements GeyserLogger, GeyserCommandSource { + + private final Logger logger; + private boolean debug; + + public GeyserViaProxyLogger(Logger logger) { + this.logger = logger; + } + + @Override + public void severe(String message) { + this.logger.fatal(ConsoleFormatter.convert(message)); + } + + @Override + public void severe(String message, Throwable error) { + this.logger.fatal(ConsoleFormatter.convert(message), error); + } + + @Override + public void error(String message) { + this.logger.error(ConsoleFormatter.convert(message)); + } + + @Override + public void error(String message, Throwable error) { + this.logger.error(ConsoleFormatter.convert(message), error); + } + + @Override + public void warning(String message) { + this.logger.warn(ConsoleFormatter.convert(message)); + } + + @Override + public void info(String message) { + this.logger.info(ConsoleFormatter.convert(message)); + } + + @Override + public void debug(String message) { + if (this.debug) { + this.logger.debug(ConsoleFormatter.convert(message)); + } + } + + @Override + public void setDebug(boolean debug) { + this.debug = debug; + } + + @Override + public boolean isDebug() { + return this.debug; + } + +} diff --git a/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyMain.java b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyMain.java new file mode 100644 index 000000000..675c92534 --- /dev/null +++ b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyMain.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2019-2023 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.platform.viaproxy; + +import net.raphimc.viaproxy.plugins.PluginManager; +import org.geysermc.geyser.GeyserMain; + +public class GeyserViaProxyMain extends GeyserMain { + + public static void main(String[] args) { + new GeyserViaProxyMain().displayMessage(); + } + + public String getPluginType() { + return "ViaProxy"; + } + + public String getPluginFolder() { + return PluginManager.PLUGINS_DIR.getName(); + } + +} diff --git a/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyPlugin.java b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyPlugin.java new file mode 100644 index 000000000..47745df7d --- /dev/null +++ b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyPlugin.java @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2019-2023 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.platform.viaproxy; + +import net.lenni0451.lambdaevents.EventHandler; +import net.raphimc.vialegacy.api.LegacyProtocolVersion; +import net.raphimc.viaproxy.ViaProxy; +import net.raphimc.viaproxy.cli.options.Options; +import net.raphimc.viaproxy.plugins.PluginManager; +import net.raphimc.viaproxy.plugins.ViaProxyPlugin; +import net.raphimc.viaproxy.plugins.events.ConsoleCommandEvent; +import net.raphimc.viaproxy.plugins.events.ProxyStartEvent; +import net.raphimc.viaproxy.plugins.events.ProxyStopEvent; +import net.raphimc.viaproxy.plugins.events.ShouldVerifyOnlineModeEvent; +import org.apache.logging.log4j.LogManager; +import org.geysermc.geyser.GeyserBootstrap; +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.GeyserLogger; +import org.geysermc.geyser.api.network.AuthType; +import org.geysermc.geyser.api.util.PlatformType; +import org.geysermc.geyser.command.GeyserCommandManager; +import org.geysermc.geyser.configuration.GeyserConfiguration; +import org.geysermc.geyser.dump.BootstrapDumpInfo; +import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough; +import org.geysermc.geyser.ping.IGeyserPingPassthrough; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.text.GeyserLocale; +import org.geysermc.geyser.util.FileUtils; +import org.geysermc.geyser.util.LoopbackUtil; +import org.jetbrains.annotations.NotNull; + +import java.io.File; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.UUID; + +public class GeyserViaProxyPlugin extends ViaProxyPlugin implements GeyserBootstrap { + + public static final File ROOT_FOLDER = new File(PluginManager.PLUGINS_DIR, "Geyser"); + + private final GeyserViaProxyLogger logger = new GeyserViaProxyLogger(LogManager.getLogger("Geyser")); + private GeyserViaProxyConfiguration config; + private GeyserImpl geyser; + private GeyserCommandManager commandManager; + private IGeyserPingPassthrough pingPassthrough; + + @Override + public void onEnable() { + ROOT_FOLDER.mkdirs(); + + GeyserLocale.init(this); + this.onGeyserInitialize(); + + ViaProxy.EVENT_MANAGER.register(this); + } + + @Override + public void onDisable() { + this.onGeyserShutdown(); + } + + @EventHandler + private void onConsoleCommand(final ConsoleCommandEvent event) { + final String command = event.getCommand().startsWith("/") ? event.getCommand().substring(1) : event.getCommand(); + if (this.getGeyserCommandManager().runCommand(this.getGeyserLogger(), command + " " + String.join(" ", event.getArgs()))) { + event.setCancelled(true); + } + } + + @EventHandler + private void onShouldVerifyOnlineModeEvent(final ShouldVerifyOnlineModeEvent event) { + final UUID uuid = event.getProxyConnection().getGameProfile().getId(); + if (uuid == null) return; + + final GeyserSession connection = GeyserImpl.getInstance().onlineConnections().stream().filter(s -> s.javaUuid().equals(uuid)).findAny().orElse(null); + if (connection == null) return; + + if (connection.javaUsername().equals(event.getProxyConnection().getGameProfile().getName())) { + event.setCancelled(true); + } + } + + @EventHandler + private void onProxyStart(final ProxyStartEvent event) { + this.onGeyserEnable(); + } + + @EventHandler + private void onProxyStop(final ProxyStopEvent event) { + this.onGeyserDisable(); + } + + @Override + public void onGeyserInitialize() { + if (!this.loadConfig()) { + return; + } + + this.geyser = GeyserImpl.load(PlatformType.VIAPROXY, this); + LoopbackUtil.checkAndApplyLoopback(this.logger); + } + + @Override + public void onGeyserEnable() { + if (GeyserImpl.getInstance().isReloading()) { + if (!this.loadConfig()) { + return; + } + } + + this.commandManager = new GeyserCommandManager(this.geyser); + this.commandManager.init(); + + GeyserImpl.start(); + + if (Options.PROTOCOL_VERSION != null && Options.PROTOCOL_VERSION.newerThanOrEqualTo(LegacyProtocolVersion.b1_8tob1_8_1)) { + // Only initialize the ping passthrough if the protocol version is above beta 1.7.3, as that's when the status protocol was added + this.pingPassthrough = GeyserLegacyPingPassthrough.init(this.geyser); + } + } + + @Override + public void onGeyserDisable() { + this.geyser.disable(); + } + + @Override + public void onGeyserShutdown() { + this.geyser.shutdown(); + } + + @Override + public GeyserConfiguration getGeyserConfig() { + return this.config; + } + + @Override + public GeyserLogger getGeyserLogger() { + return this.logger; + } + + @Override + public GeyserCommandManager getGeyserCommandManager() { + return this.commandManager; + } + + @Override + public IGeyserPingPassthrough getGeyserPingPassthrough() { + return this.pingPassthrough; + } + + @Override + public Path getConfigFolder() { + return ROOT_FOLDER.toPath(); + } + + @Override + public BootstrapDumpInfo getDumpInfo() { + return new GeyserViaProxyDumpInfo(); + } + + @NotNull + @Override + public String getServerBindAddress() { + if (Options.BIND_ADDRESS instanceof InetSocketAddress socketAddress) { + return socketAddress.getHostString(); + } else { + throw new IllegalStateException("Unsupported bind address type: " + Options.BIND_ADDRESS.getClass().getName()); + } + } + + @Override + public int getServerPort() { + if (Options.BIND_ADDRESS instanceof InetSocketAddress socketAddress) { + return socketAddress.getPort(); + } else { + throw new IllegalStateException("Unsupported bind address type: " + Options.BIND_ADDRESS.getClass().getName()); + } + } + + @Override + public boolean testFloodgatePluginPresent() { + return false; + } + + private boolean loadConfig() { + try { + final File configFile = FileUtils.fileOrCopiedFromResource(new File(ROOT_FOLDER, "config.yml"), "config.yml", s -> s.replaceAll("generateduuid", UUID.randomUUID().toString()), this); + this.config = FileUtils.loadConfig(configFile, GeyserViaProxyConfiguration.class); + } catch (IOException e) { + this.logger.severe(GeyserLocale.getLocaleStringLog("geyser.config.failed"), e); + return false; + } + this.config.getRemote().setAuthType(Files.isRegularFile(this.config.getFloodgateKeyPath()) ? AuthType.FLOODGATE : AuthType.OFFLINE); + this.logger.setDebug(this.config.isDebugMode()); + GeyserConfiguration.checkGeyserConfiguration(this.config, this.logger); + return true; + } + +} diff --git a/bootstrap/viaproxy/src/main/resources/viaproxy.yml b/bootstrap/viaproxy/src/main/resources/viaproxy.yml new file mode 100644 index 000000000..f42cda77b --- /dev/null +++ b/bootstrap/viaproxy/src/main/resources/viaproxy.yml @@ -0,0 +1,5 @@ +name: "${name}-ViaProxy" +version: "${version}" +author: "${author}" +main: "org.geysermc.geyser.platform.viaproxy.GeyserViaProxyPlugin" +min-version: "3.2.0" diff --git a/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts b/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts index 01c769733..c9f984596 100644 --- a/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts @@ -22,8 +22,8 @@ indra { tasks { processResources { - // Spigot, BungeeCord, Velocity, Fabric - filesMatching(listOf("plugin.yml", "bungee.yml", "velocity-plugin.json", "fabric.mod.json")) { + // Spigot, BungeeCord, Velocity, Fabric, ViaProxy + filesMatching(listOf("plugin.yml", "bungee.yml", "velocity-plugin.json", "fabric.mod.json", "viaproxy.yml")) { expand( "id" to "geyser", "name" to "Geyser", @@ -34,4 +34,4 @@ tasks { ) } } -} \ No newline at end of file +} diff --git a/build.gradle.kts b/build.gradle.kts index a72b8a484..1d434e599 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -23,7 +23,8 @@ val platforms = setOf( projects.bungeecord, projects.spigot, projects.standalone, - projects.velocity + projects.velocity, + projects.viaproxy ).map { it.dependencyProject } subprojects { diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index 5ed0c3947..6a8efaba1 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -44,9 +44,6 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; import org.geysermc.api.Geyser; -import org.geysermc.geyser.api.command.CommandSource; -import org.geysermc.geyser.api.util.MinecraftVersion; -import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.cumulus.form.Form; import org.geysermc.cumulus.form.util.FormBuilder; import org.geysermc.erosion.packet.Packets; @@ -56,12 +53,15 @@ import org.geysermc.floodgate.crypto.Base64Topping; import org.geysermc.floodgate.crypto.FloodgateCipher; import org.geysermc.floodgate.news.NewsItemAction; import org.geysermc.geyser.api.GeyserApi; +import org.geysermc.geyser.api.command.CommandSource; import org.geysermc.geyser.api.event.EventBus; import org.geysermc.geyser.api.event.EventRegistrar; import org.geysermc.geyser.api.event.lifecycle.*; import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.api.network.BedrockListener; import org.geysermc.geyser.api.network.RemoteServer; +import org.geysermc.geyser.api.util.MinecraftVersion; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.command.GeyserCommandManager; import org.geysermc.geyser.configuration.GeyserConfiguration; import org.geysermc.geyser.entity.EntityDefinitions; @@ -169,6 +169,12 @@ public class GeyserImpl implements GeyserApi { */ private volatile boolean isReloading; + /** + * Determines if Geyser is currently enabled. This is used to determine if {@link #disable()} should be called during {@link #shutdown()}. + */ + @Setter + private boolean isEnabled; + private GeyserImpl(PlatformType platformType, GeyserBootstrap bootstrap) { instance = this; @@ -344,15 +350,17 @@ public class GeyserImpl implements GeyserApi { logger.info("Broadcast port set from system property: " + parsedPort); } - boolean floodgatePresent = bootstrap.testFloodgatePluginPresent(); - if (config.getRemote().authType() == AuthType.FLOODGATE && !floodgatePresent) { - logger.severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.not_installed") + " " - + GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.disabling")); - return; - } else if (config.isAutoconfiguredRemote() && floodgatePresent) { - // Floodgate installed means that the user wants Floodgate authentication - logger.debug("Auto-setting to Floodgate authentication."); - config.getRemote().setAuthType(AuthType.FLOODGATE); + if (platformType != PlatformType.VIAPROXY) { + boolean floodgatePresent = bootstrap.testFloodgatePluginPresent(); + if (config.getRemote().authType() == AuthType.FLOODGATE && !floodgatePresent) { + logger.severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.not_installed") + " " + + GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.disabling")); + return; + } else if (config.isAutoconfiguredRemote() && floodgatePresent) { + // Floodgate installed means that the user wants Floodgate authentication + logger.debug("Auto-setting to Floodgate authentication."); + config.getRemote().setAuthType(AuthType.FLOODGATE); + } } } @@ -639,12 +647,14 @@ public class GeyserImpl implements GeyserApi { Registries.RESOURCE_PACKS.get().clear(); - bootstrap.getGeyserLogger().info(GeyserLocale.getLocaleStringLog("geyser.core.shutdown.done")); + this.setEnabled(false); } public void shutdown() { shuttingDown = true; - this.disable(); + if (isEnabled) { + this.disable(); + } this.commandManager().getCommands().clear(); // Disable extensions, fire the shutdown event @@ -777,6 +787,7 @@ public class GeyserImpl implements GeyserApi { } else { instance.initialize(); } + instance.setEnabled(true); } public GeyserLogger getLogger() { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginDisconnectTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginDisconnectTranslator.java index daf42a68e..c0be2c624 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginDisconnectTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginDisconnectTranslator.java @@ -51,7 +51,7 @@ public class JavaLoginDisconnectTranslator extends PacketTranslator Date: Fri, 23 Feb 2024 16:58:39 +0000 Subject: [PATCH 189/344] NeoForge Platform Support (#3781) * Initial work on Forge platform * Rework modded platforms to use a common module * Add support for integrated worlds on modded platforms * Fix classload errors and move mixins to shared module * Fix Fabric mixins and check min height in mod world manager * Add Forge command support * Add back modrinth publishing * Don't apply application plugin to shared mod sources * Fix docs * Delete unused class * Clean up repositories * - Update to 1.20.2 - set custom refmap name - fixed console commands crashing the server (hasPermission now accepts CommandSourceStack instead of Player) - Forge wants fastutil relocated, so be it Current issues: - ClassNotFound exceptions with classes that are clearly present * - Fix ClassNotFound errors on Forge due to weird Classloader - Dont relocate gson * merge upstream * oh no * Bump lombok, architectury-loom * init: neoforge 1.20.4 support * NeoForge builds Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Archive neoforge artifacts * transformForge -> transformNeoForge * Neoforge boots! * Fix mixins on neoforge * Update build/pr file names * Update mods.toml to new neoforge standard * Fix refmap naming * more fixes - no need to include gson - cleanup nullable/nonnull annotations - add more info to geyser dumps on neoforge * yeet platform executor * yet another temp branch to figure out the runServer task * yeet transitive dependency, that cant be right * Attempt at getting the runServer task to work, part two * Revert the changes for the runServer task, try and shut down the injector * Remove spigot weird bug workaround, shut down properly Also add a compileOnly dependency for the mod module to get rid of spammy false warnings * Update to latest restart changes - fix duplicate nodes crashing neoforge - connector -> geyser in GeyserModCommandExecutor - create command manager early to fix issues with permission gather event * Consistent NeoForge spelling, move some dependencies to the version toml * Add lombok to version catalogue * Add plugins to version catalogue * revert move to buildSrc * Create `assets/geyser/icon.png` to reference icon from a single file on standalone/neoforge/fabric * add fabric permissions api to libs.versions.toml --------- Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Co-authored-by: onebeastchris Co-authored-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/workflows/build.yml | 22 ++- .github/workflows/pullrequest.yml | 9 +- .../geyser/api/pack/PathPackCodec.java | 2 +- .../geyser/api/util/PlatformType.java | 1 + .../main/resources/geyser-fabric.mixins.json | 15 -- bootstrap/mod/build.gradle.kts | 15 ++ bootstrap/mod/fabric/build.gradle.kts | 49 ++++++ bootstrap/mod/fabric/gradle.properties | 1 + .../fabric/GeyserFabricBootstrap.java | 72 ++++++++ .../platform/fabric/GeyserFabricDumpInfo.java | 0 .../platform/fabric/GeyserFabricMain.java | 0 .../platform/fabric/GeyserFabricPlatform.java | 99 +++++++++++ .../fabric/src/main/resources/fabric.mod.json | 8 +- bootstrap/mod/neoforge/build.gradle.kts | 52 ++++++ bootstrap/mod/neoforge/gradle.properties | 1 + .../neoforge/GeyserNeoForgeBootstrap.java | 83 ++++++++++ .../neoforge/GeyserNeoForgeDumpInfo.java | 84 ++++++++++ .../platform/neoforge/GeyserNeoForgeMain.java | 45 +++++ .../GeyserNeoForgePermissionHandler.java | 149 +++++++++++++++++ .../neoforge/GeyserNeoForgePlatform.java | 72 ++++++++ .../platform/neoforge/ModConstants.java | 30 ++++ .../src/main/resources/META-INF/mods.toml | 25 +++ .../platform/mod/GeyserChannelGetter.java | 43 +++++ .../platform/mod/GeyserModBootstrap.java} | 124 ++++++-------- .../mod/GeyserModCompressionDisabler.java | 56 +++++++ .../platform/mod/GeyserModConfiguration.java} | 9 +- .../platform/mod/GeyserModInjector.java | 156 ++++++++++++++++++ .../geyser/platform/mod/GeyserModLogger.java} | 10 +- .../mod/GeyserModUpdateListener.java} | 19 ++- .../platform/mod}/GeyserServerPortGetter.java | 2 +- .../platform/mod}/ModPingPassthrough.java | 7 +- .../command/GeyserModCommandExecutor.java} | 14 +- .../mod/command/ModCommandSender.java} | 10 +- .../mixin/client/IntegratedServerMixin.java | 15 +- .../mixin/server/DedicatedServerMixin.java} | 10 +- .../server/ServerConnectionListenerMixin.java | 46 ++++++ .../mod/platform/GeyserModPlatform.java | 92 +++++++++++ .../mod/world/GeyserModWorldManager.java} | 74 ++++++++- .../mod/src/main/resources/geyser.mixins.json | 18 ++ .../standalone/gui/GeyserStandaloneGUI.java | 2 +- build-logic/build.gradle.kts | 17 +- build-logic/settings.gradle.kts | 11 ++ .../kotlin/geyser.base-conventions.gradle.kts | 6 +- .../geyser.modded-conventions.gradle.kts | 78 ++++----- build.gradle.kts | 24 +-- core/build.gradle.kts | 3 +- .../java/org/geysermc/geyser/GeyserImpl.java | 1 + .../geyser/pack/SkullResourcePackManager.java | 2 +- .../PendingMicrosoftAuthentication.java | 3 +- .../main/resources/assets/geyser}/icon.png | Bin core/src/main/resources/icon.png | Bin 115461 -> 0 bytes gradle.properties | 4 +- gradle/libs.versions.toml | 31 +++- gradle/wrapper/gradle-wrapper.properties | 2 +- settings.gradle.kts | 24 ++- 55 files changed, 1504 insertions(+), 243 deletions(-) delete mode 100644 bootstrap/fabric/src/main/resources/geyser-fabric.mixins.json create mode 100644 bootstrap/mod/build.gradle.kts create mode 100644 bootstrap/mod/fabric/build.gradle.kts create mode 100644 bootstrap/mod/fabric/gradle.properties create mode 100644 bootstrap/mod/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricBootstrap.java rename bootstrap/{ => mod}/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricDumpInfo.java (100%) rename bootstrap/{ => mod}/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMain.java (100%) create mode 100644 bootstrap/mod/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricPlatform.java rename bootstrap/{ => mod}/fabric/src/main/resources/fabric.mod.json (74%) create mode 100644 bootstrap/mod/neoforge/build.gradle.kts create mode 100644 bootstrap/mod/neoforge/gradle.properties create mode 100644 bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgeBootstrap.java create mode 100644 bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgeDumpInfo.java create mode 100644 bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgeMain.java create mode 100644 bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgePermissionHandler.java create mode 100644 bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgePlatform.java create mode 100644 bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/ModConstants.java create mode 100644 bootstrap/mod/neoforge/src/main/resources/META-INF/mods.toml create mode 100644 bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserChannelGetter.java rename bootstrap/{fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMod.java => mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModBootstrap.java} (70%) create mode 100644 bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModCompressionDisabler.java rename bootstrap/{fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricConfiguration.java => mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModConfiguration.java} (80%) create mode 100644 bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModInjector.java rename bootstrap/{fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricLogger.java => mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModLogger.java} (90%) rename bootstrap/{fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricUpdateListener.java => mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModUpdateListener.java} (68%) rename bootstrap/{fabric/src/main/java/org/geysermc/geyser/platform/fabric => mod/src/main/java/org/geysermc/geyser/platform/mod}/GeyserServerPortGetter.java (97%) rename bootstrap/{fabric/src/main/java/org/geysermc/geyser/platform/fabric => mod/src/main/java/org/geysermc/geyser/platform/mod}/ModPingPassthrough.java (94%) rename bootstrap/{fabric/src/main/java/org/geysermc/geyser/platform/fabric/command/GeyserFabricCommandExecutor.java => mod/src/main/java/org/geysermc/geyser/platform/mod/command/GeyserModCommandExecutor.java} (82%) rename bootstrap/{fabric/src/main/java/org/geysermc/geyser/platform/fabric/command/FabricCommandSender.java => mod/src/main/java/org/geysermc/geyser/platform/mod/command/ModCommandSender.java} (88%) rename bootstrap/{fabric/src/main/java/org/geysermc/geyser/platform/fabric => mod/src/main/java/org/geysermc/geyser/platform/mod}/mixin/client/IntegratedServerMixin.java (85%) rename bootstrap/{fabric/src/main/java/org/geysermc/geyser/platform/fabric/mixin/server/MinecraftDedicatedServerMixin.java => mod/src/main/java/org/geysermc/geyser/platform/mod/mixin/server/DedicatedServerMixin.java} (76%) create mode 100644 bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/mixin/server/ServerConnectionListenerMixin.java create mode 100644 bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/platform/GeyserModPlatform.java rename bootstrap/{fabric/src/main/java/org/geysermc/geyser/platform/fabric/world/GeyserFabricWorldManager.java => mod/src/main/java/org/geysermc/geyser/platform/mod/world/GeyserModWorldManager.java} (81%) create mode 100644 bootstrap/mod/src/main/resources/geyser.mixins.json create mode 100644 build-logic/settings.gradle.kts rename bootstrap/fabric/build.gradle.kts => build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts (70%) rename {bootstrap/fabric/src/main/resources/assets/geyser-fabric => core/src/main/resources/assets/geyser}/icon.png (100%) delete mode 100644 core/src/main/resources/icon.png diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 827136b4a..cd579c931 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -47,7 +47,14 @@ jobs: if: success() with: name: Geyser Fabric - path: bootstrap/fabric/build/libs/Geyser-Fabric.jar + path: bootstrap/mod/fabric/build/libs/Geyser-Fabric.jar + if-no-files-found: error + - name: Archive artifacts (Geyser NeoForge) + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 + if: success() + with: + name: Geyser NeoForge + path: bootstrap/mod/neoforge/build/libs/Geyser-NeoForge.jar if-no-files-found: error - name: Archive artifacts (Geyser Standalone) uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 @@ -118,7 +125,7 @@ jobs: echo "{\"project\": \"$project\", \"version\": \"$version\", \"id\": $GITHUB_RUN_NUMBER, \"commit\": \"$GITHUB_SHA\"}" > metadata.json rsync -P -e "ssh -o StrictHostKeyChecking=no -i id_ecdsa" metadata.json $DOWNLOADS_USERNAME@$DOWNLOADS_SERVER_IP:~/uploads/$project/$GITHUB_RUN_NUMBER/ - - name: Publish to Modrinth + - name: Publish to Modrinth (Fabric) uses: gradle/gradle-build-action@3bfe3a46584a206fb8361cdedd0647b0c4204232 if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} env: @@ -126,7 +133,16 @@ jobs: with: arguments: fabric:modrinth gradle-home-cache-cleanup: true - + + - name: Publish to Modrinth (NeoForge) + uses: gradle/gradle-build-action@3bfe3a46584a206fb8361cdedd0647b0c4204232 + if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} + env: + MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }} + with: + arguments: neoforge:modrinth + gradle-home-cache-cleanup: true + - name: Notify Discord if: ${{ (success() || failure()) && github.repository == 'GeyserMC/Geyser' }} # See https://github.com/Tim203/actions-git-discord-webhook/commits diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index f2c8f5d8d..851c087c1 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -57,7 +57,14 @@ jobs: if: success() with: name: Geyser Fabric - path: geyser/bootstrap/fabric/build/libs/Geyser-Fabric.jar + path: geyser/bootstrap/mod/fabric/build/libs/Geyser-Fabric.jar + if-no-files-found: error + - name: Archive artifacts (Geyser NeoForge) + uses: actions/upload-artifact@v3 + if: success() + with: + name: Geyser NeoForge + path: geyser/bootstrap/mod/neoforge/build/libs/Geyser-NeoForge.jar if-no-files-found: error - name: Archive artifacts (Geyser Standalone) uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 diff --git a/api/src/main/java/org/geysermc/geyser/api/pack/PathPackCodec.java b/api/src/main/java/org/geysermc/geyser/api/pack/PathPackCodec.java index ee5db8242..a3770451a 100644 --- a/api/src/main/java/org/geysermc/geyser/api/pack/PathPackCodec.java +++ b/api/src/main/java/org/geysermc/geyser/api/pack/PathPackCodec.java @@ -42,4 +42,4 @@ public abstract class PathPackCodec extends PackCodec { */ @NonNull public abstract Path path(); -} +} \ No newline at end of file diff --git a/api/src/main/java/org/geysermc/geyser/api/util/PlatformType.java b/api/src/main/java/org/geysermc/geyser/api/util/PlatformType.java index 1abdc0230..cda5e06e4 100644 --- a/api/src/main/java/org/geysermc/geyser/api/util/PlatformType.java +++ b/api/src/main/java/org/geysermc/geyser/api/util/PlatformType.java @@ -34,6 +34,7 @@ public record PlatformType(String platformName) { public static final PlatformType ANDROID = new PlatformType("Android"); public static final PlatformType BUNGEECORD = new PlatformType("BungeeCord"); public static final PlatformType FABRIC = new PlatformType("Fabric"); + public static final PlatformType NEOFORGE = new PlatformType("NeoForge"); public static final PlatformType SPIGOT = new PlatformType("Spigot"); @Deprecated diff --git a/bootstrap/fabric/src/main/resources/geyser-fabric.mixins.json b/bootstrap/fabric/src/main/resources/geyser-fabric.mixins.json deleted file mode 100644 index aeb051809..000000000 --- a/bootstrap/fabric/src/main/resources/geyser-fabric.mixins.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "required": true, - "package": "org.geysermc.geyser.platform.fabric.mixin", - "compatibilityLevel": "JAVA_16", - "refmap": "geyser-fabric-refmap.json", - "client": [ - "client.IntegratedServerMixin" - ], - "server": [ - "server.MinecraftDedicatedServerMixin" - ], - "injectors": { - "defaultRequire": 1 - } -} diff --git a/bootstrap/mod/build.gradle.kts b/bootstrap/mod/build.gradle.kts new file mode 100644 index 000000000..7651a2df2 --- /dev/null +++ b/bootstrap/mod/build.gradle.kts @@ -0,0 +1,15 @@ +architectury { + common("neoforge", "fabric") +} + +loom { + mixin.defaultRefmapName.set("geyser-refmap.json") +} + +dependencies { + api(projects.core) + compileOnly(libs.mixin) + + // Only here to suppress "unknown enum constant EnvType.CLIENT" warnings. DO NOT USE! + compileOnly(libs.fabric.loader) +} \ No newline at end of file diff --git a/bootstrap/mod/fabric/build.gradle.kts b/bootstrap/mod/fabric/build.gradle.kts new file mode 100644 index 000000000..dac042ad7 --- /dev/null +++ b/bootstrap/mod/fabric/build.gradle.kts @@ -0,0 +1,49 @@ +plugins { + application +} + +architectury { + platformSetupLoomIde() + fabric() +} + +dependencies { + modImplementation(libs.fabric.loader) + modApi(libs.fabric.api) + + api(project(":mod", configuration = "namedElements")) + shadow(project(path = ":mod", configuration = "transformProductionFabric")) { + isTransitive = false + } + shadow(projects.core) { + exclude(group = "com.google.guava", module = "guava") + exclude(group = "com.google.code.gson", module = "gson") + exclude(group = "org.slf4j") + exclude(group = "com.nukkitx.fastutil") + exclude(group = "io.netty.incubator") + } + + modImplementation(libs.fabric.permissions) + include(libs.fabric.permissions) +} + +application { + mainClass.set("org.geysermc.geyser.platform.fabric.GeyserFabricMain") +} + +tasks { + remapJar { + archiveBaseName.set("Geyser-Fabric") + } + + remapModrinthJar { + archiveBaseName.set("geyser-fabric") + } +} + +modrinth { + loaders.add("fabric") + dependencies { + required.project("fabric-api") + } +} \ No newline at end of file diff --git a/bootstrap/mod/fabric/gradle.properties b/bootstrap/mod/fabric/gradle.properties new file mode 100644 index 000000000..90ee7a259 --- /dev/null +++ b/bootstrap/mod/fabric/gradle.properties @@ -0,0 +1 @@ +loom.platform=fabric \ No newline at end of file diff --git a/bootstrap/mod/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricBootstrap.java b/bootstrap/mod/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricBootstrap.java new file mode 100644 index 000000000..81e329c03 --- /dev/null +++ b/bootstrap/mod/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricBootstrap.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2019-2023 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.platform.fabric; + +import me.lucko.fabric.api.permissions.v0.Permissions; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.world.entity.player.Player; +import org.geysermc.geyser.platform.mod.GeyserModBootstrap; +import org.geysermc.geyser.platform.mod.GeyserModUpdateListener; +import org.checkerframework.checker.nullness.qual.NonNull; + +public class GeyserFabricBootstrap extends GeyserModBootstrap implements ModInitializer { + + public GeyserFabricBootstrap() { + super(new GeyserFabricPlatform()); + } + + @Override + public void onInitialize() { + if (FabricLoader.getInstance().getEnvironmentType() == EnvType.SERVER) { + // Set as an event, so we can get the proper IP and port if needed + ServerLifecycleEvents.SERVER_STARTED.register((server) -> { + this.setServer(server); + onGeyserEnable(); + }); + } + + // These are only registered once + ServerLifecycleEvents.SERVER_STOPPING.register((server) -> onGeyserShutdown()); + ServerPlayConnectionEvents.JOIN.register((handler, $, $$) -> GeyserModUpdateListener.onPlayReady(handler.getPlayer())); + + this.onGeyserInitialize(); + } + + @Override + public boolean hasPermission(@NonNull Player source, @NonNull String permissionNode) { + return Permissions.check(source, permissionNode); + } + + @Override + public boolean hasPermission(@NonNull CommandSourceStack source, @NonNull String permissionNode, int permissionLevel) { + return Permissions.check(source, permissionNode, permissionLevel); + } +} diff --git a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricDumpInfo.java b/bootstrap/mod/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricDumpInfo.java similarity index 100% rename from bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricDumpInfo.java rename to bootstrap/mod/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricDumpInfo.java diff --git a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMain.java b/bootstrap/mod/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMain.java similarity index 100% rename from bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMain.java rename to bootstrap/mod/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMain.java diff --git a/bootstrap/mod/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricPlatform.java b/bootstrap/mod/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricPlatform.java new file mode 100644 index 000000000..4631ab493 --- /dev/null +++ b/bootstrap/mod/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricPlatform.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2019-2023 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.platform.fabric; + +import net.fabricmc.loader.api.FabricLoader; +import net.fabricmc.loader.api.ModContainer; +import net.minecraft.server.MinecraftServer; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.geyser.api.util.PlatformType; +import org.geysermc.geyser.dump.BootstrapDumpInfo; +import org.geysermc.geyser.platform.mod.GeyserModBootstrap; +import org.geysermc.geyser.platform.mod.platform.GeyserModPlatform; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Path; +import java.util.Optional; + +public class GeyserFabricPlatform implements GeyserModPlatform { + + private final ModContainer mod; + + public GeyserFabricPlatform() { + this.mod = FabricLoader.getInstance().getModContainer("geyser-fabric").orElseThrow(); + } + + @Override + public @NonNull PlatformType platformType() { + return PlatformType.FABRIC; + } + + @Override + public @NonNull String configPath() { + return "Geyser-Fabric"; + } + + @Override + public @NonNull Path dataFolder(@NonNull String modId) { + return FabricLoader.getInstance().getConfigDir().resolve(modId); + } + + @Override + public @NonNull BootstrapDumpInfo dumpInfo(@NonNull MinecraftServer server) { + return new GeyserFabricDumpInfo(server); + } + + @Override + public boolean testFloodgatePluginPresent(@NonNull GeyserModBootstrap bootstrap) { + Optional floodgate = FabricLoader.getInstance().getModContainer("floodgate"); + if (floodgate.isPresent()) { + Path floodgateDataFolder = FabricLoader.getInstance().getConfigDir().resolve("floodgate"); + bootstrap.getGeyserConfig().loadFloodgate(bootstrap, floodgateDataFolder); + return true; + } + + return false; + } + + @Override + public @Nullable InputStream resolveResource(@NonNull String resource) { + // We need to handle this differently, because Fabric shares the classloader across multiple mods + Path path = this.mod.findPath(resource).orElse(null); + if (path == null) { + return null; + } + + try { + return path.getFileSystem() + .provider() + .newInputStream(path); + } catch (IOException e) { + return null; + } + } +} diff --git a/bootstrap/fabric/src/main/resources/fabric.mod.json b/bootstrap/mod/fabric/src/main/resources/fabric.mod.json similarity index 74% rename from bootstrap/fabric/src/main/resources/fabric.mod.json rename to bootstrap/mod/fabric/src/main/resources/fabric.mod.json index a192109e2..6bd217433 100644 --- a/bootstrap/fabric/src/main/resources/fabric.mod.json +++ b/bootstrap/mod/fabric/src/main/resources/fabric.mod.json @@ -9,18 +9,18 @@ ], "contact": { "website": "${url}", - "repo": "https://github.com/GeyserMC/Geyser-Fabric" + "repo": "https://github.com/GeyserMC/Geyser" }, "license": "MIT", - "icon": "assets/geyser-fabric/icon.png", + "icon": "assets/geyser/icon.png", "environment": "*", "entrypoints": { "main": [ - "org.geysermc.geyser.platform.fabric.GeyserFabricMod" + "org.geysermc.geyser.platform.fabric.GeyserFabricBootstrap" ] }, "mixins": [ - "geyser-fabric.mixins.json" + "geyser.mixins.json" ], "depends": { "fabricloader": ">=0.15.2", diff --git a/bootstrap/mod/neoforge/build.gradle.kts b/bootstrap/mod/neoforge/build.gradle.kts new file mode 100644 index 000000000..d85087542 --- /dev/null +++ b/bootstrap/mod/neoforge/build.gradle.kts @@ -0,0 +1,52 @@ +plugins { + application +} + +architectury { + platformSetupLoomIde() + neoForge() +} + +dependencies { + // See https://github.com/google/guava/issues/6618 + modules { + module("com.google.guava:listenablefuture") { + replacedBy("com.google.guava:guava", "listenablefuture is part of guava") + } + } + + neoForge(libs.neoforge.minecraft) + + api(project(":mod", configuration = "namedElements")) + shadow(project(path = ":mod", configuration = "transformProductionNeoForge")) { + isTransitive = false + } + shadow(projects.core) { + exclude(group = "com.google.guava", module = "guava") + exclude(group = "com.google.code.gson", module = "gson") + exclude(group = "org.slf4j") + exclude(group = "io.netty.incubator") + } +} + +application { + mainClass.set("org.geysermc.geyser.platform.forge.GeyserNeoForgeMain") +} + +tasks { + shadowJar { + relocate("it.unimi.dsi.fastutil", "org.geysermc.relocate.fastutil") + } + + remapJar { + archiveBaseName.set("Geyser-NeoForge") + } + + remapModrinthJar { + archiveBaseName.set("geyser-neoforge") + } +} + +modrinth { + loaders.add("neoforge") +} \ No newline at end of file diff --git a/bootstrap/mod/neoforge/gradle.properties b/bootstrap/mod/neoforge/gradle.properties new file mode 100644 index 000000000..2914393db --- /dev/null +++ b/bootstrap/mod/neoforge/gradle.properties @@ -0,0 +1 @@ +loom.platform=neoforge \ No newline at end of file diff --git a/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgeBootstrap.java b/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgeBootstrap.java new file mode 100644 index 000000000..67cad1683 --- /dev/null +++ b/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgeBootstrap.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2019-2023 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.platform.neoforge; + +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.world.entity.player.Player; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.fml.common.Mod; +import net.neoforged.fml.loading.FMLLoader; +import net.neoforged.neoforge.common.NeoForge; +import net.neoforged.neoforge.event.entity.player.PlayerEvent; +import net.neoforged.neoforge.event.server.ServerStartedEvent; +import net.neoforged.neoforge.event.server.ServerStoppingEvent; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.platform.mod.GeyserModBootstrap; +import org.geysermc.geyser.platform.mod.GeyserModUpdateListener; + +@Mod(ModConstants.MOD_ID) +public class GeyserNeoForgeBootstrap extends GeyserModBootstrap { + + private final GeyserNeoForgePermissionHandler permissionHandler = new GeyserNeoForgePermissionHandler(); + + public GeyserNeoForgeBootstrap() { + super(new GeyserNeoForgePlatform()); + + if (FMLLoader.getDist() == Dist.DEDICATED_SERVER) { + // Set as an event so we can get the proper IP and port if needed + NeoForge.EVENT_BUS.addListener(this::onServerStarted); + } + + NeoForge.EVENT_BUS.addListener(this::onServerStopping); + NeoForge.EVENT_BUS.addListener(this::onPlayerJoin); + NeoForge.EVENT_BUS.addListener(this.permissionHandler::onPermissionGather); + + this.onGeyserInitialize(); + } + + private void onServerStarted(ServerStartedEvent event) { + this.setServer(event.getServer()); + this.onGeyserEnable(); + } + + private void onServerStopping(ServerStoppingEvent event) { + this.onGeyserShutdown(); + } + + private void onPlayerJoin(PlayerEvent.PlayerLoggedInEvent event) { + GeyserModUpdateListener.onPlayReady(event.getEntity()); + } + + @Override + public boolean hasPermission(@NonNull Player source, @NonNull String permissionNode) { + return this.permissionHandler.hasPermission(source, permissionNode); + } + + @Override + public boolean hasPermission(@NonNull CommandSourceStack source, @NonNull String permissionNode, int permissionLevel) { + return this.permissionHandler.hasPermission(source, permissionNode, permissionLevel); + } +} diff --git a/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgeDumpInfo.java b/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgeDumpInfo.java new file mode 100644 index 000000000..623f68d3a --- /dev/null +++ b/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgeDumpInfo.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2019-2023 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.platform.neoforge; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import net.minecraft.server.MinecraftServer; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.fml.ModList; +import net.neoforged.fml.loading.FMLLoader; +import net.neoforged.neoforgespi.language.IModInfo; +import org.geysermc.geyser.dump.BootstrapDumpInfo; +import org.geysermc.geyser.text.AsteriskSerializer; + +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +@Getter +public class GeyserNeoForgeDumpInfo extends BootstrapDumpInfo { + + private final String platformName; + private final String platformVersion; + private final String minecraftVersion; + private final Dist dist; + + @AsteriskSerializer.Asterisk(isIp = true) + private final String serverIP; + private final int serverPort; + private final boolean onlineMode; + private final List mods; + + public GeyserNeoForgeDumpInfo(MinecraftServer server) { + this.platformName = FMLLoader.launcherHandlerName(); + this.platformVersion = FMLLoader.versionInfo().neoForgeVersion(); + this.minecraftVersion = FMLLoader.versionInfo().mcVersion(); + this.dist = FMLLoader.getDist(); + this.serverIP = server.getLocalIp() == null ? "unknown" : server.getLocalIp(); + this.serverPort = server.getPort(); + this.onlineMode = server.usesAuthentication(); + this.mods = new ArrayList<>(); + + for (IModInfo mod : ModList.get().getMods()) { + this.mods.add(new ModInfo( + ModList.get().isLoaded(mod.getModId()), + mod.getModId(), + mod.getVersion().toString(), + mod.getModURL().map(URL::toString).orElse("") + )); + } + } + + @Getter + @AllArgsConstructor + public static class ModInfo { + public boolean enabled; + public String name; + public String version; + public String url; + } +} \ No newline at end of file diff --git a/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgeMain.java b/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgeMain.java new file mode 100644 index 000000000..70bac2a40 --- /dev/null +++ b/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgeMain.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2019-2023 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.platform.neoforge; + +import org.geysermc.geyser.GeyserMain; + +public class GeyserNeoForgeMain extends GeyserMain { + + public static void main(String[] args) { + new GeyserNeoForgeMain().displayMessage(); + } + + @Override + public String getPluginType() { + return "NeoForge"; + } + + @Override + public String getPluginFolder() { + return "mods"; + } +} diff --git a/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgePermissionHandler.java b/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgePermissionHandler.java new file mode 100644 index 000000000..0a5f8f052 --- /dev/null +++ b/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgePermissionHandler.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2019-2023 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.platform.neoforge; + +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Player; +import net.neoforged.neoforge.server.permission.PermissionAPI; +import net.neoforged.neoforge.server.permission.events.PermissionGatherEvent; +import net.neoforged.neoforge.server.permission.nodes.PermissionDynamicContextKey; +import net.neoforged.neoforge.server.permission.nodes.PermissionNode; +import net.neoforged.neoforge.server.permission.nodes.PermissionType; +import net.neoforged.neoforge.server.permission.nodes.PermissionTypes; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.Constants; +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.command.Command; +import org.geysermc.geyser.command.GeyserCommandManager; + +import java.lang.reflect.Constructor; +import java.util.HashMap; +import java.util.Map; + +public class GeyserNeoForgePermissionHandler { + + private static final Constructor PERMISSION_NODE_CONSTRUCTOR; + + static { + try { + @SuppressWarnings("rawtypes") + Constructor constructor = PermissionNode.class.getDeclaredConstructor( + String.class, + PermissionType.class, + PermissionNode.PermissionResolver.class, + PermissionDynamicContextKey[].class + ); + constructor.setAccessible(true); + PERMISSION_NODE_CONSTRUCTOR = constructor; + } catch (NoSuchMethodException e) { + throw new RuntimeException("Unable to construct PermissionNode!", e); + } + } + + private final Map> permissionNodes = new HashMap<>(); + + public void onPermissionGather(PermissionGatherEvent.Nodes event) { + this.registerNode(Constants.UPDATE_PERMISSION, event); + + GeyserCommandManager commandManager = GeyserImpl.getInstance().commandManager(); + for (Map.Entry entry : commandManager.commands().entrySet()) { + Command command = entry.getValue(); + + // Don't register aliases + if (!command.name().equals(entry.getKey())) { + continue; + } + + this.registerNode(command.permission(), event); + } + + for (Map commands : commandManager.extensionCommands().values()) { + for (Map.Entry entry : commands.entrySet()) { + Command command = entry.getValue(); + + // Don't register aliases + if (!command.name().equals(entry.getKey())) { + continue; + } + + this.registerNode(command.permission(), event); + } + } + } + + public boolean hasPermission(@NonNull Player source, @NonNull String permissionNode) { + PermissionNode node = this.permissionNodes.get(permissionNode); + if (node == null) { + GeyserImpl.getInstance().getLogger().warning("Unable to find permission node " + permissionNode); + return false; + } + + return PermissionAPI.getPermission((ServerPlayer) source, node); + } + + public boolean hasPermission(@NonNull CommandSourceStack source, @NonNull String permissionNode, int permissionLevel) { + if (!source.isPlayer()) { + return true; + } + assert source.getPlayer() != null; + boolean permission = this.hasPermission(source.getPlayer(), permissionNode); + if (!permission) { + return source.getPlayer().hasPermissions(permissionLevel); + } + + return true; + } + + private void registerNode(String node, PermissionGatherEvent.Nodes event) { + PermissionNode permissionNode = this.createNode(node); + + // NeoForge likes to crash if you try and register a duplicate node + if (!event.getNodes().contains(permissionNode)) { + event.addNodes(permissionNode); + this.permissionNodes.put(node, permissionNode); + } + } + + @SuppressWarnings("unchecked") + private PermissionNode createNode(String node) { + // The typical constructors in PermissionNode require a + // mod id, which means our permission nodes end up becoming + // geyser_neoforge. instead of just . We work around + // this by using reflection to access the constructor that + // doesn't require a mod id or ResourceLocation. + try { + return (PermissionNode) PERMISSION_NODE_CONSTRUCTOR.newInstance( + node, + PermissionTypes.BOOLEAN, + (PermissionNode.PermissionResolver) (player, playerUUID, context) -> false, + new PermissionDynamicContextKey[0] + ); + } catch (Exception e) { + throw new RuntimeException("Unable to create permission node " + node, e); + } + } +} diff --git a/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgePlatform.java b/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgePlatform.java new file mode 100644 index 000000000..63abe4a4a --- /dev/null +++ b/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgePlatform.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2019-2023 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.platform.neoforge; + +import net.minecraft.server.MinecraftServer; +import net.neoforged.fml.loading.FMLPaths; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.geyser.GeyserBootstrap; +import org.geysermc.geyser.api.util.PlatformType; +import org.geysermc.geyser.dump.BootstrapDumpInfo; +import org.geysermc.geyser.platform.mod.GeyserModBootstrap; +import org.geysermc.geyser.platform.mod.platform.GeyserModPlatform; + +import java.io.InputStream; +import java.nio.file.Path; + +public class GeyserNeoForgePlatform implements GeyserModPlatform { + + @Override + public @NonNull PlatformType platformType() { + return PlatformType.NEOFORGE; + } + + @Override + public @NonNull String configPath() { + return "Geyser-NeoForge"; + } + + @Override + public @NonNull Path dataFolder(@NonNull String modId) { + return FMLPaths.CONFIGDIR.get().resolve(modId); + } + + @Override + public @NonNull BootstrapDumpInfo dumpInfo(@NonNull MinecraftServer server) { + return new GeyserNeoForgeDumpInfo(server); + } + + @Override + public boolean testFloodgatePluginPresent(@NonNull GeyserModBootstrap bootstrap) { + return false; // No Floodgate mod for NeoForge yet + } + + @Override + public @Nullable InputStream resolveResource(@NonNull String resource) { + return GeyserBootstrap.class.getClassLoader().getResourceAsStream(resource); + } +} diff --git a/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/ModConstants.java b/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/ModConstants.java new file mode 100644 index 000000000..aa72bb2a0 --- /dev/null +++ b/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/ModConstants.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2019-2023 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.platform.neoforge; + +public class ModConstants { + public static final String MOD_ID = "geyser_neoforge"; +} diff --git a/bootstrap/mod/neoforge/src/main/resources/META-INF/mods.toml b/bootstrap/mod/neoforge/src/main/resources/META-INF/mods.toml new file mode 100644 index 000000000..2f9e9b12e --- /dev/null +++ b/bootstrap/mod/neoforge/src/main/resources/META-INF/mods.toml @@ -0,0 +1,25 @@ +modLoader="javafml" +loaderVersion="[1,)" +license="MIT" +[[mods]] +modId="geyser_neoforge" +version="${version}" +displayName="Geyser" +displayURL="https://geysermc.org/" +logoFile= "../assets/geyser/icon.png" +authors="GeyserMC" +description="${description}" +[[mixins]] +config = "geyser.mixins.json" +[[dependencies.geyser_neoforge]] + modId="neoforge" + type="required" + versionRange="[20.4.48-beta,)" + ordering="NONE" + side="BOTH" +[[dependencies.geyser_neoforge]] + modId="minecraft" + type="required" + versionRange="[1.20,1.21)" + ordering="NONE" + side="BOTH" \ No newline at end of file diff --git a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserChannelGetter.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserChannelGetter.java new file mode 100644 index 000000000..8dc0026bf --- /dev/null +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserChannelGetter.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019-2023 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.platform.mod; + +import io.netty.channel.ChannelFuture; + +import java.util.List; + +/** + * Represents a getter to the server channels in the connection listener class. + */ +public interface GeyserChannelGetter { + + /** + * Returns the channels. + * + * @return The channels. + */ + List geyser$getChannels(); +} diff --git a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMod.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModBootstrap.java similarity index 70% rename from bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMod.java rename to bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModBootstrap.java index 756063af7..db966ec1a 100644 --- a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMod.java +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModBootstrap.java @@ -23,21 +23,17 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.geyser.platform.fabric; +package org.geysermc.geyser.platform.mod; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import lombok.Getter; +import lombok.RequiredArgsConstructor; import lombok.Setter; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; -import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; -import net.fabricmc.loader.api.FabricLoader; -import net.fabricmc.loader.api.ModContainer; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.server.MinecraftServer; +import net.minecraft.world.entity.player.Player; import org.apache.logging.log4j.LogManager; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -46,7 +42,6 @@ import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserLogger; import org.geysermc.geyser.api.command.Command; import org.geysermc.geyser.api.extension.Extension; -import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.command.GeyserCommand; import org.geysermc.geyser.command.GeyserCommandManager; import org.geysermc.geyser.configuration.GeyserConfiguration; @@ -54,8 +49,9 @@ import org.geysermc.geyser.dump.BootstrapDumpInfo; import org.geysermc.geyser.level.WorldManager; import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough; import org.geysermc.geyser.ping.IGeyserPingPassthrough; -import org.geysermc.geyser.platform.fabric.command.GeyserFabricCommandExecutor; -import org.geysermc.geyser.platform.fabric.world.GeyserFabricWorldManager; +import org.geysermc.geyser.platform.mod.command.GeyserModCommandExecutor; +import org.geysermc.geyser.platform.mod.platform.GeyserModPlatform; +import org.geysermc.geyser.platform.mod.world.GeyserModWorldManager; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.util.FileUtils; @@ -64,58 +60,46 @@ import java.io.IOException; import java.io.InputStream; import java.nio.file.Path; import java.util.Map; -import java.util.Optional; import java.util.UUID; -public class GeyserFabricMod implements ModInitializer, GeyserBootstrap { +@RequiredArgsConstructor +public abstract class GeyserModBootstrap implements GeyserBootstrap { @Getter - private static GeyserFabricMod instance; + private static GeyserModBootstrap instance; + + private final GeyserModPlatform platform; + private GeyserImpl geyser; - private ModContainer mod; private Path dataFolder; @Setter private MinecraftServer server; private GeyserCommandManager geyserCommandManager; - private GeyserFabricConfiguration geyserConfig; - private GeyserFabricLogger geyserLogger; + private GeyserModConfiguration geyserConfig; + private GeyserModInjector geyserInjector; + private GeyserModLogger geyserLogger; private IGeyserPingPassthrough geyserPingPassthrough; private WorldManager geyserWorldManager; - @Override - public void onInitialize() { - instance = this; - mod = FabricLoader.getInstance().getModContainer("geyser-fabric").orElseThrow(); - onGeyserInitialize(); - } - @Override public void onGeyserInitialize() { - if (FabricLoader.getInstance().getEnvironmentType() == EnvType.SERVER) { - // Set as an event, so we can get the proper IP and port if needed - ServerLifecycleEvents.SERVER_STARTED.register((server) -> { - this.server = server; - onGeyserEnable(); - }); - } - - // These are only registered once - ServerLifecycleEvents.SERVER_STOPPING.register((server) -> onGeyserShutdown()); - ServerPlayConnectionEvents.JOIN.register((handler, $, $$) -> GeyserFabricUpdateListener.onPlayReady(handler)); - - dataFolder = FabricLoader.getInstance().getConfigDir().resolve("Geyser-Fabric"); + instance = this; + dataFolder = this.platform.dataFolder(this.platform.configPath()); GeyserLocale.init(this); if (!loadConfig()) { return; } - this.geyserLogger = new GeyserFabricLogger(geyserConfig.isDebugMode()); + this.geyserLogger = new GeyserModLogger(geyserConfig.isDebugMode()); GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); - this.geyser = GeyserImpl.load(PlatformType.FABRIC, this); + this.geyser = GeyserImpl.load(this.platform.platformType(), this); + + // Create command manager here, since the permission handler on neo needs it + this.geyserCommandManager = new GeyserCommandManager(geyser); + this.geyserCommandManager.init(); } - @Override public void onGeyserEnable() { if (GeyserImpl.getInstance().isReloading()) { if (!loadConfig()) { @@ -123,35 +107,37 @@ public class GeyserFabricMod implements ModInitializer, GeyserBootstrap { } this.geyserLogger.setDebug(geyserConfig.isDebugMode()); GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); - } else { - this.geyserCommandManager = new GeyserCommandManager(geyser); - this.geyserCommandManager.init(); } + GeyserImpl.start(); + if (geyserConfig.isLegacyPingPassthrough()) { this.geyserPingPassthrough = GeyserLegacyPingPassthrough.init(geyser); } else { this.geyserPingPassthrough = new ModPingPassthrough(server, geyserLogger); } - GeyserImpl.start(); - - // No need to re-register commands, or re-recreate the world manager when reloading + // No need to re-register commands, or try to re-inject if (GeyserImpl.getInstance().isReloading()) { return; } - this.geyserWorldManager = new GeyserFabricWorldManager(server); + this.geyserWorldManager = new GeyserModWorldManager(server); + + // We want to do this late in the server startup process to allow other mods + // To do their job injecting, then connect into *that* + this.geyserInjector = new GeyserModInjector(server, this.platform); + this.geyserInjector.initializeLocalChannel(this); // Start command building // Set just "geyser" as the help command - GeyserFabricCommandExecutor helpExecutor = new GeyserFabricCommandExecutor(geyser, + GeyserModCommandExecutor helpExecutor = new GeyserModCommandExecutor(geyser, (GeyserCommand) geyser.commandManager().getCommands().get("help")); LiteralArgumentBuilder builder = Commands.literal("geyser").executes(helpExecutor); // Register all subcommands as valid for (Map.Entry command : geyser.commandManager().getCommands().entrySet()) { - GeyserFabricCommandExecutor executor = new GeyserFabricCommandExecutor(geyser, (GeyserCommand) command.getValue()); + GeyserModCommandExecutor executor = new GeyserModCommandExecutor(geyser, (GeyserCommand) command.getValue()); builder.then(Commands.literal(command.getKey()) .executes(executor) // Could also test for Bedrock but depending on when this is called it may backfire @@ -171,12 +157,12 @@ public class GeyserFabricMod implements ModInitializer, GeyserBootstrap { } // Register help command for just "/" - GeyserFabricCommandExecutor extensionHelpExecutor = new GeyserFabricCommandExecutor(geyser, + GeyserModCommandExecutor extensionHelpExecutor = new GeyserModCommandExecutor(geyser, (GeyserCommand) extensionCommands.get("help")); LiteralArgumentBuilder extCmdBuilder = Commands.literal(extensionMapEntry.getKey().description().id()).executes(extensionHelpExecutor); for (Map.Entry command : extensionCommands.entrySet()) { - GeyserFabricCommandExecutor executor = new GeyserFabricCommandExecutor(geyser, (GeyserCommand) command.getValue()); + GeyserModCommandExecutor executor = new GeyserModCommandExecutor(geyser, (GeyserCommand) command.getValue()); extCmdBuilder.then(Commands.literal(command.getKey()) .executes(executor) .requires(executor::testPermission) @@ -201,11 +187,14 @@ public class GeyserFabricMod implements ModInitializer, GeyserBootstrap { geyser.shutdown(); geyser = null; } - this.server = null; + if (geyserInjector != null) { + geyserInjector.shutdown(); + this.server = null; + } } @Override - public GeyserConfiguration getGeyserConfig() { + public GeyserModConfiguration getGeyserConfig() { return geyserConfig; } @@ -236,7 +225,7 @@ public class GeyserFabricMod implements ModInitializer, GeyserBootstrap { @Override public BootstrapDumpInfo getDumpInfo() { - return new GeyserFabricDumpInfo(server); + return this.platform.dumpInfo(this.server); } @Override @@ -258,32 +247,19 @@ public class GeyserFabricMod implements ModInitializer, GeyserBootstrap { @Override public boolean testFloodgatePluginPresent() { - Optional floodgate = FabricLoader.getInstance().getModContainer("floodgate"); - if (floodgate.isPresent()) { - geyserConfig.loadFloodgate(this, floodgate.orElse(null)); - return true; - } - return false; + return this.platform.testFloodgatePluginPresent(this); } @Nullable @Override public InputStream getResourceOrNull(String resource) { - // We need to handle this differently, because Fabric shares the classloader across multiple mods - Path path = this.mod.findPath(resource).orElse(null); - if (path == null) { - return null; - } - - try { - return path.getFileSystem() - .provider() - .newInputStream(path); - } catch (IOException e) { - return null; - } + return this.platform.resolveResource(resource); } + public abstract boolean hasPermission(@NonNull Player source, @NonNull String permissionNode); + + public abstract boolean hasPermission(@NonNull CommandSourceStack source, @NonNull String permissionNode, int permissionLevel); + @SuppressWarnings("BooleanMethodIsAlwaysInverted") private boolean loadConfig() { try { @@ -294,10 +270,10 @@ public class GeyserFabricMod implements ModInitializer, GeyserBootstrap { File configFile = FileUtils.fileOrCopiedFromResource(dataFolder.resolve("config.yml").toFile(), "config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this); - this.geyserConfig = FileUtils.loadConfig(configFile, GeyserFabricConfiguration.class); + this.geyserConfig = FileUtils.loadConfig(configFile, GeyserModConfiguration.class); return true; } catch (IOException ex) { - LogManager.getLogger("geyser-fabric").error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex); + LogManager.getLogger("geyser").error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex); ex.printStackTrace(); return false; } diff --git a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModCompressionDisabler.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModCompressionDisabler.java new file mode 100644 index 000000000..631a21510 --- /dev/null +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModCompressionDisabler.java @@ -0,0 +1,56 @@ +/* + * 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.geyser.platform.mod; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelOutboundHandlerAdapter; +import io.netty.channel.ChannelPromise; +import net.minecraft.network.protocol.login.ClientboundGameProfilePacket; +import net.minecraft.network.protocol.login.ClientboundLoginCompressionPacket; + +/** + * Disables the compression packet (and the compression handlers from being added to the pipeline) for Geyser clients + * that won't be receiving the data over the network. + *

+ * As of 1.8 - 1.17.1, compression is enabled in the Netty pipeline by adding a listener after a packet is written. + * If we simply "cancel" or don't forward the packet, then the listener is never called. + */ +public class GeyserModCompressionDisabler extends ChannelOutboundHandlerAdapter { + + @Override + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + Class msgClass = msg.getClass(); + // Don't let any compression packet get through + if (!ClientboundLoginCompressionPacket.class.isAssignableFrom(msgClass)) { + if (ClientboundGameProfilePacket.class.isAssignableFrom(msgClass)) { + + // We're past the point that a compression packet can be sent, so we can safely yeet ourselves away + ctx.channel().pipeline().remove(this); + } + super.write(ctx, msg, promise); + } + } +} diff --git a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricConfiguration.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModConfiguration.java similarity index 80% rename from bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricConfiguration.java rename to bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModConfiguration.java index f557d16c0..a24380bd6 100644 --- a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricConfiguration.java +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModConfiguration.java @@ -23,23 +23,20 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.geyser.platform.fabric; +package org.geysermc.geyser.platform.mod; import com.fasterxml.jackson.annotation.JsonIgnore; -import net.fabricmc.loader.api.FabricLoader; -import net.fabricmc.loader.api.ModContainer; import org.geysermc.geyser.FloodgateKeyLoader; import org.geysermc.geyser.configuration.GeyserJacksonConfiguration; import java.nio.file.Path; -public class GeyserFabricConfiguration extends GeyserJacksonConfiguration { +public class GeyserModConfiguration extends GeyserJacksonConfiguration { @JsonIgnore private Path floodgateKeyPath; - public void loadFloodgate(GeyserFabricMod geyser, ModContainer floodgate) { + public void loadFloodgate(GeyserModBootstrap geyser, Path floodgateDataFolder) { Path geyserDataFolder = geyser.getConfigFolder(); - Path floodgateDataFolder = floodgate != null ? FabricLoader.getInstance().getConfigDir().resolve("floodgate") : null; floodgateKeyPath = FloodgateKeyLoader.getKeyPath(this, floodgateDataFolder, geyserDataFolder, geyser.getGeyserLogger()); } diff --git a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModInjector.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModInjector.java new file mode 100644 index 000000000..06496293f --- /dev/null +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModInjector.java @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2019-2023 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.platform.mod; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.DefaultEventLoopGroup; +import io.netty.channel.local.LocalAddress; +import io.netty.util.concurrent.DefaultThreadFactory; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerConnectionListener; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.GeyserBootstrap; +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.network.netty.GeyserInjector; +import org.geysermc.geyser.network.netty.LocalServerChannelWrapper; +import org.geysermc.geyser.platform.mod.platform.GeyserModPlatform; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.List; + +public class GeyserModInjector extends GeyserInjector { + + private final MinecraftServer server; + private final GeyserModPlatform platform; + private DefaultEventLoopGroup eventLoopGroup; + + /** + * Used to uninject ourselves on shutdown. + */ + private List allServerChannels; + + public GeyserModInjector(MinecraftServer server, GeyserModPlatform platform) { + this.server = server; + this.platform = platform; + } + + @Override + protected void initializeLocalChannel0(GeyserBootstrap bootstrap) throws Exception { + ServerConnectionListener connection = this.server.getConnection(); + + // Find the channel that Minecraft uses to listen to connections + ChannelFuture listeningChannel = null; + this.allServerChannels = ((GeyserChannelGetter) connection).geyser$getChannels(); + for (ChannelFuture o : allServerChannels) { + listeningChannel = o; + break; + } + + if (listeningChannel == null) { + throw new RuntimeException("Unable to find listening channel!"); + } + + // Making this a function prevents childHandler from being treated as a non-final variable + ChannelInitializer childHandler = getChildHandler(bootstrap, listeningChannel); + // This method is what initializes the connection in Java Edition, after Netty is all set. + Method initChannel = childHandler.getClass().getDeclaredMethod("initChannel", Channel.class); + initChannel.setAccessible(true); + + // Separate variable so we can shut it down later + eventLoopGroup = new DefaultEventLoopGroup(0, new DefaultThreadFactory("Geyser " + this.platform.platformType().platformName() + " connection thread", Thread.MAX_PRIORITY)); + ChannelFuture channelFuture = (new ServerBootstrap() + .channel(LocalServerChannelWrapper.class) + .childHandler(new ChannelInitializer<>() { + @Override + protected void initChannel(@NonNull Channel ch) throws Exception { + initChannel.invoke(childHandler, ch); + + if (bootstrap.getGeyserConfig().isDisableCompression()) { + ch.pipeline().addAfter("encoder", "geyser-compression-disabler", new GeyserModCompressionDisabler()); + } + } + }) + // Set to MAX_PRIORITY as MultithreadEventLoopGroup#newDefaultThreadFactory which DefaultEventLoopGroup implements does by default + .group(eventLoopGroup) + .localAddress(LocalAddress.ANY)) + .bind() + .syncUninterruptibly(); + // We don't need to add to the list, but plugins like ProtocolSupport and ProtocolLib that add to the main pipeline + // will work when we add to the list. + allServerChannels.add(channelFuture); + this.localChannel = channelFuture; + this.serverSocketAddress = channelFuture.channel().localAddress(); + } + + @SuppressWarnings("unchecked") + private ChannelInitializer getChildHandler(GeyserBootstrap bootstrap, ChannelFuture listeningChannel) { + List names = listeningChannel.channel().pipeline().names(); + ChannelInitializer childHandler = null; + for (String name : names) { + ChannelHandler handler = listeningChannel.channel().pipeline().get(name); + try { + Field childHandlerField = handler.getClass().getDeclaredField("childHandler"); + childHandlerField.setAccessible(true); + childHandler = (ChannelInitializer) childHandlerField.get(handler); + break; + } catch (Exception e) { + if (bootstrap.getGeyserConfig().isDebugMode()) { + bootstrap.getGeyserLogger().debug("The handler " + name + " isn't a ChannelInitializer. THIS ERROR IS SAFE TO IGNORE!"); + e.printStackTrace(); + } + } + } + if (childHandler == null) { + throw new RuntimeException(); + } + return childHandler; + } + + @Override + public void shutdown() { + if (this.allServerChannels != null) { + this.allServerChannels.remove(this.localChannel); + this.allServerChannels = null; + } + + if (eventLoopGroup != null) { + try { + eventLoopGroup.shutdownGracefully().sync(); + eventLoopGroup = null; + } catch (Exception e) { + GeyserImpl.getInstance().getLogger().error("Unable to shut down injector! " + e.getMessage()); + e.printStackTrace(); + } + } + + super.shutdown(); + } +} diff --git a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricLogger.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModLogger.java similarity index 90% rename from bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricLogger.java rename to bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModLogger.java index 180197f2d..444b725e9 100644 --- a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricLogger.java +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModLogger.java @@ -23,7 +23,7 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.geyser.platform.fabric; +package org.geysermc.geyser.platform.mod; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; @@ -32,12 +32,12 @@ import org.apache.logging.log4j.Logger; import org.geysermc.geyser.GeyserLogger; import org.geysermc.geyser.text.ChatColor; -public class GeyserFabricLogger implements GeyserLogger { - private final Logger logger = LogManager.getLogger("geyser-fabric"); +public class GeyserModLogger implements GeyserLogger { + private final Logger logger = LogManager.getLogger("geyser"); private boolean debug; - public GeyserFabricLogger(boolean isDebug) { + public GeyserModLogger(boolean isDebug) { debug = isDebug; } @@ -73,7 +73,7 @@ public class GeyserFabricLogger implements GeyserLogger { @Override public void sendMessage(Component message) { - // As of Java Edition 1.19.2, Fabric's console doesn't natively support legacy format + // As of Java Edition 1.19.2, Minecraft's console doesn't natively support legacy format String flattened = LegacyComponentSerializer.legacySection().serialize(message); // Add the reset at the end, or else format will persist... forever. // https://cdn.discordapp.com/attachments/573909525132738590/1033904509170225242/unknown.png diff --git a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricUpdateListener.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModUpdateListener.java similarity index 68% rename from bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricUpdateListener.java rename to bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModUpdateListener.java index 1ea69cbe2..11ca0bc4f 100644 --- a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricUpdateListener.java +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModUpdateListener.java @@ -23,21 +23,22 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.geyser.platform.fabric; +package org.geysermc.geyser.platform.mod; -import me.lucko.fabric.api.permissions.v0.Permissions; -import net.minecraft.server.network.ServerGamePacketListenerImpl; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.world.entity.player.Player; import org.geysermc.geyser.Constants; -import org.geysermc.geyser.platform.fabric.command.FabricCommandSender; +import org.geysermc.geyser.platform.mod.command.ModCommandSender; import org.geysermc.geyser.util.VersionCheckUtils; -public final class GeyserFabricUpdateListener { - public static void onPlayReady(ServerGamePacketListenerImpl handler) { - if (Permissions.check(handler.player, Constants.UPDATE_PERMISSION, 2)) { - VersionCheckUtils.checkForGeyserUpdate(() -> new FabricCommandSender(handler.player.createCommandSourceStack())); +public final class GeyserModUpdateListener { + public static void onPlayReady(Player player) { + CommandSourceStack stack = player.createCommandSourceStack(); + if (GeyserModBootstrap.getInstance().hasPermission(stack, Constants.UPDATE_PERMISSION, 2)) { + VersionCheckUtils.checkForGeyserUpdate(() -> new ModCommandSender(stack)); } } - private GeyserFabricUpdateListener() { + private GeyserModUpdateListener() { } } diff --git a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserServerPortGetter.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserServerPortGetter.java similarity index 97% rename from bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserServerPortGetter.java rename to bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserServerPortGetter.java index 4f1c8b638..fad0d1678 100644 --- a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserServerPortGetter.java +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserServerPortGetter.java @@ -23,7 +23,7 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.geyser.platform.fabric; +package org.geysermc.geyser.platform.mod; import net.minecraft.server.MinecraftServer; diff --git a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/ModPingPassthrough.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/ModPingPassthrough.java similarity index 94% rename from bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/ModPingPassthrough.java rename to bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/ModPingPassthrough.java index e74be7fb7..12d690d83 100644 --- a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/ModPingPassthrough.java +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/ModPingPassthrough.java @@ -23,7 +23,7 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.geyser.platform.fabric; +package org.geysermc.geyser.platform.mod; import lombok.AllArgsConstructor; import net.kyori.adventure.text.Component; @@ -39,10 +39,11 @@ import net.minecraft.network.protocol.status.ServerStatusPacketListener; import net.minecraft.network.protocol.status.ServerboundStatusRequestPacket; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerStatusPacketListenerImpl; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.GeyserLogger; import org.geysermc.geyser.ping.GeyserPingInfo; import org.geysermc.geyser.ping.IGeyserPingPassthrough; -import org.jetbrains.annotations.Nullable; import java.net.InetSocketAddress; import java.util.Objects; @@ -100,7 +101,7 @@ public class ModPingPassthrough implements IGeyserPingPassthrough { } @Override - public void send(Packet packet, @Nullable PacketSendListener packetSendListener, boolean bl) { + public void send(@NonNull Packet packet, @Nullable PacketSendListener packetSendListener, boolean bl) { if (packet instanceof ClientboundStatusResponsePacket statusResponse) { status = statusResponse.status(); } diff --git a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/command/GeyserFabricCommandExecutor.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/command/GeyserModCommandExecutor.java similarity index 82% rename from bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/command/GeyserFabricCommandExecutor.java rename to bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/command/GeyserModCommandExecutor.java index 86b50d431..694dc732e 100644 --- a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/command/GeyserFabricCommandExecutor.java +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/command/GeyserModCommandExecutor.java @@ -23,31 +23,31 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.geyser.platform.fabric.command; +package org.geysermc.geyser.platform.mod.command; import com.mojang.brigadier.Command; import com.mojang.brigadier.context.CommandContext; -import me.lucko.fabric.api.permissions.v0.Permissions; import net.minecraft.commands.CommandSourceStack; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.command.GeyserCommand; import org.geysermc.geyser.command.GeyserCommandExecutor; +import org.geysermc.geyser.platform.mod.GeyserModBootstrap; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.GeyserLocale; import java.util.Collections; -public class GeyserFabricCommandExecutor extends GeyserCommandExecutor implements Command { +public class GeyserModCommandExecutor extends GeyserCommandExecutor implements Command { private final GeyserCommand command; - public GeyserFabricCommandExecutor(GeyserImpl connector, GeyserCommand command) { - super(connector, Collections.singletonMap(command.name(), command)); + public GeyserModCommandExecutor(GeyserImpl geyser, GeyserCommand command) { + super(geyser, Collections.singletonMap(command.name(), command)); this.command = command; } public boolean testPermission(CommandSourceStack source) { - return Permissions.check(source, command.permission(), command.isSuggestedOpOnly() ? 2 : 0); + return GeyserModBootstrap.getInstance().hasPermission(source, command.permission(), command.isSuggestedOpOnly() ? 2 : 0); } @Override @@ -57,7 +57,7 @@ public class GeyserFabricCommandExecutor extends GeyserCommandExecutor implement public int runWithArgs(CommandContext context, String args) { CommandSourceStack source = context.getSource(); - FabricCommandSender sender = new FabricCommandSender(source); + ModCommandSender sender = new ModCommandSender(source); GeyserSession session = getGeyserSession(sender); if (!testPermission(source)) { sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.permission_fail", sender.locale())); diff --git a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/command/FabricCommandSender.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/command/ModCommandSender.java similarity index 88% rename from bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/command/FabricCommandSender.java rename to bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/command/ModCommandSender.java index 28875ec6e..17154ffd8 100644 --- a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/command/FabricCommandSender.java +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/command/ModCommandSender.java @@ -23,9 +23,8 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.geyser.platform.fabric.command; +package org.geysermc.geyser.platform.mod.command; -import me.lucko.fabric.api.permissions.v0.Permissions; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.minecraft.commands.CommandSourceStack; import net.minecraft.network.chat.Component; @@ -33,15 +32,16 @@ import net.minecraft.server.level.ServerPlayer; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.command.GeyserCommandSource; +import org.geysermc.geyser.platform.mod.GeyserModBootstrap; import org.geysermc.geyser.text.ChatColor; import java.util.Objects; -public class FabricCommandSender implements GeyserCommandSource { +public class ModCommandSender implements GeyserCommandSource { private final CommandSourceStack source; - public FabricCommandSender(CommandSourceStack source) { + public ModCommandSender(CommandSourceStack source) { this.source = source; } @@ -76,6 +76,6 @@ public class FabricCommandSender implements GeyserCommandSource { @Override public boolean hasPermission(String permission) { - return Permissions.check(source, permission, source.getServer().getOperatorUserPermissionLevel()); + return GeyserModBootstrap.getInstance().hasPermission(source, permission, source.getServer().getOperatorUserPermissionLevel()); } } diff --git a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/mixin/client/IntegratedServerMixin.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/mixin/client/IntegratedServerMixin.java similarity index 85% rename from bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/mixin/client/IntegratedServerMixin.java rename to bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/mixin/client/IntegratedServerMixin.java index 999a077bb..4db1165fc 100644 --- a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/mixin/client/IntegratedServerMixin.java +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/mixin/client/IntegratedServerMixin.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2023 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 @@ -23,18 +23,16 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.geyser.platform.fabric.mixin.client; +package org.geysermc.geyser.platform.mod.mixin.client; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; import net.minecraft.client.Minecraft; import net.minecraft.client.server.IntegratedServer; import net.minecraft.network.chat.Component; import net.minecraft.server.MinecraftServer; import net.minecraft.world.level.GameType; import org.geysermc.geyser.GeyserImpl; -import org.geysermc.geyser.platform.fabric.GeyserFabricMod; -import org.geysermc.geyser.platform.fabric.GeyserServerPortGetter; +import org.geysermc.geyser.platform.mod.GeyserModBootstrap; +import org.geysermc.geyser.platform.mod.GeyserServerPortGetter; import org.geysermc.geyser.text.GeyserLocale; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -45,7 +43,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.Objects; -@Environment(EnvType.CLIENT) @Mixin(IntegratedServer.class) public class IntegratedServerMixin implements GeyserServerPortGetter { @Shadow @@ -57,8 +54,8 @@ public class IntegratedServerMixin implements GeyserServerPortGetter { private void onOpenToLan(GameType gameType, boolean cheatsAllowed, int port, CallbackInfoReturnable cir) { if (cir.getReturnValueZ()) { // If the LAN is opened, starts Geyser. - GeyserFabricMod.getInstance().setServer((MinecraftServer) (Object) this); - GeyserFabricMod.getInstance().onGeyserEnable(); + GeyserModBootstrap.getInstance().setServer((MinecraftServer) (Object) this); + GeyserModBootstrap.getInstance().onGeyserEnable(); // Ensure player locale has been loaded, in case it's different from Java system language GeyserLocale.loadGeyserLocale(this.minecraft.options.languageCode); // Give indication that Geyser is loaded diff --git a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/mixin/server/MinecraftDedicatedServerMixin.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/mixin/server/DedicatedServerMixin.java similarity index 76% rename from bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/mixin/server/MinecraftDedicatedServerMixin.java rename to bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/mixin/server/DedicatedServerMixin.java index 23e148775..3b809d321 100644 --- a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/mixin/server/MinecraftDedicatedServerMixin.java +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/mixin/server/DedicatedServerMixin.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2023 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 @@ -23,7 +23,7 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.geyser.platform.fabric.mixin.server; +package org.geysermc.geyser.platform.mod.mixin.server; import com.mojang.datafixers.DataFixer; import net.minecraft.server.MinecraftServer; @@ -33,14 +33,14 @@ import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.server.level.progress.ChunkProgressListenerFactory; import net.minecraft.server.packs.repository.PackRepository; import net.minecraft.world.level.storage.LevelStorageSource; -import org.geysermc.geyser.platform.fabric.GeyserServerPortGetter; +import org.geysermc.geyser.platform.mod.GeyserServerPortGetter; import org.spongepowered.asm.mixin.Mixin; import java.net.Proxy; @Mixin(DedicatedServer.class) -public abstract class MinecraftDedicatedServerMixin extends MinecraftServer implements GeyserServerPortGetter { - public MinecraftDedicatedServerMixin(Thread thread, LevelStorageSource.LevelStorageAccess levelStorageAccess, PackRepository packRepository, WorldStem worldStem, Proxy proxy, DataFixer dataFixer, Services services, ChunkProgressListenerFactory chunkProgressListenerFactory) { +public abstract class DedicatedServerMixin extends MinecraftServer implements GeyserServerPortGetter { + public DedicatedServerMixin(Thread thread, LevelStorageSource.LevelStorageAccess levelStorageAccess, PackRepository packRepository, WorldStem worldStem, Proxy proxy, DataFixer dataFixer, Services services, ChunkProgressListenerFactory chunkProgressListenerFactory) { super(thread, levelStorageAccess, packRepository, worldStem, proxy, dataFixer, services, chunkProgressListenerFactory); } diff --git a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/mixin/server/ServerConnectionListenerMixin.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/mixin/server/ServerConnectionListenerMixin.java new file mode 100644 index 000000000..52941d631 --- /dev/null +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/mixin/server/ServerConnectionListenerMixin.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2019-2023 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.platform.mod.mixin.server; + +import io.netty.channel.ChannelFuture; +import net.minecraft.server.network.ServerConnectionListener; +import org.geysermc.geyser.platform.mod.GeyserChannelGetter; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.List; + +@Mixin(ServerConnectionListener.class) +public abstract class ServerConnectionListenerMixin implements GeyserChannelGetter { + + @Shadow @Final private List channels; + + @Override + public List geyser$getChannels() { + return this.channels; + } +} diff --git a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/platform/GeyserModPlatform.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/platform/GeyserModPlatform.java new file mode 100644 index 000000000..2f615591b --- /dev/null +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/platform/GeyserModPlatform.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2019-2023 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.platform.mod.platform; + +import net.minecraft.server.MinecraftServer; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.geyser.api.util.PlatformType; +import org.geysermc.geyser.dump.BootstrapDumpInfo; +import org.geysermc.geyser.platform.mod.GeyserModBootstrap; + +import java.io.InputStream; +import java.nio.file.Path; + +/** + * An interface which holds common methods that have different + * APIs on their respective mod platforms. + */ +public interface GeyserModPlatform { + + /** + * Gets the {@link PlatformType} of the mod platform. + * + * @return the platform type of the mod platform + */ + @NonNull + PlatformType platformType(); + + /** + * Gets the config path of the mod platform. + * + * @return the config path of the mod platform + */ + @NonNull + String configPath(); + + /** + * Gets the data folder of the mod platform. + * + * @return the data folder of the mod platform + */ + @NonNull + Path dataFolder(@NonNull String modId); + + /** + * Gets the dump info of the mod platform. + * + * @param server the server to get the dump info from + * @return the dump info of the mod platform + */ + @NonNull + BootstrapDumpInfo dumpInfo(@NonNull MinecraftServer server); + + /** + * Tests if the Floodgate plugin is present on the mod platform. + * + * @return {@code true} if the Floodgate plugin is present on the mod platform, {@code false} otherwise + */ + boolean testFloodgatePluginPresent(@NonNull GeyserModBootstrap bootstrap); + + /** + * Resolves a resource from the mod jar. + * + * @param resource the name of the resource + * @return the input stream of the resource + */ + @Nullable + InputStream resolveResource(@NonNull String resource); +} diff --git a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/world/GeyserFabricWorldManager.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/world/GeyserModWorldManager.java similarity index 81% rename from bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/world/GeyserFabricWorldManager.java rename to bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/world/GeyserModWorldManager.java index 9d7b81831..04c538632 100644 --- a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/world/GeyserFabricWorldManager.java +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/world/GeyserModWorldManager.java @@ -23,22 +23,41 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.geyser.platform.fabric.world; +package org.geysermc.geyser.platform.mod.world; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityInfo; -import me.lucko.fabric.api.permissions.v0.Permissions; +import net.minecraft.SharedConstants; import net.minecraft.core.BlockPos; -import net.minecraft.nbt.*; +import net.minecraft.nbt.ByteArrayTag; +import net.minecraft.nbt.ByteTag; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.DoubleTag; +import net.minecraft.nbt.EndTag; +import net.minecraft.nbt.FloatTag; +import net.minecraft.nbt.IntArrayTag; +import net.minecraft.nbt.IntTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.LongArrayTag; +import net.minecraft.nbt.LongTag; +import net.minecraft.nbt.ShortTag; +import net.minecraft.nbt.StringTag; +import net.minecraft.nbt.Tag; +import net.minecraft.nbt.TagVisitor; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.WritableBookItem; import net.minecraft.world.item.WrittenBookItem; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BannerBlockEntity; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.LecternBlockEntity; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.ChunkStatus; import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.chunk.LevelChunkSection; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; @@ -46,6 +65,8 @@ import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; import org.geysermc.erosion.util.LecternUtils; import org.geysermc.geyser.level.GeyserWorldManager; +import org.geysermc.geyser.network.GameProtocol; +import org.geysermc.geyser.platform.mod.GeyserModBootstrap; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.BlockEntityUtils; @@ -54,13 +75,54 @@ import java.util.List; import java.util.Objects; import java.util.concurrent.CompletableFuture; -public class GeyserFabricWorldManager extends GeyserWorldManager { +public class GeyserModWorldManager extends GeyserWorldManager { private final MinecraftServer server; - public GeyserFabricWorldManager(MinecraftServer server) { + public GeyserModWorldManager(MinecraftServer server) { this.server = server; } + @Override + public int getBlockAt(GeyserSession session, int x, int y, int z) { + // If the protocol version of Geyser and the server are not the + // same, fallback to the chunk cache. May be able to update this + // in the future to use ViaVersion however, like Spigot does. + if (SharedConstants.getCurrentVersion().getProtocolVersion() != GameProtocol.getJavaProtocolVersion()) { + return super.getBlockAt(session, x, y, z); + } + + ServerPlayer player = this.getPlayer(session); + if (player == null) { + return 0; + } + + Level level = player.level(); + if (y < level.getMinBuildHeight()) { + return 0; + } + + ChunkAccess chunk = level.getChunkSource().getChunk(x >> 4, z >> 4, ChunkStatus.FULL, false); + if (chunk == null) { + return 0; + } + + int worldOffset = level.getMinBuildHeight() >> 4; + int chunkOffset = (y >> 4) - worldOffset; + if (chunkOffset < chunk.getSections().length) { + LevelChunkSection section = chunk.getSections()[chunkOffset]; + if (section != null && !section.hasOnlyAir()) { + return Block.getId(section.getBlockState(x & 15, y & 15, z & 15)); + } + } + + return 0; + } + + @Override + public boolean hasOwnChunkCache() { + return SharedConstants.getCurrentVersion().getProtocolVersion() == GameProtocol.getJavaProtocolVersion(); + } + @Override public boolean shouldExpectLecternHandled(GeyserSession session) { return true; @@ -154,7 +216,7 @@ public class GeyserFabricWorldManager extends GeyserWorldManager { @Override public boolean hasPermission(GeyserSession session, String permission) { ServerPlayer player = getPlayer(session); - return Permissions.check(player, permission); + return GeyserModBootstrap.getInstance().hasPermission(player, permission); } @Override diff --git a/bootstrap/mod/src/main/resources/geyser.mixins.json b/bootstrap/mod/src/main/resources/geyser.mixins.json new file mode 100644 index 000000000..47b2f60f3 --- /dev/null +++ b/bootstrap/mod/src/main/resources/geyser.mixins.json @@ -0,0 +1,18 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "org.geysermc.geyser.platform.mod.mixin", + "compatibilityLevel": "JAVA_17", + "mixins": [ + "server.ServerConnectionListenerMixin" + ], + "server": [ + "server.DedicatedServerMixin" + ], + "client": [ + "client.IntegratedServerMixin" + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/gui/GeyserStandaloneGUI.java b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/gui/GeyserStandaloneGUI.java index c3e2e10e8..b82d8cc94 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/gui/GeyserStandaloneGUI.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/gui/GeyserStandaloneGUI.java @@ -100,7 +100,7 @@ public class GeyserStandaloneGUI { Container cp = frame.getContentPane(); // Fetch and set the icon for the frame - URL image = getClass().getClassLoader().getResource("icon.png"); + URL image = getClass().getClassLoader().getResource("assets/geyser/icon.png"); if (image != null) { ImageIcon icon = new ImageIcon(image); frame.setIconImage(icon.getImage()); diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts index c0c683920..b7aab2bf0 100644 --- a/build-logic/build.gradle.kts +++ b/build-logic/build.gradle.kts @@ -4,14 +4,17 @@ plugins { repositories { gradlePluginPortal() - maven("https://repo.opencollab.dev/maven-snapshots") + + maven("https://repo.opencollab.dev/maven-snapshots/") + maven("https://maven.fabricmc.net/") + maven("https://maven.neoforged.net/releases") + maven("https://maven.architectury.dev/") } dependencies { - implementation("net.kyori", "indra-common", "3.1.1") - implementation("com.github.johnrengelman", "shadow", "7.1.3-SNAPSHOT") - - // Within the gradle plugin classpath, there is a version conflict between loom and some other - // plugin for databind. This fixes it: minimum 2.13.2 is required by loom. - implementation("com.fasterxml.jackson.core:jackson-databind:2.14.0") + implementation(libs.indra) + implementation(libs.shadow) + implementation(libs.architectury.plugin) + implementation(libs.architectury.loom) + implementation(libs.minotaur) } diff --git a/build-logic/settings.gradle.kts b/build-logic/settings.gradle.kts new file mode 100644 index 000000000..63bde189b --- /dev/null +++ b/build-logic/settings.gradle.kts @@ -0,0 +1,11 @@ +@file:Suppress("UnstableApiUsage") + +dependencyResolutionManagement { + versionCatalogs { + create("libs") { + from(files("../gradle/libs.versions.toml")) + } + } +} + +rootProject.name = "build-logic" \ No newline at end of file diff --git a/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts b/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts index c9f984596..3d41a3dd6 100644 --- a/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts @@ -22,8 +22,8 @@ indra { tasks { processResources { - // Spigot, BungeeCord, Velocity, Fabric, ViaProxy - filesMatching(listOf("plugin.yml", "bungee.yml", "velocity-plugin.json", "fabric.mod.json", "viaproxy.yml")) { + // Spigot, BungeeCord, Velocity, Fabric, ViaProxy, NeoForge + filesMatching(listOf("plugin.yml", "bungee.yml", "velocity-plugin.json", "fabric.mod.json", "viaproxy.yml", "META-INF/mods.toml")) { expand( "id" to "geyser", "name" to "Geyser", @@ -34,4 +34,4 @@ tasks { ) } } -} +} \ No newline at end of file diff --git a/bootstrap/fabric/build.gradle.kts b/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts similarity index 70% rename from bootstrap/fabric/build.gradle.kts rename to build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts index 66af130b3..0842eae84 100644 --- a/bootstrap/fabric/build.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts @@ -1,50 +1,22 @@ +@file:Suppress("UnstableApiUsage") + import net.fabricmc.loom.task.RemapJarTask +import org.gradle.kotlin.dsl.dependencies +import org.gradle.kotlin.dsl.maven plugins { - id("fabric-loom") version "1.0-SNAPSHOT" - id("com.modrinth.minotaur") version "2.+" + id("geyser.publish-conventions") + id("architectury-plugin") + id("dev.architectury.loom") + id("com.modrinth.minotaur") } -dependencies { - //to change the versions see the gradle.properties file - minecraft(libs.fabric.minecraft) - mappings(loom.officialMojangMappings()) - modImplementation(libs.fabric.loader) - - // Fabric API. This is technically optional, but you probably want it anyway. - modImplementation(libs.fabric.api) - - // This should be in the libs TOML, but something about modImplementation AND include just doesn't work - include(modImplementation("me.lucko", "fabric-permissions-api", "0.2-SNAPSHOT")) - - // PSA: Some older mods, compiled on Loom 0.2.1, might have outdated Maven POMs. - // You may need to force-disable transitiveness on them. - - api(projects.core) - shadow(projects.core) { - exclude(group = "com.google.guava", module = "guava") - exclude(group = "com.google.code.gson", module = "gson") - exclude(group = "org.slf4j") - exclude(group = "com.nukkitx.fastutil") - exclude(group = "io.netty.incubator") - } +architectury { + minecraft = "1.20.4" } loom { - mixin.defaultRefmapName.set("geyser-fabric-refmap.json") -} - -repositories { - mavenLocal() - maven("https://repo.opencollab.dev/maven-releases/") - maven("https://repo.opencollab.dev/maven-snapshots/") - maven("https://jitpack.io") - maven("https://oss.sonatype.org/content/repositories/snapshots/") - maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") -} - -application { - mainClass.set("org.geysermc.geyser.platform.fabric.GeyserFabricMain") + silentMojangMappingsLicense() } tasks { @@ -59,7 +31,7 @@ tasks { shadowJar { // Mirrors the example fabric project, otherwise tons of dependencies are shaded that shouldn't be configurations = listOf(project.configurations.shadow.get()) - // The remapped shadowJar is the final desired Geyser-Fabric.jar + // The remapped shadowJar is the final desired mod jar archiveVersion.set(project.version.toString()) archiveClassifier.set("shaded") @@ -89,20 +61,32 @@ tasks { remapJar { dependsOn(shadowJar) inputFile.set(shadowJar.get().archiveFile) - archiveBaseName.set("Geyser-Fabric") - archiveVersion.set("") archiveClassifier.set("") + archiveVersion.set("") } register("remapModrinthJar", RemapJarTask::class) { dependsOn(shadowJar) inputFile.set(shadowJar.get().archiveFile) - archiveBaseName.set("geyser-fabric") archiveVersion.set(project.version.toString() + "+build." + System.getenv("GITHUB_RUN_NUMBER")) archiveClassifier.set("") } } +dependencies { + minecraft("com.mojang:minecraft:1.20.4") + mappings(loom.officialMojangMappings()) +} + +repositories { + maven("https://repo.opencollab.dev/maven-releases/") + maven("https://repo.opencollab.dev/maven-snapshots/") + maven("https://jitpack.io") + maven("https://oss.sonatype.org/content/repositories/snapshots/") + maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") + maven("https://maven.neoforged.net/releases") +} + modrinth { token.set(System.getenv("MODRINTH_TOKEN")) // Even though this is the default value, apparently this prevents GitHub Actions caching the token? projectId.set("wKkoqHrH") @@ -114,11 +98,5 @@ modrinth { uploadFile.set(tasks.getByPath("remapModrinthJar")) gameVersions.addAll("1.20.4") - - loaders.add("fabric") failSilently.set(true) - - dependencies { - required.project("fabric-api") - } -} +} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 1d434e599..dfdff2187 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,9 +1,9 @@ plugins { `java-library` // Ensure AP works in eclipse (no effect on other IDEs) - `eclipse` + eclipse id("geyser.build-logic") - id("io.freefair.lombok") version "6.3.0" apply false + alias(libs.plugins.lombok) apply false } allprojects { @@ -12,14 +12,7 @@ allprojects { description = properties["description"] as String } -java { - toolchain { - languageVersion.set(JavaLanguageVersion.of(17)) - } -} - -val platforms = setOf( - projects.fabric, +val basePlatforms = setOf( projects.bungeecord, projects.spigot, projects.standalone, @@ -27,6 +20,12 @@ val platforms = setOf( projects.viaproxy ).map { it.dependencyProject } +val moddedPlatforms = setOf( + projects.fabric, + projects.neoforge, + projects.mod +).map { it.dependencyProject } + subprojects { apply { plugin("java-library") @@ -35,7 +34,8 @@ subprojects { } when (this) { - in platforms -> plugins.apply("geyser.platform-conventions") + in basePlatforms -> plugins.apply("geyser.platform-conventions") + in moddedPlatforms -> plugins.apply("geyser.modded-conventions") else -> plugins.apply("geyser.base-conventions") } -} +} \ No newline at end of file diff --git a/core/build.gradle.kts b/core/build.gradle.kts index f67b652be..6d289ae37 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -1,8 +1,7 @@ import net.kyori.blossom.BlossomExtension plugins { - id("net.kyori.blossom") - id("net.kyori.indra.git") + alias(libs.plugins.blossom) id("geyser.publish-conventions") } diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index 6a8efaba1..8b54f5298 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -221,6 +221,7 @@ public class GeyserImpl implements GeyserApi { if (ex != null) { return; } + MinecraftLocale.ensureEN_US(); String locale = GeyserLocale.getDefaultLocale(); if (!"en_us".equals(locale)) { diff --git a/core/src/main/java/org/geysermc/geyser/pack/SkullResourcePackManager.java b/core/src/main/java/org/geysermc/geyser/pack/SkullResourcePackManager.java index e7a9f4f1e..f6c5140d8 100644 --- a/core/src/main/java/org/geysermc/geyser/pack/SkullResourcePackManager.java +++ b/core/src/main/java/org/geysermc/geyser/pack/SkullResourcePackManager.java @@ -187,7 +187,7 @@ public class SkullResourcePackManager { ZipEntry entry = new ZipEntry("skull_resource_pack/pack_icon.png"); zipOS.putNextEntry(entry); - zipOS.write(FileUtils.readAllBytes("icon.png")); + zipOS.write(FileUtils.readAllBytes("assets/geyser/icon.png")); zipOS.closeEntry(); } } diff --git a/core/src/main/java/org/geysermc/geyser/session/PendingMicrosoftAuthentication.java b/core/src/main/java/org/geysermc/geyser/session/PendingMicrosoftAuthentication.java index 132de67cb..0651039a0 100644 --- a/core/src/main/java/org/geysermc/geyser/session/PendingMicrosoftAuthentication.java +++ b/core/src/main/java/org/geysermc/geyser/session/PendingMicrosoftAuthentication.java @@ -123,7 +123,8 @@ public class PendingMicrosoftAuthentication { public CompletableFuture getCode(boolean offlineAccess) { // Request the code - CompletableFuture code = CompletableFuture.supplyAsync(() -> tryGetCode(offlineAccess)); + CompletableFuture code = CompletableFuture.supplyAsync( + () -> tryGetCode(offlineAccess)); // Once the code is received, continuously try to request the access token, profile, etc code.thenRun(() -> performLoginAttempt(System.currentTimeMillis())); return code; diff --git a/bootstrap/fabric/src/main/resources/assets/geyser-fabric/icon.png b/core/src/main/resources/assets/geyser/icon.png similarity index 100% rename from bootstrap/fabric/src/main/resources/assets/geyser-fabric/icon.png rename to core/src/main/resources/assets/geyser/icon.png diff --git a/core/src/main/resources/icon.png b/core/src/main/resources/icon.png deleted file mode 100644 index 4e6a38a787f0ed02a93b2580b5be0e838ffefea3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 115461 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�? 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 diff --git a/gradle.properties b/gradle.properties index 74504759e..a8e5eaaaf 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,8 +1,8 @@ # Gradle settings org.gradle.jvmargs=-Xmx4G -org.gradle.configureondemand=true -org.gradle.caching=true +org.gradle.daemon=false org.gradle.parallel=true +org.gradle.caching=true org.gradle.vfs.watch=false group=org.geysermc diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0dc0fbc4a..4ce5dda1a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -32,6 +32,18 @@ viaproxy = "3.2.0-SNAPSHOT" fabric-minecraft = "1.20.4" fabric-loader = "0.15.2" fabric-api = "0.91.2+1.20.4" +fabric-permissions = "0.2-SNAPSHOT" +neoforge-minecraft = "20.4.48-beta" +mixin = "0.8.5" + +# plugin versions +indra = "3.1.3" +shadow = "7.1.3-SNAPSHOT" +architectury-plugin = "3.4-SNAPSHOT" +architectury-loom = "1.4-SNAPSHOT" +minotaur = "2.8.7" +lombok = "8.4" +blossom = "1.2.0" [libraries] base-api = { group = "org.geysermc.api", name = "base-api", version.ref = "base-api" } @@ -75,10 +87,15 @@ jline-reader = { group = "org.jline", name = "jline-reader", version.ref = "jlin folia-api = { group = "dev.folia", name = "folia-api", version.ref = "folia" } paper-mojangapi = { group = "io.papermc.paper", name = "paper-mojangapi", version.ref = "folia" } -# check these on https://modmuss50.me/fabric.html +mixin = { group = "org.spongepowered", name = "mixin", version.ref = "mixin" } + +# Check these on https://modmuss50.me/fabric.html fabric-minecraft = { group = "com.mojang", name = "minecraft", version.ref = "fabric-minecraft" } fabric-loader = { group = "net.fabricmc", name = "fabric-loader", version.ref = "fabric-loader" } fabric-api = { group = "net.fabricmc.fabric-api", name = "fabric-api", version.ref = "fabric-api" } +fabric-permissions = { group = "me.lucko", name = "fabric-permissions-api", version.ref = "fabric-permissions" } + +neoforge-minecraft = { group = "net.neoforged", name = "neoforge", version.ref = "neoforge-minecraft" } adapters-spigot = { group = "org.geysermc.geyser.adapters", name = "spigot-all", version.ref = "adapters" } bungeecord-proxy = { group = "com.github.SpigotMC.BungeeCord", name = "bungeecord-proxy", version.ref = "bungeecord" } @@ -104,6 +121,18 @@ math = { group = "org.cloudburstmc.math", name = "immutable", version = "2.0" } blockstateupdater = { group = "org.cloudburstmc", name = "block-state-updater", version.ref = "blockstateupdater"} +# plugins +indra = { group = "net.kyori", name = "indra-common", version.ref = "indra" } +shadow = { group = "com.github.johnrengelman", name = "shadow", version.ref = "shadow" } +architectury-plugin = { group = "architectury-plugin", name = "architectury-plugin.gradle.plugin", version.ref = "architectury-plugin" } +architectury-loom = { group = "dev.architectury.loom", name = "dev.architectury.loom.gradle.plugin", version.ref = "architectury-loom" } +minotaur = { group = "com.modrinth.minotaur", name = "Minotaur", version.ref = "minotaur" } + +[plugins] +lombok = { id = "io.freefair.lombok", version.ref = "lombok" } +indra = { id = "net.kyori.indra", version.ref = "indra" } +blossom = { id = "net.kyori.blossom", version.ref = "blossom" } + [bundles] jackson = [ "jackson-annotations", "jackson-core", "jackson-dataformat-yaml" ] fastutil = [ "fastutil-int-int-maps", "fastutil-int-long-maps", "fastutil-int-byte-maps", "fastutil-int-boolean-maps", "fastutil-object-int-maps", "fastutil-object-object-maps" ] diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ae04661ee..db9a6b825 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/settings.gradle.kts b/settings.gradle.kts index 6c644bf09..68848bca4 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,7 +1,8 @@ +@file:Suppress("UnstableApiUsage") + enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") dependencyResolutionManagement { -// repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { // Floodgate, Cumulus etc. maven("https://repo.opencollab.dev/main") @@ -18,6 +19,11 @@ dependencyResolutionManagement { mavenContent { snapshotsOnly() } } + // NeoForge + maven("https://maven.neoforged.net/releases") { + mavenContent { releasesOnly() } + } + // Minecraft maven("https://libraries.minecraft.net") { name = "minecraft" @@ -44,13 +50,11 @@ dependencyResolutionManagement { pluginManagement { repositories { gradlePluginPortal() + + maven("https://repo.opencollab.dev/maven-snapshots/") maven("https://maven.fabricmc.net/") - maven("https://repo.opencollab.dev/maven-snapshots") - } - plugins { - id("net.kyori.blossom") version "1.2.0" - id("net.kyori.indra") - id("net.kyori.indra.git") + maven("https://maven.architectury.dev/") + maven("https://maven.neoforged.net/releases") } includeBuild("build-logic") } @@ -61,6 +65,8 @@ include(":ap") include(":api") include(":bungeecord") include(":fabric") +include(":neoforge") +include(":mod") include(":spigot") include(":standalone") include(":velocity") @@ -70,7 +76,9 @@ include(":core") // Specify project dirs project(":bungeecord").projectDir = file("bootstrap/bungeecord") -project(":fabric").projectDir = file("bootstrap/fabric") +project(":fabric").projectDir = file("bootstrap/mod/fabric") +project(":neoforge").projectDir = file("bootstrap/mod/neoforge") +project(":mod").projectDir = file("bootstrap/mod") project(":spigot").projectDir = file("bootstrap/spigot") project(":standalone").projectDir = file("bootstrap/standalone") project(":velocity").projectDir = file("bootstrap/velocity") From f8e6d26fc2ee7e507085472015812683cc6e803d Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 23 Feb 2024 18:40:41 +0100 Subject: [PATCH 190/344] Fix mod platform publishing (#4454) --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cd579c931..b316cd037 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -120,6 +120,7 @@ jobs: ssh -o StrictHostKeyChecking=no -i id_ecdsa $DOWNLOADS_USERNAME@$DOWNLOADS_SERVER_IP mkdir -p "~/uploads/$project/$GITHUB_RUN_NUMBER/" # Copy over artifacts rsync -P -e "ssh -o StrictHostKeyChecking=no -i id_ecdsa" bootstrap/**/build/libs/Geyser-*.jar $DOWNLOADS_USERNAME@$DOWNLOADS_SERVER_IP:~/uploads/$project/$GITHUB_RUN_NUMBER/ + rsync -P -e "ssh -o StrictHostKeyChecking=no -i id_ecdsa" bootstrap/mod/**/build/libs/Geyser-*.jar $DOWNLOADS_USERNAME@$DOWNLOADS_SERVER_IP:~/uploads/$project/$GITHUB_RUN_NUMBER/ # Run the build script # Push the metadata echo "{\"project\": \"$project\", \"version\": \"$version\", \"id\": $GITHUB_RUN_NUMBER, \"commit\": \"$GITHUB_SHA\"}" > metadata.json From 3c4a1a82c9ca8c990dae89ad55a3e9c395f878ef Mon Sep 17 00:00:00 2001 From: rtm516 Date: Sat, 2 Mar 2024 00:56:35 +0000 Subject: [PATCH 191/344] Deprecate unit cube in block components (#4470) * Depricate unit cube * Didn't mean to remove that --- .../custom/component/CustomBlockComponents.java | 7 +++++++ .../level/block/GeyserCustomBlockComponents.java | 12 ++++++++---- .../mappings/versions/MappingsReader_v1.java | 4 +++- .../populator/CustomBlockRegistryPopulator.java | 4 ---- 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/api/src/main/java/org/geysermc/geyser/api/block/custom/component/CustomBlockComponents.java b/api/src/main/java/org/geysermc/geyser/api/block/custom/component/CustomBlockComponents.java index 63788df8e..06608f787 100644 --- a/api/src/main/java/org/geysermc/geyser/api/block/custom/component/CustomBlockComponents.java +++ b/api/src/main/java/org/geysermc/geyser/api/block/custom/component/CustomBlockComponents.java @@ -129,8 +129,11 @@ public interface CustomBlockComponents { * Gets the unit cube component * Equivalent to "minecraft:unit_cube" * + * @deprecated Use {@link #geometry()} and compare with `minecraft:geometry.full_block` instead. + * * @return The rotation. */ + @Deprecated boolean unitCube(); /** @@ -181,6 +184,10 @@ public interface CustomBlockComponents { Builder transformation(TransformationComponent transformation); + /** + * @deprecated Use {@link #geometry(GeometryComponent)} with `minecraft:geometry.full_block` instead. + */ + @Deprecated Builder unitCube(boolean unitCube); Builder placeAir(boolean placeAir); diff --git a/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockComponents.java b/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockComponents.java index 1fa863d55..dfcb548ee 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockComponents.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockComponents.java @@ -58,7 +58,6 @@ public class GeyserCustomBlockComponents implements CustomBlockComponents { Integer lightEmission; Integer lightDampening; TransformationComponent transformation; - boolean unitCube; boolean placeAir; Set tags; @@ -66,7 +65,13 @@ public class GeyserCustomBlockComponents implements CustomBlockComponents { this.selectionBox = builder.selectionBox; this.collisionBox = builder.collisionBox; this.displayName = builder.displayName; - this.geometry = builder.geometry; + GeometryComponent geo = builder.geometry; + if (builder.unitCube && geo == null) { + geo = GeometryComponent.builder() + .identifier("minecraft:geometry.full_block") + .build(); + } + this.geometry = geo; if (builder.materialInstances.isEmpty()) { this.materialInstances = Object2ObjectMaps.emptyMap(); } else { @@ -78,7 +83,6 @@ public class GeyserCustomBlockComponents implements CustomBlockComponents { this.lightEmission = builder.lightEmission; this.lightDampening = builder.lightDampening; this.transformation = builder.transformation; - this.unitCube = builder.unitCube; this.placeAir = builder.placeAir; if (builder.tags.isEmpty()) { this.tags = Set.of(); @@ -144,7 +148,7 @@ public class GeyserCustomBlockComponents implements CustomBlockComponents { @Override public boolean unitCube() { - return unitCube; + return geometry.identifier().equals("minecraft:geometry.full_block"); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java b/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java index 0bc55c7b1..ce4a8f30e 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java +++ b/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java @@ -488,7 +488,9 @@ public class MappingsReader_v1 extends MappingsReader { } if (node.has("unit_cube")) { - builder.unitCube(node.get("unit_cube").asBoolean()); + builder.geometry(GeometryComponent.builder() + .identifier("minecraft:geometry.full_block") + .build()); } if (node.has("material_instances")) { diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java index ea33450bf..36b1fc859 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java @@ -422,10 +422,6 @@ public class CustomBlockRegistryPopulator { .build()); } - if (components.unitCube()) { - builder.putCompound("minecraft:unit_cube", NbtMap.EMPTY); - } - // place_air is not an actual component // We just apply a dummy event to prevent the client from trying to place a block // This mitigates the issue with the client sometimes double placing blocks From 5d95bf65a6f13baa4fb9ad3b6a6b0c0c42c43ab9 Mon Sep 17 00:00:00 2001 From: chris Date: Sat, 2 Mar 2024 03:21:31 +0100 Subject: [PATCH 192/344] Fix lecterns on 1.20.60, add support for virtual books (#4471) * Fix lecterns on 1.20.60, start on virtual lecterns * Fix: virtual books & actual books opening twice, resolve other issues, remove debug * undo some unnecessary diff * Don't try to send virtual books to pre 1.20.60 clients * address review by camotoy --- .../holder/BlockInventoryHolder.java | 30 +++++-- .../inventory/item/StoredItemMappings.java | 2 + .../geyser/session/GeyserSession.java | 7 ++ .../inventory/LecternInventoryTranslator.java | 71 ++++++++++++--- ...BedrockInventoryTransactionTranslator.java | 4 +- .../BedrockLecternUpdateTranslator.java | 11 +++ .../player/BedrockInteractTranslator.java | 5 ++ .../JavaContainerSetContentTranslator.java | 11 +-- .../JavaContainerSetSlotTranslator.java | 15 ++-- .../inventory/JavaOpenBookTranslator.java | 87 +++++++++++++++++++ .../geysermc/geyser/util/InventoryUtils.java | 9 +- 11 files changed, 218 insertions(+), 34 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaOpenBookTranslator.java 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 135e1057f..c11505ffb 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 @@ -32,8 +32,10 @@ import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket; import org.cloudburstmc.protocol.bedrock.packet.ContainerClosePacket; import org.cloudburstmc.protocol.bedrock.packet.ContainerOpenPacket; import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket; +import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.inventory.Container; import org.geysermc.geyser.inventory.Inventory; +import org.geysermc.geyser.inventory.LecternContainer; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.type.BlockMapping; import org.geysermc.geyser.session.GeyserSession; @@ -151,13 +153,27 @@ public class BlockInventoryHolder extends InventoryHolder { @Override public void closeInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) { - if (((Container) inventory).isUsingRealBlock()) { - // No need to reset a block since we didn't change any blocks - // But send a container close packet because we aren't destroying the original. - ContainerClosePacket packet = new ContainerClosePacket(); - packet.setId((byte) inventory.getBedrockId()); - packet.setServerInitiated(true); - session.sendUpstreamPacket(packet); + if (inventory instanceof Container container) { + if (container.isUsingRealBlock() && !(inventory instanceof LecternContainer)) { + // No need to reset a block since we didn't change any blocks + // But send a container close packet because we aren't destroying the original. + ContainerClosePacket packet = new ContainerClosePacket(); + packet.setId((byte) inventory.getBedrockId()); + packet.setServerInitiated(true); + session.sendUpstreamPacket(packet); + return; + } + } else { + GeyserImpl.getInstance().getLogger().warning("Tried to close a non-container inventory in a block inventory holder! "); + if (GeyserImpl.getInstance().getLogger().isDebug()) { + GeyserImpl.getInstance().getLogger().debug("Current inventory: " + inventory); + GeyserImpl.getInstance().getLogger().debug("Open inventory: " + session.getOpenInventory()); + } + // Try to save ourselves? maybe? + // https://github.com/GeyserMC/Geyser/issues/4141 + // TODO: improve once this issue is pinned down properly + session.setOpenInventory(null); + session.setInventoryTranslator(InventoryTranslator.PLAYER_INVENTORY_TRANSLATOR); return; } diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java b/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java index 6bb786896..c15a5d3b4 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java @@ -53,6 +53,7 @@ public class StoredItemMappings { private final ItemMapping upgradeTemplate; private final ItemMapping wheat; private final ItemMapping writableBook; + private final ItemMapping writtenBook; public StoredItemMappings(Map itemMappings) { this.bamboo = load(itemMappings, Items.BAMBOO); @@ -68,6 +69,7 @@ public class StoredItemMappings { this.upgradeTemplate = load(itemMappings, Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE); this.wheat = load(itemMappings, Items.WHEAT); this.writableBook = load(itemMappings, Items.WRITABLE_BOOK); + this.writtenBook = load(itemMappings, Items.WRITTEN_BOOK); } @NonNull diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index d40b07939..b151f9b09 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -89,6 +89,7 @@ import org.cloudburstmc.protocol.bedrock.data.command.CommandEnumData; import org.cloudburstmc.protocol.bedrock.data.command.CommandPermission; import org.cloudburstmc.protocol.bedrock.data.command.SoftEnumUpdateType; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; +import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.packet.*; import org.cloudburstmc.protocol.common.DefinitionRegistry; import org.cloudburstmc.protocol.common.util.OptionalBoolean; @@ -595,6 +596,12 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { */ private final Queue keepAliveCache = new ConcurrentLinkedQueue<>(); + /** + * Stores the book that is currently being read. Used in {@link org.geysermc.geyser.translator.protocol.java.inventory.JavaOpenBookTranslator} + */ + @Setter + private @Nullable ItemData currentBook = null; + private final GeyserCameraData cameraData; private final GeyserEntityData entityData; diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java index 92cd8a0d4..26721bfcc 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java @@ -36,36 +36,71 @@ import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.erosion.util.LecternUtils; +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.inventory.Container; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.LecternContainer; import org.geysermc.geyser.inventory.PlayerInventory; -import org.geysermc.geyser.inventory.updater.InventoryUpdater; +import org.geysermc.geyser.inventory.updater.ContainerInventoryUpdater; +import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.BlockEntityUtils; import org.geysermc.geyser.util.InventoryUtils; import java.util.Collections; -public class LecternInventoryTranslator extends BaseInventoryTranslator { - private final InventoryUpdater updater; +public class LecternInventoryTranslator extends AbstractBlockInventoryTranslator { + + /** + * Hack: Java opens a lectern first, and then follows it up with a ClientboundContainerSetContentPacket + * to actually send the book's contents. We delay opening the inventory until the book was sent. + */ + private boolean initialized = false; public LecternInventoryTranslator() { - super(1); - this.updater = new InventoryUpdater(); + super(1, "minecraft:lectern[facing=north,has_book=true,powered=true]", org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.LECTERN , ContainerInventoryUpdater.INSTANCE); } @Override public boolean prepareInventory(GeyserSession session, Inventory inventory) { + super.prepareInventory(session, inventory); + if (((Container) inventory).isUsingRealBlock()) { + initialized = false; // We have to wait until we get the book to show to the client + } else { + updateBook(session, inventory, inventory.getItem(0)); // See JavaOpenBookTranslator; placed here manually + initialized = true; + } return true; } @Override public void openInventory(GeyserSession session, Inventory inventory) { + // Hacky, but we're dealing with LECTERNS! It cannot not be hacky. + // "initialized" indicates whether we've received the book from the Java server yet. + // dropping lectern book is the fun workaround when we have to enter the gui to drop the book. + // Since we leave it immediately... don't open it! + if (initialized && !session.isDroppingLecternBook()) { + super.openInventory(session, inventory); + } } @Override public void closeInventory(GeyserSession session, Inventory inventory) { + // Of course, sending a simple ContainerClosePacket, or even breaking the block doesn't work to close a lectern. + // Heck, the latter crashes the client xd + // BDS just sends an empty base lectern tag... that kicks out the client. Fine. Let's do that! + LecternContainer lecternContainer = (LecternContainer) inventory; + Vector3i position = lecternContainer.isUsingRealBlock() ? session.getLastInteractionBlockPosition() : inventory.getHolderPosition(); + var baseLecternTag = LecternUtils.getBaseLecternTag(position.getX(), position.getY(), position.getZ(), 0); + BlockEntityUtils.updateBlockEntity(session, baseLecternTag.build(), position); + + super.closeInventory(session, inventory); // Removes the fake blocks if need be + + // Now: Restore the lectern, if it actually exists + if (lecternContainer.isUsingRealBlock()) { + GeyserImpl.getInstance().getWorldManager().sendLecternData(session, position.getX(), position.getY(), position.getZ()); + } } @Override @@ -82,13 +117,19 @@ public class LecternInventoryTranslator extends BaseInventoryTranslator { public void updateInventory(GeyserSession session, Inventory inventory) { GeyserItemStack itemStack = inventory.getItem(0); if (!itemStack.isEmpty()) { + boolean isDropping = session.isDroppingLecternBook(); updateBook(session, inventory, itemStack); + + if (!initialized && !isDropping) { + initialized = true; + openInventory(session, inventory); + } } } @Override public void updateSlot(GeyserSession session, Inventory inventory, int slot) { - this.updater.updateSlot(this, session, inventory, slot); + super.updateSlot(session, inventory, slot); if (slot == 0) { updateBook(session, inventory, inventory.getItem(0)); } @@ -107,11 +148,14 @@ public class LecternInventoryTranslator extends BaseInventoryTranslator { InventoryUtils.closeInventory(session, inventory.getJavaId(), false); } else if (lecternContainer.getBlockEntityTag() == null) { CompoundTag tag = book.getNbt(); - // Position has to be the last interacted position... right? - Vector3i position = session.getLastInteractionBlockPosition(); + Vector3i position = lecternContainer.isUsingRealBlock() ? session.getLastInteractionBlockPosition() : inventory.getHolderPosition(); + // If shouldExpectLecternHandled returns true, this is already handled for us // shouldRefresh means that we should boot out the client on our side because their lectern GUI isn't updated yet - boolean shouldRefresh = !session.getGeyser().getWorldManager().shouldExpectLecternHandled(session) && !session.getLecternCache().contains(position); + // TODO: yeet after 1.20.60 is minimum supported version + boolean shouldRefresh = !session.getGeyser().getWorldManager().shouldExpectLecternHandled(session) + && !session.getLecternCache().contains(position) + && !GameProtocol.is1_20_60orHigher(session.getUpstream().getProtocolVersion()); NbtMap blockEntityTag; if (tag != null) { @@ -147,10 +191,11 @@ public class LecternInventoryTranslator extends BaseInventoryTranslator { // the block entity tag lecternContainer.setBlockEntityTag(blockEntityTag); lecternContainer.setPosition(position); + + BlockEntityUtils.updateBlockEntity(session, blockEntityTag, position); + session.getLecternCache().add(position); + if (shouldRefresh) { - // Update the lectern because it's not updated client-side - BlockEntityUtils.updateBlockEntity(session, blockEntityTag, position); - session.getLecternCache().add(position); // Close the window - we will reopen it once the client has this data synced ServerboundContainerClosePacket closeWindowPacket = new ServerboundContainerClosePacket(lecternContainer.getJavaId()); session.sendDownstreamGamePacket(closeWindowPacket); @@ -161,6 +206,6 @@ public class LecternInventoryTranslator extends BaseInventoryTranslator { @Override public Inventory createInventory(String name, int windowId, ContainerType containerType, PlayerInventory playerInventory) { - return new LecternContainer(name, windowId, this.size, containerType, playerInventory); + return new LecternContainer(name, windowId, this.size + playerInventory.getSize(), containerType, playerInventory); } } 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 29a78daf3..101035cb5 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 @@ -380,6 +380,8 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator legacySlots = packet.getLegacySlots(); - if (packet.getActions().size() == 1 && legacySlots.size() > 0) { + if (packet.getActions().size() == 1 && !legacySlots.isEmpty()) { InventoryActionData actionData = packet.getActions().get(0); LegacySetItemSlotData slotData = legacySlots.get(0); if (slotData.getContainerId() == 6 && !actionData.getFromItem().isNull()) { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockLecternUpdateTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockLecternUpdateTranslator.java index b2a34d904..2678128ed 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockLecternUpdateTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockLecternUpdateTranslator.java @@ -31,8 +31,10 @@ import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.Ser import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClosePacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundUseItemOnPacket; import org.cloudburstmc.protocol.bedrock.packet.LecternUpdatePacket; +import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.LecternContainer; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.inventory.LecternInventoryTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.util.InventoryUtils; @@ -77,6 +79,15 @@ public class BedrockLecternUpdateTranslator extends PacketTranslator containerOpenPacket.setBlockPosition(entity.getPosition().toInt()); session.sendUpstreamPacket(containerOpenPacket); } + } else { + // Case: Player opens a player inventory, while we think it shouldn't have! + // Close all inventories, reset to player inventory. + InventoryUtils.closeInventory(session, session.getOpenInventory().getJavaId(), false); } break; } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerSetContentTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerSetContentTranslator.java index cfe1c404e..2f8204871 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerSetContentTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerSetContentTranslator.java @@ -27,6 +27,7 @@ package org.geysermc.geyser.translator.protocol.java.inventory; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.inventory.ClientboundContainerSetContentPacket; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.GeyserLogger; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.session.GeyserSession; @@ -48,12 +49,12 @@ public class JavaContainerSetContentTranslator extends PacketTranslator= inventorySize) { - GeyserImpl geyser = session.getGeyser(); - geyser.getLogger().warning("ClientboundContainerSetContentPacket sent to " + session.bedrockUsername() + GeyserLogger logger = session.getGeyser().getLogger(); + logger.warning("ClientboundContainerSetContentPacket sent to " + session.bedrockUsername() + " that exceeds inventory size!"); - if (geyser.getConfig().isDebugMode()) { - geyser.getLogger().debug(packet); - geyser.getLogger().debug(inventory); + if (logger.isDebug()) { + logger.debug(packet); + logger.debug(inventory); } updateInventory(session, inventory, packet.getContainerId()); // 1.18.1 behavior: the previous items will be correctly set, but the state ID and carried item will not diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerSetSlotTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerSetSlotTranslator.java index 734c6945a..4b8eef00d 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerSetSlotTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerSetSlotTranslator.java @@ -34,7 +34,7 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.ShapedRe import org.cloudburstmc.protocol.bedrock.data.inventory.descriptor.ItemDescriptorWithCount; import org.cloudburstmc.protocol.bedrock.packet.CraftingDataPacket; import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket; -import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.GeyserLogger; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.recipe.GeyserShapedRecipe; @@ -65,8 +65,9 @@ public class JavaContainerSetSlotTranslator extends PacketTranslator= inventory.getSize()) { - GeyserImpl geyser = session.getGeyser(); - geyser.getLogger().warning("ClientboundContainerSetSlotPacket sent to " + session.bedrockUsername() + GeyserLogger logger = session.getGeyser().getLogger(); + logger.warning("ClientboundContainerSetSlotPacket sent to " + session.bedrockUsername() + " that exceeds inventory size!"); - if (geyser.getConfig().isDebugMode()) { - geyser.getLogger().debug(packet); - geyser.getLogger().debug(inventory); + if (logger.isDebug()) { + logger.debug(packet.toString()); + logger.debug(inventory.toString()); } // 1.19.0 behavior: the state ID will not be set due to exception return; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaOpenBookTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaOpenBookTranslator.java new file mode 100644 index 000000000..f9cf4ee28 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaOpenBookTranslator.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2019-2024 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.translator.protocol.java.inventory; + +import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; +import com.github.steveice10.mc.protocol.packet.ingame.clientbound.inventory.ClientboundOpenBookPacket; +import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClosePacket; +import org.geysermc.geyser.inventory.GeyserItemStack; +import org.geysermc.geyser.inventory.Inventory; +import org.geysermc.geyser.item.Items; +import org.geysermc.geyser.network.GameProtocol; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.inventory.InventoryTranslator; +import org.geysermc.geyser.translator.protocol.PacketTranslator; +import org.geysermc.geyser.translator.protocol.Translator; +import org.geysermc.geyser.util.InventoryUtils; + +import java.util.Objects; + +@Translator(packet = ClientboundOpenBookPacket.class) +public class JavaOpenBookTranslator extends PacketTranslator { + + /** + * Unlike other fake inventories that rely on placing blocks in the world; + * the virtual lectern workaround for books isn't triggered the same way. + * Specifically, we don't get a window id - hence, we just use our own! + */ + private final static int FAKE_LECTERN_WINDOW_ID = -69; + + @Override + public void translate(GeyserSession session, ClientboundOpenBookPacket packet) { + GeyserItemStack stack = session.getPlayerInventory().getItemInHand(); + + // Don't spawn a fake lectern for books already opened "normally" by the client. + if (stack.getItemData(session).equals(session.getCurrentBook())) { + session.setCurrentBook(null); + return; + } + + // Only post 1.20.60 is it possible to tell the client to open a lectern. + if (!GameProtocol.is1_20_60orHigher(session.getUpstream().getProtocolVersion())) { + return; + } + + if (stack.asItem().equals(Items.WRITTEN_BOOK)) { + Inventory openInventory = session.getOpenInventory(); + if (openInventory != null) { + InventoryUtils.closeInventory(session, openInventory.getJavaId(), true); + + ServerboundContainerClosePacket closeWindowPacket = new ServerboundContainerClosePacket(openInventory.getJavaId()); + session.sendDownstreamGamePacket(closeWindowPacket); + } + + InventoryTranslator translator = InventoryTranslator.inventoryTranslator(ContainerType.LECTERN); + session.setInventoryTranslator(translator); + + // Should never be null + Objects.requireNonNull(translator, "lectern translator must exist"); + Inventory inventory = translator.createInventory("", FAKE_LECTERN_WINDOW_ID, ContainerType.LECTERN , session.getPlayerInventory()); + inventory.setItem(0, stack, session); + InventoryUtils.openInventory(session, inventory); + } + } +} diff --git a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java index 4d91f853c..30b2907cc 100644 --- a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java @@ -45,6 +45,7 @@ import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.inventory.Container; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.Inventory; +import org.geysermc.geyser.inventory.LecternContainer; import org.geysermc.geyser.inventory.PlayerInventory; import org.geysermc.geyser.inventory.click.Click; import org.geysermc.geyser.inventory.recipe.GeyserRecipe; @@ -123,7 +124,9 @@ public class InventoryUtils { if (inventory != null) { InventoryTranslator translator = session.getInventoryTranslator(); translator.closeInventory(session, inventory); - if (confirm && inventory.isDisplayed() && !inventory.isPending() && !(translator instanceof LecternInventoryTranslator)) { + if (confirm && inventory.isDisplayed() && !inventory.isPending() + && !(translator instanceof LecternInventoryTranslator) // TODO: double-check + ) { session.setClosingInventory(true); } } @@ -133,6 +136,10 @@ public class InventoryUtils { public static @Nullable Inventory getInventory(GeyserSession session, int javaId) { if (javaId == 0) { + // ugly hack: lecterns aren't their own inventory on Java, and can hence be closed with e.g. an id of 0 + if (session.getOpenInventory() instanceof LecternContainer) { + return session.getOpenInventory(); + } return session.getPlayerInventory(); } else { Inventory openInventory = session.getOpenInventory(); From 123990a79502cf6734e6858c1362c2431f050ece Mon Sep 17 00:00:00 2001 From: chris Date: Sat, 2 Mar 2024 20:03:18 +0100 Subject: [PATCH 193/344] Update ViaVersion api usage --- .../org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java index 1bc1718d7..1f14a2f65 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java @@ -433,7 +433,7 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { return false; } for (int i = protocolList.size() - 1; i >= 0; i--) { - MappingData mappingData = protocolList.get(i).getProtocol().getMappingData(); + MappingData mappingData = protocolList.get(i).protocol().getMappingData(); if (mappingData != null) { return true; } From 79154f3d0c37174fbba8a305e84b1176e1f239b4 Mon Sep 17 00:00:00 2001 From: chris Date: Mon, 4 Mar 2024 00:39:57 +0100 Subject: [PATCH 194/344] Fix: Lecterns not opening when there is no lectern cache (#4476) ... the LecternCache doesn't always exist. Oops. --- .../main/java/org/geysermc/geyser/session/GeyserSession.java | 2 +- .../translator/inventory/LecternInventoryTranslator.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index b151f9b09..8bdb41979 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -285,7 +285,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { * See {@link WorldManager#sendLecternData(GeyserSession, int, int, int)} * for more information. */ - private final Set lecternCache; + private final @Nullable Set lecternCache; /** * A list of all players that have a player head on with a custom texture. diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java index 26721bfcc..7a1ec7573 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java @@ -193,9 +193,11 @@ public class LecternInventoryTranslator extends AbstractBlockInventoryTranslator lecternContainer.setPosition(position); BlockEntityUtils.updateBlockEntity(session, blockEntityTag, position); - session.getLecternCache().add(position); if (shouldRefresh) { + // the lectern cache doesn't always exist; only when we must refresh + session.getLecternCache().add(position); + // Close the window - we will reopen it once the client has this data synced ServerboundContainerClosePacket closeWindowPacket = new ServerboundContainerClosePacket(lecternContainer.getJavaId()); session.sendDownstreamGamePacket(closeWindowPacket); From 621dc6f89a0b355b16313df753abb9464d88105c Mon Sep 17 00:00:00 2001 From: Shanwer Date: Tue, 5 Mar 2024 06:37:45 +0800 Subject: [PATCH 195/344] Update actions to node20 (#4456) --- .github/workflows/build.yml | 30 +++++++++++++++--------------- .github/workflows/pullrequest.yml | 22 +++++++++++----------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b316cd037..385797af7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,7 +6,7 @@ on: paths-ignore: - '.github/ISSUE_TEMPLATE/*.yml' - '.github/actions/pullrequest.yml' - - '.idea/copyright/*.xml' + - '.idea/copyright/*.xml' - '.gitignore' - 'CONTRIBUTING.md' - 'LICENSE' @@ -20,72 +20,72 @@ jobs: steps: - name: Checkout repository and submodules # See https://github.com/actions/checkout/commits - uses: actions/checkout@72f2cec99f417b1a1c5e2e88945068983b7965f9 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: submodules: recursive - name: Validate Gradle Wrapper # See https://github.com/gradle/wrapper-validation-action/commits - uses: gradle/wrapper-validation-action@56b90f209b02bf6d1deae490e9ef18b21a389cd4 + uses: gradle/wrapper-validation-action@699bb18358f12c5b78b37bb0111d3a0e2276e0e2 # v2.1.1 # See https://github.com/actions/setup-java/commits - - uses: actions/setup-java@4075bfc1b51bf22876335ae1cd589602d60d8758 + - uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4.0.0 with: java-version: 17 distribution: temurin - name: Build # See https://github.com/gradle/gradle-build-action/commits - uses: gradle/gradle-build-action@3bfe3a46584a206fb8361cdedd0647b0c4204232 + uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 from https://github.com/gradle/actions/commits with: arguments: build gradle-home-cache-cleanup: true - name: Archive artifacts (Geyser Fabric) # See https://github.com/actions/upload-artifact/commits - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 if: success() with: name: Geyser Fabric path: bootstrap/mod/fabric/build/libs/Geyser-Fabric.jar if-no-files-found: error - name: Archive artifacts (Geyser NeoForge) - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 if: success() with: name: Geyser NeoForge path: bootstrap/mod/neoforge/build/libs/Geyser-NeoForge.jar if-no-files-found: error - name: Archive artifacts (Geyser Standalone) - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 if: success() with: name: Geyser Standalone path: bootstrap/standalone/build/libs/Geyser-Standalone.jar if-no-files-found: error - name: Archive artifacts (Geyser Spigot) - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 if: success() with: name: Geyser Spigot path: bootstrap/spigot/build/libs/Geyser-Spigot.jar if-no-files-found: error - name: Archive artifacts (Geyser BungeeCord) - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 if: success() with: name: Geyser BungeeCord path: bootstrap/bungeecord/build/libs/Geyser-BungeeCord.jar if-no-files-found: error - name: Archive artifacts (Geyser Velocity) - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 if: success() with: name: Geyser Velocity path: bootstrap/velocity/build/libs/Geyser-Velocity.jar if-no-files-found: error - name: Archive artifacts (Geyser ViaProxy) - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 if: success() with: name: Geyser ViaProxy @@ -94,7 +94,7 @@ jobs: - name: Publish to Maven Repository if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} - uses: gradle/gradle-build-action@3bfe3a46584a206fb8361cdedd0647b0c4204232 + uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 env: ORG_GRADLE_PROJECT_geysermcUsername: ${{ vars.DEPLOY_USER }} ORG_GRADLE_PROJECT_geysermcPassword: ${{ secrets.DEPLOY_PASS }} @@ -127,7 +127,7 @@ jobs: rsync -P -e "ssh -o StrictHostKeyChecking=no -i id_ecdsa" metadata.json $DOWNLOADS_USERNAME@$DOWNLOADS_SERVER_IP:~/uploads/$project/$GITHUB_RUN_NUMBER/ - name: Publish to Modrinth (Fabric) - uses: gradle/gradle-build-action@3bfe3a46584a206fb8361cdedd0647b0c4204232 + uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} env: MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }} @@ -136,7 +136,7 @@ jobs: gradle-home-cache-cleanup: true - name: Publish to Modrinth (NeoForge) - uses: gradle/gradle-build-action@3bfe3a46584a206fb8361cdedd0647b0c4204232 + uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} env: MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }} diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 851c087c1..309905b25 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -9,7 +9,7 @@ jobs: steps: - name: Set up JDK 17 # See https://github.com/actions/setup-java/commits - uses: actions/setup-java@4075bfc1b51bf22876335ae1cd589602d60d8758 + uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4.0.0 with: java-version: 17 distribution: temurin @@ -35,67 +35,67 @@ jobs: - name: Checkout repository and submodules # See https://github.com/actions/checkout/commits - uses: actions/checkout@72f2cec99f417b1a1c5e2e88945068983b7965f9 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: submodules: recursive path: geyser - name: Validate Gradle Wrapper # See https://github.com/gradle/wrapper-validation-action/commits - uses: gradle/wrapper-validation-action@56b90f209b02bf6d1deae490e9ef18b21a389cd4 + uses: gradle/wrapper-validation-action@699bb18358f12c5b78b37bb0111d3a0e2276e0e2 # v2.1.1 - name: Build Geyser # See https://github.com/gradle/gradle-build-action/commits - uses: gradle/gradle-build-action@3bfe3a46584a206fb8361cdedd0647b0c4204232 + uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 from https://github.com/gradle/actions/commits with: arguments: build build-root-directory: geyser - name: Archive artifacts (Geyser Fabric) # See https://github.com/actions/upload-artifact/commits - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 if: success() with: name: Geyser Fabric path: geyser/bootstrap/mod/fabric/build/libs/Geyser-Fabric.jar if-no-files-found: error - name: Archive artifacts (Geyser NeoForge) - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 if: success() with: name: Geyser NeoForge path: geyser/bootstrap/mod/neoforge/build/libs/Geyser-NeoForge.jar if-no-files-found: error - name: Archive artifacts (Geyser Standalone) - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 if: success() with: name: Geyser Standalone path: geyser/bootstrap/standalone/build/libs/Geyser-Standalone.jar if-no-files-found: error - name: Archive artifacts (Geyser Spigot) - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 if: success() with: name: Geyser Spigot path: geyser/bootstrap/spigot/build/libs/Geyser-Spigot.jar if-no-files-found: error - name: Archive artifacts (Geyser BungeeCord) - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 if: success() with: name: Geyser BungeeCord path: geyser/bootstrap/bungeecord/build/libs/Geyser-BungeeCord.jar if-no-files-found: error - name: Archive artifacts (Geyser Velocity) - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 if: success() with: name: Geyser Velocity path: geyser/bootstrap/velocity/build/libs/Geyser-Velocity.jar if-no-files-found: error - name: Archive artifacts (Geyser ViaProxy) - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 if: success() with: name: Geyser ViaProxy From 1af24e5547e613bf18c58063ca3b89f2374dcc04 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Fri, 8 Mar 2024 21:24:15 +0000 Subject: [PATCH 196/344] Add new village map icons (#4480) --- .../java/org/geysermc/geyser/level/BedrockMapIcon.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/level/BedrockMapIcon.java b/core/src/main/java/org/geysermc/geyser/level/BedrockMapIcon.java index eac8aca09..120e40f17 100644 --- a/core/src/main/java/org/geysermc/geyser/level/BedrockMapIcon.java +++ b/core/src/main/java/org/geysermc/geyser/level/BedrockMapIcon.java @@ -56,7 +56,14 @@ public enum BedrockMapIcon { ICON_GREEN_BANNER(MapIconType.GREEN_BANNER, 13, 94, 124, 22), ICON_RED_BANNER(MapIconType.RED_BANNER, 13, 176, 46, 38), ICON_BLACK_BANNER(MapIconType.BLACK_BANNER, 13, 29, 29, 33), - ICON_TREASURE_MARKER(MapIconType.TREASURE_MARKER, 4); + ICON_TREASURE_MARKER(MapIconType.TREASURE_MARKER, 4), + ICON_DESERT_VILLAGE(MapIconType.DESERT_VILLAGE, 17), + ICON_PLAINS_VILLAGE(MapIconType.PLAINS_VILLAGE, 18), + ICON_SAVANNA_VILLAGE(MapIconType.SAVANNA_VILLAGE, 19), + ICON_SNOWY_VILLAGE(MapIconType.SNOWY_VILLAGE, 20), + ICON_TAIGA_VILLAGE(MapIconType.TAIGA_VILLAGE, 21), + ICON_JUNGLE_TEMPLE(MapIconType.JUNGLE_TEMPLE, 22), + ICON_SWAMP_HUT(MapIconType.SWAMP_HUT, 23); private static final BedrockMapIcon[] VALUES = values(); From 32f66371d97620e7ea4bda3a5a0ca7a5c75b510c Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 8 Mar 2024 22:30:17 +0100 Subject: [PATCH 197/344] Should resolve https://github.com/GeyserMC/Geyser/issues/4121 (#4481) --- .../inventory/PlayerInventoryTranslator.java | 12 ++++++++++++ .../entity/player/BedrockInteractTranslator.java | 11 +---------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java index 613121dfd..1447f2b5b 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java @@ -44,6 +44,8 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.SwapAction; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.TransferItemStackRequestAction; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.response.ItemStackResponse; +import org.cloudburstmc.protocol.bedrock.packet.ContainerClosePacket; +import org.cloudburstmc.protocol.bedrock.packet.ContainerOpenPacket; import org.cloudburstmc.protocol.bedrock.packet.InventoryContentPacket; import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket; import org.geysermc.geyser.inventory.*; @@ -534,10 +536,20 @@ public class PlayerInventoryTranslator extends InventoryTranslator { @Override public void openInventory(GeyserSession session, Inventory inventory) { + ContainerOpenPacket containerOpenPacket = new ContainerOpenPacket(); + containerOpenPacket.setId((byte) 0); + containerOpenPacket.setType(org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.INVENTORY); + containerOpenPacket.setUniqueEntityId(-1); + containerOpenPacket.setBlockPosition(session.getPlayerEntity().getPosition().toInt()); + session.sendUpstreamPacket(containerOpenPacket); } @Override public void closeInventory(GeyserSession session, Inventory inventory) { + ContainerClosePacket packet = new ContainerClosePacket(); + packet.setServerInitiated(true); + packet.setId((byte) ContainerId.INVENTORY); + session.sendUpstreamPacket(packet); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockInteractTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockInteractTranslator.java index 4b40bb38e..80141f849 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockInteractTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockInteractTranslator.java @@ -33,8 +33,6 @@ import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.Server import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundPlayerCommandPacket; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityLinkData; -import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; -import org.cloudburstmc.protocol.bedrock.packet.ContainerOpenPacket; import org.cloudburstmc.protocol.bedrock.packet.InteractPacket; import org.cloudburstmc.protocol.bedrock.packet.SetEntityLinkPacket; import org.geysermc.geyser.entity.type.Entity; @@ -126,14 +124,7 @@ public class BedrockInteractTranslator extends PacketTranslator ServerboundPlayerCommandPacket openVehicleWindowPacket = new ServerboundPlayerCommandPacket(session.getPlayerEntity().getEntityId(), PlayerState.OPEN_VEHICLE_INVENTORY); session.sendDownstreamGamePacket(openVehicleWindowPacket); } else { - session.setOpenInventory(session.getPlayerInventory()); - - ContainerOpenPacket containerOpenPacket = new ContainerOpenPacket(); - containerOpenPacket.setId((byte) 0); - containerOpenPacket.setType(ContainerType.INVENTORY); - containerOpenPacket.setUniqueEntityId(-1); - containerOpenPacket.setBlockPosition(entity.getPosition().toInt()); - session.sendUpstreamPacket(containerOpenPacket); + InventoryUtils.openInventory(session, session.getPlayerInventory()); } } else { // Case: Player opens a player inventory, while we think it shouldn't have! From f1e125a360356070f12dc33f5c4e3b1cc7660c65 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Fri, 8 Mar 2024 21:32:28 +0000 Subject: [PATCH 198/344] Add merge group trigger to pullrequest workflow (#4482) --- .github/workflows/pullrequest.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 309905b25..93be4711e 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -2,6 +2,7 @@ name: Build Pull Request on: pull_request: + merge_group: jobs: build: From 92ce0fc6c7bbb061f7428c88a695e9f8e06d0788 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Sat, 9 Mar 2024 01:24:16 +0000 Subject: [PATCH 199/344] Ignore merge queue branches from build workflow (#4483) --- .github/workflows/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 385797af7..1d70d9948 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,6 +3,8 @@ name: Build on: workflow_dispatch: push: + branches-ignore: + - 'gh-readonly-queue/**' paths-ignore: - '.github/ISSUE_TEMPLATE/*.yml' - '.github/actions/pullrequest.yml' From 527eab0b586c8a8904beb3ed989036e7e08f9f9d Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Fri, 8 Mar 2024 19:51:32 -0800 Subject: [PATCH 200/344] Cap render distance at 96 (#3530) Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Co-authored-by: onebeastchris --- .../main/java/org/geysermc/geyser/session/GeyserSession.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 8bdb41979..73cbf32c8 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -1464,6 +1464,11 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { } public void setServerRenderDistance(int renderDistance) { + // +1 is for Fabric and Spigot + // Without the client misses loading some chunks per https://github.com/GeyserMC/Geyser/issues/3490 + // Fog still appears essentially normally + // Ensure render distance is not above 96 as sending a larger value at any point crashes mobile clients and 96 is the max of any bedrock platform + renderDistance = Math.min(renderDistance, 96); this.serverRenderDistance = renderDistance; ChunkRadiusUpdatedPacket chunkRadiusUpdatedPacket = new ChunkRadiusUpdatedPacket(); From 0ad7c4325d43b0865c0ebea5cd0f83aba93bf40d Mon Sep 17 00:00:00 2001 From: chris Date: Sun, 10 Mar 2024 23:38:38 +0100 Subject: [PATCH 201/344] Fix: Workaround for recipes involving custom items to show up in the recipe book (#4484) * Allow adding custom items to the creative inventory in order for recipes outputting said custom items to work * yeet includeInCreativeInventory as it would break existing nonvanilla extensions - and is pretty pointless anyways * rename mappings to `creative_group` and `creative_category` * delete outdated comment --- .../api/block/custom/CustomBlockData.java | 8 +-- .../api/item/custom/CustomItemData.java | 19 ++++++ .../item/custom/NonVanillaCustomItemData.java | 25 ++------ .../geyser/item/GeyserCustomItemData.java | 35 ++++++++++- .../item/GeyserNonVanillaCustomItemData.java | 62 +++++++------------ .../mappings/versions/MappingsReader_v1.java | 8 +++ .../CustomItemRegistryPopulator.java | 27 +++++--- .../populator/ItemRegistryPopulator.java | 12 +++- .../geyser/session/GeyserSession.java | 7 +-- 9 files changed, 124 insertions(+), 79 deletions(-) diff --git a/api/src/main/java/org/geysermc/geyser/api/block/custom/CustomBlockData.java b/api/src/main/java/org/geysermc/geyser/api/block/custom/CustomBlockData.java index 9f142faab..2605cda21 100644 --- a/api/src/main/java/org/geysermc/geyser/api/block/custom/CustomBlockData.java +++ b/api/src/main/java/org/geysermc/geyser/api/block/custom/CustomBlockData.java @@ -61,16 +61,16 @@ public interface CustomBlockData { boolean includedInCreativeInventory(); /** - * Gets the item's creative category, or tab id. + * Gets the block's creative category, or tab id. * - * @return the item's creative category + * @return the block's creative category */ @Nullable CreativeCategory creativeCategory(); /** - * Gets the item's creative group. + * Gets the block's creative group. * - * @return the item's creative group + * @return the block's creative group */ @Nullable String creativeGroup(); diff --git a/api/src/main/java/org/geysermc/geyser/api/item/custom/CustomItemData.java b/api/src/main/java/org/geysermc/geyser/api/item/custom/CustomItemData.java index 404679e60..3b871cd74 100644 --- a/api/src/main/java/org/geysermc/geyser/api/item/custom/CustomItemData.java +++ b/api/src/main/java/org/geysermc/geyser/api/item/custom/CustomItemData.java @@ -29,6 +29,7 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.api.GeyserApi; +import java.util.OptionalInt; import java.util.Set; /** @@ -77,6 +78,20 @@ public interface CustomItemData { */ boolean displayHandheld(); + /** + * Gets the item's creative category, or tab id. + * + * @return the item's creative category + */ + @NonNull OptionalInt creativeCategory(); + + /** + * Gets the item's creative group. + * + * @return the item's creative group + */ + @Nullable String creativeGroup(); + /** * Gets the item's texture size. This is to resize the item if the texture is not 16x16. * @@ -119,6 +134,10 @@ public interface CustomItemData { Builder displayHandheld(boolean displayHandheld); + Builder creativeCategory(int creativeCategory); + + Builder creativeGroup(@Nullable String creativeGroup); + Builder textureSize(int textureSize); Builder renderOffsets(@Nullable CustomRenderOffsets renderOffsets); diff --git a/api/src/main/java/org/geysermc/geyser/api/item/custom/NonVanillaCustomItemData.java b/api/src/main/java/org/geysermc/geyser/api/item/custom/NonVanillaCustomItemData.java index 616a5bba6..37a4247d1 100644 --- a/api/src/main/java/org/geysermc/geyser/api/item/custom/NonVanillaCustomItemData.java +++ b/api/src/main/java/org/geysermc/geyser/api/item/custom/NonVanillaCustomItemData.java @@ -30,7 +30,6 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.api.GeyserApi; -import java.util.OptionalInt; import java.util.Set; /** @@ -107,20 +106,6 @@ public interface NonVanillaCustomItemData extends CustomItemData { */ @Nullable Set repairMaterials(); - /** - * Gets the item's creative category, or tab id. - * - * @return the item's creative category - */ - @NonNull OptionalInt creativeCategory(); - - /** - * Gets the item's creative group. - * - * @return the item's creative group - */ - @Nullable String creativeGroup(); - /** * Gets if the item is a hat. This is used to determine if the item should be rendered on the player's head, and * normally allow the player to equip it. This is not meant for armor. @@ -196,10 +181,6 @@ public interface NonVanillaCustomItemData extends CustomItemData { Builder repairMaterials(@Nullable Set repairMaterials); - Builder creativeCategory(int creativeCategory); - - Builder creativeGroup(@Nullable String creativeGroup); - Builder hat(boolean isHat); Builder foil(boolean isFoil); @@ -218,6 +199,12 @@ public interface NonVanillaCustomItemData extends CustomItemData { return displayHandheld(isTool); } + @Override + Builder creativeCategory(int creativeCategory); + + @Override + Builder creativeGroup(@Nullable String creativeGroup); + @Override Builder customItemOptions(@NonNull CustomItemOptions customItemOptions); diff --git a/core/src/main/java/org/geysermc/geyser/item/GeyserCustomItemData.java b/core/src/main/java/org/geysermc/geyser/item/GeyserCustomItemData.java index 2906a9be3..a2054f78a 100644 --- a/core/src/main/java/org/geysermc/geyser/item/GeyserCustomItemData.java +++ b/core/src/main/java/org/geysermc/geyser/item/GeyserCustomItemData.java @@ -35,6 +35,7 @@ import org.geysermc.geyser.api.item.custom.CustomRenderOffsets; import java.util.HashSet; import java.util.Objects; +import java.util.OptionalInt; import java.util.Set; @EqualsAndHashCode @@ -46,6 +47,8 @@ public class GeyserCustomItemData implements CustomItemData { private final String icon; private final boolean allowOffhand; private final boolean displayHandheld; + private final OptionalInt creativeCategory; + private final String creativeGroup; private final int textureSize; private final CustomRenderOffsets renderOffsets; private final Set tags; @@ -56,6 +59,8 @@ public class GeyserCustomItemData implements CustomItemData { String icon, boolean allowOffhand, boolean displayHandheld, + OptionalInt creativeCategory, + String creativeGroup, int textureSize, CustomRenderOffsets renderOffsets, Set tags) { @@ -65,6 +70,8 @@ public class GeyserCustomItemData implements CustomItemData { this.icon = icon; this.allowOffhand = allowOffhand; this.displayHandheld = displayHandheld; + this.creativeCategory = creativeCategory; + this.creativeGroup = creativeGroup; this.textureSize = textureSize; this.renderOffsets = renderOffsets; this.tags = tags; @@ -100,6 +107,16 @@ public class GeyserCustomItemData implements CustomItemData { return this.displayHandheld; } + @Override + public @NonNull OptionalInt creativeCategory() { + return this.creativeCategory; + } + + @Override + public @Nullable String creativeGroup() { + return this.creativeGroup; + } + @Override public int textureSize() { return textureSize; @@ -118,11 +135,12 @@ public class GeyserCustomItemData implements CustomItemData { public static class Builder implements CustomItemData.Builder { protected String name = null; protected CustomItemOptions customItemOptions = null; - protected String displayName = null; protected String icon = null; protected boolean allowOffhand = true; // Bedrock doesn't give items offhand allowance unless they serve gameplay purpose, but we want to be friendly with Java protected boolean displayHandheld = false; + protected OptionalInt creativeCategory = OptionalInt.empty(); + protected String creativeGroup = null; protected int textureSize = 16; protected CustomRenderOffsets renderOffsets = null; protected Set tags = new HashSet<>(); @@ -163,6 +181,18 @@ public class GeyserCustomItemData implements CustomItemData { return this; } + @Override + public Builder creativeCategory(int creativeCategory) { + this.creativeCategory = OptionalInt.of(creativeCategory); + return this; + } + + @Override + public Builder creativeGroup(@Nullable String creativeGroup) { + this.creativeGroup = creativeGroup; + return this; + } + @Override public Builder textureSize(int textureSize) { this.textureSize = textureSize; @@ -193,7 +223,8 @@ public class GeyserCustomItemData implements CustomItemData { if (this.icon == null) { this.icon = this.name; } - return new GeyserCustomItemData(this.name, this.customItemOptions, this.displayName, this.icon, this.allowOffhand, this.displayHandheld, this.textureSize, this.renderOffsets, this.tags); + return new GeyserCustomItemData(this.name, this.customItemOptions, this.displayName, this.icon, this.allowOffhand, + this.displayHandheld, this.creativeCategory, this.creativeGroup, this.textureSize, this.renderOffsets, this.tags); } } } diff --git a/core/src/main/java/org/geysermc/geyser/item/GeyserNonVanillaCustomItemData.java b/core/src/main/java/org/geysermc/geyser/item/GeyserNonVanillaCustomItemData.java index bb4e60589..14f8c3a39 100644 --- a/core/src/main/java/org/geysermc/geyser/item/GeyserNonVanillaCustomItemData.java +++ b/core/src/main/java/org/geysermc/geyser/item/GeyserNonVanillaCustomItemData.java @@ -33,10 +33,8 @@ import org.geysermc.geyser.api.item.custom.CustomItemOptions; import org.geysermc.geyser.api.item.custom.CustomRenderOffsets; import org.geysermc.geyser.api.item.custom.NonVanillaCustomItemData; -import java.util.OptionalInt; import java.util.Set; -@SuppressWarnings("OptionalUsedAsFieldOrParameterType") @EqualsAndHashCode(callSuper = true) @ToString public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData implements NonVanillaCustomItemData { @@ -50,8 +48,6 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i private final int protectionValue; private final String translationString; private final Set repairMaterials; - private final OptionalInt creativeCategory; - private final String creativeGroup; private final boolean isHat; private final boolean isFoil; private final boolean isTool; @@ -61,7 +57,8 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i public GeyserNonVanillaCustomItemData(Builder builder) { super(builder.name, builder.customItemOptions, builder.displayName, builder.icon, builder.allowOffhand, - builder.displayHandheld, builder.textureSize, builder.renderOffsets, builder.tags); + builder.displayHandheld, builder.creativeCategory, builder.creativeGroup, + builder.textureSize, builder.renderOffsets, builder.tags); this.identifier = builder.identifier; this.javaId = builder.javaId; @@ -73,8 +70,6 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i this.protectionValue = builder.protectionValue; this.translationString = builder.translationString; this.repairMaterials = builder.repairMaterials; - this.creativeCategory = builder.creativeCategory; - this.creativeGroup = builder.creativeGroup; this.isHat = builder.hat; this.isFoil = builder.foil; this.isTool = builder.tool; @@ -133,16 +128,6 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i return repairMaterials; } - @Override - public @NonNull OptionalInt creativeCategory() { - return creativeCategory; - } - - @Override - public String creativeGroup() { - return creativeGroup; - } - @Override public boolean isHat() { return isHat; @@ -186,9 +171,6 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i private Set repairMaterials; - private OptionalInt creativeCategory = OptionalInt.empty(); - private String creativeGroup = null; - private boolean hat = false; private boolean foil = false; private boolean tool = false; @@ -243,103 +225,101 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i } @Override - public NonVanillaCustomItemData.Builder identifier(@NonNull String identifier) { + public Builder identifier(@NonNull String identifier) { this.identifier = identifier; return this; } @Override - public NonVanillaCustomItemData.Builder javaId(int javaId) { + public Builder javaId(int javaId) { this.javaId = javaId; return this; } @Override - public NonVanillaCustomItemData.Builder stackSize(int stackSize) { + public Builder stackSize(int stackSize) { this.stackSize = stackSize; return this; } @Override - public NonVanillaCustomItemData.Builder maxDamage(int maxDamage) { + public Builder maxDamage(int maxDamage) { this.maxDamage = maxDamage; return this; } @Override - public NonVanillaCustomItemData.Builder toolType(@Nullable String toolType) { + public Builder toolType(@Nullable String toolType) { this.toolType = toolType; return this; } @Override - public NonVanillaCustomItemData.Builder toolTier(@Nullable String toolTier) { + public Builder toolTier(@Nullable String toolTier) { this.toolTier = toolTier; return this; } @Override - public NonVanillaCustomItemData.Builder armorType(@Nullable String armorType) { + public Builder armorType(@Nullable String armorType) { this.armorType = armorType; return this; } @Override - public NonVanillaCustomItemData.Builder protectionValue(int protectionValue) { + public Builder protectionValue(int protectionValue) { this.protectionValue = protectionValue; return this; } @Override - public NonVanillaCustomItemData.Builder translationString(@Nullable String translationString) { + public Builder translationString(@Nullable String translationString) { this.translationString = translationString; return this; } @Override - public NonVanillaCustomItemData.Builder repairMaterials(@Nullable Set repairMaterials) { + public Builder repairMaterials(@Nullable Set repairMaterials) { this.repairMaterials = repairMaterials; return this; } @Override - public NonVanillaCustomItemData.Builder creativeCategory(int creativeCategory) { - this.creativeCategory = OptionalInt.of(creativeCategory); - return this; + public Builder creativeCategory(int creativeCategory) { + return (Builder) super.creativeCategory(creativeCategory); } @Override - public NonVanillaCustomItemData.Builder creativeGroup(@Nullable String creativeGroup) { - this.creativeGroup = creativeGroup; - return this; + public Builder creativeGroup(@Nullable String creativeGroup) { + return (Builder) super.creativeGroup(creativeGroup); } @Override - public NonVanillaCustomItemData.Builder hat(boolean isHat) { + public Builder hat(boolean isHat) { this.hat = isHat; return this; } @Override - public NonVanillaCustomItemData.Builder foil(boolean isFoil) { + public Builder foil(boolean isFoil) { this.foil = isFoil; return this; } @Override - public NonVanillaCustomItemData.Builder edible(boolean isEdible) { + public Builder edible(boolean isEdible) { this.edible = isEdible; return this; } @Override - public NonVanillaCustomItemData.Builder canAlwaysEat(boolean canAlwaysEat) { + public Builder canAlwaysEat(boolean canAlwaysEat) { this.canAlwaysEat = canAlwaysEat; return this; } @Override - public NonVanillaCustomItemData.Builder chargeable(boolean isChargeable) { + public Builder chargeable(boolean isChargeable) { this.chargeable = isChargeable; return this; } diff --git a/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java b/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java index ce4a8f30e..e8901a550 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java +++ b/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java @@ -193,6 +193,14 @@ public class MappingsReader_v1 extends MappingsReader { customItemData.icon(node.get("icon").asText()); } + if (node.has("creative_category")) { + customItemData.creativeCategory(node.get("creative_category").asInt()); + } + + if (node.has("creative_group")) { + customItemData.creativeGroup(node.get("creative_group").asText()); + } + if (node.has("allow_offhand")) { customItemData.allowOffhand(node.get("allow_offhand").asBoolean()); } 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 c1f1bb10c..2e00bd4ad 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 @@ -246,13 +246,6 @@ public class CustomItemRegistryPopulator { computeRenderOffsets(isHat, customItemData, componentBuilder); - if (creativeGroup != null) { - itemProperties.putString("creative_group", creativeGroup); - } - if (creativeCategory.isPresent()) { - itemProperties.putInt("creative_category", creativeCategory.getAsInt()); - } - if (customItemData.isFoil()) { itemProperties.putBoolean("foil", true); } @@ -278,6 +271,14 @@ public class CustomItemRegistryPopulator { } itemProperties.putCompound("minecraft:icon", iconMap); + if (customItemData.creativeCategory().isPresent()) { + itemProperties.putInt("creative_category", customItemData.creativeCategory().getAsInt()); + + if (customItemData.creativeGroup() != null) { + itemProperties.putString("creative_group", customItemData.creativeGroup()); + } + } + componentBuilder.putCompound("minecraft:display_name", NbtMap.builder().putString("value", customItemData.displayName()).build()); // Add a Geyser tag to the item, allowing Molang queries @@ -370,21 +371,33 @@ public class CustomItemRegistryPopulator { componentBuilder.putString("minecraft:render_offsets", "boots"); componentBuilder.putCompound("minecraft:wearable", WearableSlot.FEET.getSlotNbt()); componentBuilder.putCompound("minecraft:armor", NbtMap.builder().putInt("protection", protectionValue).build()); + + itemProperties.putString("enchantable_slot", "armor_feet"); + itemProperties.putInt("enchantable_value", 15); } case "chestplate" -> { componentBuilder.putString("minecraft:render_offsets", "chestplates"); componentBuilder.putCompound("minecraft:wearable", WearableSlot.CHEST.getSlotNbt()); componentBuilder.putCompound("minecraft:armor", NbtMap.builder().putInt("protection", protectionValue).build()); + + itemProperties.putString("enchantable_slot", "armor_torso"); + itemProperties.putInt("enchantable_value", 15); } case "leggings" -> { componentBuilder.putString("minecraft:render_offsets", "leggings"); componentBuilder.putCompound("minecraft:wearable", WearableSlot.LEGS.getSlotNbt()); componentBuilder.putCompound("minecraft:armor", NbtMap.builder().putInt("protection", protectionValue).build()); + + itemProperties.putString("enchantable_slot", "armor_legs"); + itemProperties.putInt("enchantable_value", 15); } case "helmet" -> { componentBuilder.putString("minecraft:render_offsets", "helmets"); componentBuilder.putCompound("minecraft:wearable", WearableSlot.HEAD.getSlotNbt()); componentBuilder.putCompound("minecraft:armor", NbtMap.builder().putInt("protection", protectionValue).build()); + + itemProperties.putString("enchantable_slot", "armor_head"); + itemProperties.putInt("enchantable_value", 15); } } } 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 539452169..c1593447d 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 @@ -425,6 +425,16 @@ public class ItemRegistryPopulator { GeyserCustomMappingData customMapping = CustomItemRegistryPopulator.registerCustomItem( customItemName, javaItem, mappingItem, customItem, customProtocolId, palette.protocolVersion ); + + if (customItem.creativeCategory().isPresent()) { + creativeItems.add(ItemData.builder() + .netId(creativeNetId.incrementAndGet()) + .definition(customMapping.itemDefinition()) + .blockDefinition(null) + .count(1) + .build()); + } + // ComponentItemData - used to register some custom properties componentItemData.add(customMapping.componentItemData()); customItemOptions.add(Pair.of(customItem.customItemOptions(), customMapping.itemDefinition())); @@ -523,7 +533,7 @@ public class ItemRegistryPopulator { mappings.set(javaItem.javaId(), mapping); registry.put(customItemId, mapping.getBedrockDefinition()); - if (customItem.creativeGroup() != null || customItem.creativeCategory().isPresent()) { + if (customItem.creativeCategory().isPresent()) { creativeItems.add(ItemData.builder() .definition(registration.mapping().getBedrockDefinition()) .netId(creativeNetId.incrementAndGet()) diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 73cbf32c8..7a4a8ff6f 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -113,8 +113,6 @@ import org.geysermc.geyser.api.event.bedrock.SessionLoginEvent; import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.api.network.RemoteServer; import org.geysermc.geyser.api.util.PlatformType; -import org.geysermc.geyser.impl.camera.CameraDefinitions; -import org.geysermc.geyser.impl.camera.GeyserCameraData; import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.configuration.EmoteOffhandWorkaroundOption; import org.geysermc.geyser.configuration.GeyserConfiguration; @@ -127,6 +125,8 @@ import org.geysermc.geyser.entity.type.Tickable; import org.geysermc.geyser.entity.type.player.SessionPlayerEntity; import org.geysermc.geyser.erosion.AbstractGeyserboundPacketHandler; import org.geysermc.geyser.erosion.GeyserboundHandshakePacketHandler; +import org.geysermc.geyser.impl.camera.CameraDefinitions; +import org.geysermc.geyser.impl.camera.GeyserCameraData; import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.PlayerInventory; import org.geysermc.geyser.inventory.recipe.GeyserRecipe; @@ -1464,9 +1464,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { } public void setServerRenderDistance(int renderDistance) { - // +1 is for Fabric and Spigot - // Without the client misses loading some chunks per https://github.com/GeyserMC/Geyser/issues/3490 - // Fog still appears essentially normally // Ensure render distance is not above 96 as sending a larger value at any point crashes mobile clients and 96 is the max of any bedrock platform renderDistance = Math.min(renderDistance, 96); this.serverRenderDistance = renderDistance; From a0fd720e7c00a542933b9e8544c5fb3e8f3d7cb8 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Mon, 11 Mar 2024 00:03:37 -0700 Subject: [PATCH 202/344] Fix client crash issue if empty recipe is sent (#4485) * Fix client crash issue if empty recipe is sent Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * More efficent order Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Recipes are recipies Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --------- Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .../java/JavaClientboundRecipesTranslator.java | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaClientboundRecipesTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaClientboundRecipesTranslator.java index fbf4c6f7b..3fe5abff8 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaClientboundRecipesTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaClientboundRecipesTranslator.java @@ -27,7 +27,6 @@ package org.geysermc.geyser.translator.protocol.java; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundRecipePacket; import org.cloudburstmc.protocol.bedrock.packet.UnlockedRecipesPacket; -import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; @@ -47,12 +46,22 @@ public class JavaClientboundRecipesTranslator extends PacketTranslator { + List recipes = getBedrockRecipes(session, packet.getRecipes()); + if (recipes.isEmpty()) { + // Sending an empty list here packet will crash the client as of 1.20.60 + return; + } recipesPacket.setAction(UnlockedRecipesPacket.ActionType.NEWLY_UNLOCKED); - recipesPacket.getUnlockedRecipes().addAll(getBedrockRecipes(session, packet.getRecipes())); + recipesPacket.getUnlockedRecipes().addAll(recipes); } case REMOVE -> { + List recipes = getBedrockRecipes(session, packet.getRecipes()); + if (recipes.isEmpty()) { + // Sending an empty list here will crash the client as of 1.20.60 + return; + } recipesPacket.setAction(UnlockedRecipesPacket.ActionType.REMOVE_UNLOCKED); - recipesPacket.getUnlockedRecipes().addAll(getBedrockRecipes(session, packet.getRecipes())); + recipesPacket.getUnlockedRecipes().addAll(recipes); } } session.sendUpstreamPacket(recipesPacket); @@ -70,5 +79,4 @@ public class JavaClientboundRecipesTranslator extends PacketTranslator Date: Mon, 11 Mar 2024 00:29:27 -0700 Subject: [PATCH 203/344] Support Bedrock 1.20.70 (#4477) * Support 1.20.70 Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Update readme Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Use 1.20.70 mappings Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Creative lectern drops work but not survival yet Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Fix lectern book pickup in survival Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Add copyright notices to new files Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Temp fix for incorrect creative_items from Cloudburst/Data Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Fix item frame breaking in creative Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Clarify what to remove when 1.20.60 support is dropped Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Don't use dim change enum pre 1.20.70 Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --------- Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- README.md | 2 +- build-logic/src/main/kotlin/extensions.kt | 48 +- core/build.gradle.kts | 16 + .../geysermc/geyser/network/GameProtocol.java | 12 +- .../populator/BlockRegistryPopulator.java | 8 +- .../registry/populator/Conversion630_622.java | 4 + ...ion630_649.java => Conversion649_630.java} | 36 +- .../registry/populator/Conversion662_649.java | 156 + .../populator/ItemRegistryPopulator.java | 6 +- .../BedrockItemFrameDropItemTranslator.java | 2 + .../BedrockLecternUpdateTranslator.java | 1 + .../player/BedrockActionTranslator.java | 76 +- .../BedrockLevelSoundEventTranslator.java | 26 + .../resources/bedrock/biome_definitions.dat | Bin 2605093 -> 41676 bytes .../bedrock/block_palette.1_20_70.nbt | Bin 0 -> 176502 bytes .../bedrock/creative_items.1_20_70.json | 5803 ++++++++++++++++ .../resources/bedrock/entity_identifiers.dat | Bin 7886 -> 7886 bytes .../bedrock/runtime_item_states.1_20_70.json | 6126 +++++++++++++++++ core/src/main/resources/mappings | 2 +- gradle/libs.versions.toml | 6 +- 20 files changed, 12288 insertions(+), 42 deletions(-) rename core/src/main/java/org/geysermc/geyser/registry/populator/{Conversion630_649.java => Conversion649_630.java} (51%) create mode 100644 core/src/main/java/org/geysermc/geyser/registry/populator/Conversion662_649.java create mode 100644 core/src/main/resources/bedrock/block_palette.1_20_70.nbt create mode 100644 core/src/main/resources/bedrock/creative_items.1_20_70.json create mode 100644 core/src/main/resources/bedrock/runtime_item_states.1_20_70.json diff --git a/README.md b/README.md index d58e2eb58..c6445155f 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,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.20.40 - 1.20.61 and Minecraft Java 1.20.4 +### Currently supporting Minecraft Bedrock 1.20.40 - 1.20.70 and Minecraft Java 1.20.4 ## Setting Up Take a look [here](https://wiki.geysermc.org/geyser/setup/) for how to set up Geyser. diff --git a/build-logic/src/main/kotlin/extensions.kt b/build-logic/src/main/kotlin/extensions.kt index 1e1732852..b4a14f678 100644 --- a/build-logic/src/main/kotlin/extensions.kt +++ b/build-logic/src/main/kotlin/extensions.kt @@ -24,11 +24,17 @@ */ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import org.gradle.api.DefaultTask import org.gradle.api.Project import org.gradle.api.artifacts.MinimalExternalModuleDependency import org.gradle.api.artifacts.ProjectDependency import org.gradle.api.provider.Provider +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.options.Option +import org.gradle.api.tasks.TaskAction import org.gradle.kotlin.dsl.named +import java.io.File +import java.net.URL fun Project.relocate(pattern: String) { tasks.named("shadowJar") { @@ -69,5 +75,45 @@ fun Project.provided(dependency: MinimalExternalModuleDependency) = fun Project.provided(provider: Provider) = provided(provider.get()) +open class DownloadFilesTask : DefaultTask() { + @Input + var urls: List = listOf() + + @Input + var destinationDir: String = "" + + @Option(option="suffix", description="suffix") + @Input + var suffix: String = "" + + @Input + var suffixedFiles: List = listOf() + + @TaskAction + fun downloadAndAddSuffix() { + urls.forEach { fileUrl -> + val fileName = fileUrl.substringAfterLast("/") + val baseName = fileName.substringBeforeLast(".") + val extension = fileName.substringAfterLast(".", "") + val shouldSuffix = fileName in suffixedFiles + val suffixedFileName = if (shouldSuffix && extension.isNotEmpty()) "$baseName.$suffix.$extension" else fileName + val outputFile = File(destinationDir, suffixedFileName) + + if (!outputFile.parentFile.exists()) { + outputFile.parentFile.mkdirs() + } + + URL(fileUrl).openStream().use { input -> + outputFile.outputStream().use { output -> + input.copyTo(output) + } + } + + println("Downloaded: $suffixedFileName") + } + } +} + private fun calcExclusion(section: String, bit: Int, excludedOn: Int): String = - if (excludedOn and bit > 0) section else "" \ No newline at end of file + if (excludedOn and bit > 0) section else "" + diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 6d289ae37..054f4f0ae 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -132,3 +132,19 @@ inner class GitInfo { // todo remove this when we're not using Jenkins anymore fun jenkinsBuildNumber(): String? = System.getenv("BUILD_NUMBER") + +// Manual task to download the bedrock data files from the CloudburstMC/Data repository +// Invoke with ./gradlew :core:downloadBedrockData --suffix=1_20_70 +// Set suffix to the current Bedrock version +tasks.register("downloadBedrockData") { + urls = listOf( + "https://raw.githubusercontent.com/CloudburstMC/Data/master/entity_identifiers.dat", + "https://raw.githubusercontent.com/CloudburstMC/Data/master/biome_definitions.dat", + "https://raw.githubusercontent.com/CloudburstMC/Data/master/block_palette.nbt", + "https://raw.githubusercontent.com/CloudburstMC/Data/master/creative_items.json", + "https://raw.githubusercontent.com/CloudburstMC/Data/master/runtime_item_states.json" + ) + suffixedFiles = listOf("block_palette.nbt", "creative_items.json", "runtime_item_states.json") + + destinationDir = "$projectDir/src/main/resources/bedrock" +} \ No newline at end of file diff --git a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java index a03a36ad2..3ead79d9e 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java @@ -32,6 +32,7 @@ import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; import org.cloudburstmc.protocol.bedrock.codec.v622.Bedrock_v622; import org.cloudburstmc.protocol.bedrock.codec.v630.Bedrock_v630; import org.cloudburstmc.protocol.bedrock.codec.v649.Bedrock_v649; +import org.cloudburstmc.protocol.bedrock.codec.v662.Bedrock_v662; import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec; import org.geysermc.geyser.session.GeyserSession; @@ -47,7 +48,7 @@ public final class GameProtocol { * Default Bedrock codec that should act as a fallback. Should represent the latest available * release of the game that Geyser supports. */ - public static final BedrockCodec DEFAULT_BEDROCK_CODEC = Bedrock_v649.CODEC; + public static final BedrockCodec DEFAULT_BEDROCK_CODEC = Bedrock_v662.CODEC; /** * A list of all supported Bedrock versions that can join Geyser @@ -67,8 +68,11 @@ public final class GameProtocol { SUPPORTED_BEDROCK_CODECS.add(Bedrock_v630.CODEC.toBuilder() .minecraftVersion("1.20.50/1.20.51") .build()); + SUPPORTED_BEDROCK_CODECS.add(Bedrock_v649.CODEC.toBuilder() + .minecraftVersion("1.20.60/1.20.62") + .build()); SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC.toBuilder() - .minecraftVersion("1.20.60/1.20.61") + .minecraftVersion("1.20.70") .build()); } @@ -92,6 +96,10 @@ public final class GameProtocol { return session.getUpstream().getProtocolVersion() < Bedrock_v630.CODEC.getProtocolVersion(); } + public static boolean isPre1_20_70(GeyserSession session) { + return session.getUpstream().getProtocolVersion() < Bedrock_v662.CODEC.getProtocolVersion(); + } + public static boolean is1_20_60orHigher(int protocolVersion) { return protocolVersion >= Bedrock_v649.CODEC.getProtocolVersion(); } 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 8aa16fe48..4c52a1530 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 @@ -42,6 +42,7 @@ import org.cloudburstmc.nbt.NbtType; import org.cloudburstmc.protocol.bedrock.codec.v622.Bedrock_v622; import org.cloudburstmc.protocol.bedrock.codec.v630.Bedrock_v630; import org.cloudburstmc.protocol.bedrock.codec.v649.Bedrock_v649; +import org.cloudburstmc.protocol.bedrock.codec.v662.Bedrock_v662; import org.cloudburstmc.protocol.bedrock.data.BlockPropertyData; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.geysermc.geyser.GeyserImpl; @@ -118,9 +119,10 @@ public final class BlockRegistryPopulator { private static void registerBedrockBlocks() { var blockMappers = ImmutableMap., Remapper>builder() .put(ObjectIntPair.of("1_20_40", Bedrock_v622.CODEC.getProtocolVersion()), Conversion630_622::remapBlock) - .put(ObjectIntPair.of("1_20_50", Bedrock_v630.CODEC.getProtocolVersion()), tag -> tag) + .put(ObjectIntPair.of("1_20_50", Bedrock_v630.CODEC.getProtocolVersion()), Conversion649_630::remapBlock) // Only changes in 1.20.60 are hard_stained_glass (an EDU only block) - .put(ObjectIntPair.of("1_20_60", Bedrock_v649.CODEC.getProtocolVersion()), tag -> tag) + .put(ObjectIntPair.of("1_20_60", Bedrock_v649.CODEC.getProtocolVersion()), Conversion662_649::remapBlock) + .put(ObjectIntPair.of("1_20_70", Bedrock_v662.CODEC.getProtocolVersion()), tag -> tag) .build(); // We can keep this strong as nothing should be garbage collected @@ -133,7 +135,7 @@ public final class BlockRegistryPopulator { List vanillaBlockStates; List blockStates; try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow(String.format("bedrock/block_palette.%s.nbt", palette.key())); - NBTInputStream nbtInputStream = new NBTInputStream(new DataInputStream(new GZIPInputStream(stream)), true, true)) { + NBTInputStream nbtInputStream = new NBTInputStream(new DataInputStream(new GZIPInputStream(stream)), true, true)) { NbtMap blockPalette = (NbtMap) nbtInputStream.readTag(); vanillaBlockStates = new ArrayList<>(blockPalette.getList("blocks", NbtType.COMPOUND)); diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion630_622.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion630_622.java index 7c1453dc7..398eabc3c 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion630_622.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion630_622.java @@ -121,6 +121,8 @@ class Conversion630_622 { } static GeyserMappingItem remapItem(@SuppressWarnings("unused") Item item, GeyserMappingItem mapping) { + mapping = Conversion649_630.remapItem(item, mapping); + String replacement = ITEMS.get(mapping.getBedrockIdentifier()); if (replacement == null) { return mapping; @@ -130,6 +132,8 @@ class Conversion630_622 { } static NbtMap remapBlock(NbtMap tag) { + tag = Conversion649_630.remapBlock(tag); + final String name = tag.getString("name"); String replacement; diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion630_649.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion649_630.java similarity index 51% rename from core/src/main/java/org/geysermc/geyser/registry/populator/Conversion630_649.java rename to core/src/main/java/org/geysermc/geyser/registry/populator/Conversion649_630.java index ed66322ff..56de1081e 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion630_649.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion649_630.java @@ -22,19 +22,41 @@ * @author GeyserMC * @link https://github.com/GeyserMC/Geyser */ - package org.geysermc.geyser.registry.populator; +import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.registry.type.GeyserMappingItem; +public class Conversion649_630 { + + static GeyserMappingItem remapItem(@SuppressWarnings("unused") Item item, GeyserMappingItem mapping) { + mapping = Conversion662_649.remapItem(item, mapping); -public class Conversion630_649 { + String identifer = mapping.getBedrockIdentifier(); - static GeyserMappingItem remapItem(@SuppressWarnings("unused") Item item, GeyserMappingItem mapping) { - if (mapping.getBedrockIdentifier().equalsIgnoreCase("minecraft:scute")) { - return mapping.withBedrockIdentifier("minecraft:turtle_scute"); + switch (identifer) { + case "minecraft:turtle_scute" -> { return mapping.withBedrockIdentifier("minecraft:scute"); } + case "minecraft:trial_spawner" -> { return mapping.withBedrockIdentifier("minecraft:mob_spawner"); } + case "minecraft:trial_key" -> { return mapping.withBedrockIdentifier("minecraft:echo_shard"); } + default -> { return mapping; } + } + } + + static NbtMap remapBlock(NbtMap tag) { + tag = Conversion662_649.remapBlock(tag); + + final String name = tag.getString("name"); + + if (name.equals("minecraft:trial_spawner")) { + NbtMapBuilder builder = tag.toBuilder() + .putString("name", "minecraft:mob_spawner") + .putCompound("states", NbtMap.EMPTY); + + return builder.build(); + } + + return tag; } - return mapping; - } } diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion662_649.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion662_649.java new file mode 100644 index 000000000..6dc6b01a0 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion662_649.java @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2019-2024 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 org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtMapBuilder; +import org.geysermc.geyser.item.type.Item; +import org.geysermc.geyser.registry.type.GeyserMappingItem; + +import java.util.List; +import java.util.stream.Stream; + +public class Conversion662_649 { + + private static final List NEW_MISC = List.of("minecraft:grass_block", "minecraft:trial_spawner"); + private static final List NEW_WOODS = List.of("minecraft:oak_wood", "minecraft:spruce_wood", "minecraft:birch_wood", "minecraft:jungle_wood", "minecraft:acacia_wood", "minecraft:dark_oak_wood", "minecraft:stripped_oak_wood", "minecraft:stripped_spruce_wood", "minecraft:stripped_birch_wood", "minecraft:stripped_jungle_wood", "minecraft:stripped_acacia_wood", "minecraft:stripped_dark_oak_wood"); + private static final List NEW_LEAVES = List.of("minecraft:oak_leaves", "minecraft:spruce_leaves", "minecraft:birch_leaves", "minecraft:jungle_leaves"); + private static final List NEW_LEAVES2 = List.of("minecraft:acacia_leaves", "minecraft:dark_oak_leaves"); + private static final List NEW_SLABS = List.of("minecraft:oak_slab", "minecraft:spruce_slab", "minecraft:birch_slab", "minecraft:jungle_slab", "minecraft:acacia_slab", "minecraft:dark_oak_slab", "minecraft:oak_double_slab", "minecraft:spruce_double_slab", "minecraft:birch_double_slab", "minecraft:jungle_double_slab", "minecraft:acacia_double_slab", "minecraft:dark_oak_double_slab"); + private static final List NEW_BLOCKS = Stream.of(NEW_WOODS, NEW_LEAVES, NEW_LEAVES2, NEW_SLABS, NEW_MISC).flatMap(List::stream).toList(); + + + static GeyserMappingItem remapItem(@SuppressWarnings("unused") Item item, GeyserMappingItem mapping) { + String identifer = mapping.getBedrockIdentifier(); + + if (identifer.equals("minecraft:grass_block")) { + return mapping.withBedrockIdentifier("minecraft:grass"); + } + + if (NEW_WOODS.contains(identifer)) { + switch (identifer) { + case "minecraft:oak_wood" -> { return mapping.withBedrockIdentifier("minecraft:wood").withBedrockData(0); } + case "minecraft:spruce_wood" -> { return mapping.withBedrockIdentifier("minecraft:wood").withBedrockData(1); } + case "minecraft:birch_wood" -> { return mapping.withBedrockIdentifier("minecraft:wood").withBedrockData(2); } + case "minecraft:jungle_wood" -> { return mapping.withBedrockIdentifier("minecraft:wood").withBedrockData(3); } + case "minecraft:acacia_wood" -> { return mapping.withBedrockIdentifier("minecraft:wood").withBedrockData(4); } + case "minecraft:dark_oak_wood" -> { return mapping.withBedrockIdentifier("minecraft:wood").withBedrockData(5); } + case "minecraft:stripped_oak_wood" -> { return mapping.withBedrockIdentifier("minecraft:wood").withBedrockData(8); } + case "minecraft:stripped_spruce_wood" -> { return mapping.withBedrockIdentifier("minecraft:wood").withBedrockData(9); } + case "minecraft:stripped_birch_wood" -> { return mapping.withBedrockIdentifier("minecraft:wood").withBedrockData(10); } + case "minecraft:stripped_jungle_wood" -> { return mapping.withBedrockIdentifier("minecraft:wood").withBedrockData(11); } + case "minecraft:stripped_acacia_wood" -> { return mapping.withBedrockIdentifier("minecraft:wood").withBedrockData(12); } + case "minecraft:stripped_dark_oak_wood" -> { return mapping.withBedrockIdentifier("minecraft:wood").withBedrockData(13); } + } + } + + if (NEW_LEAVES.contains(identifer) || NEW_LEAVES2.contains(identifer)) { + switch (identifer) { + case "minecraft:oak_leaves" -> { return mapping.withBedrockIdentifier("minecraft:leaves").withBedrockData(0); } + case "minecraft:spruce_leaves" -> { return mapping.withBedrockIdentifier("minecraft:leaves").withBedrockData(1); } + case "minecraft:birch_leaves" -> { return mapping.withBedrockIdentifier("minecraft:leaves").withBedrockData(2); } + case "minecraft:jungle_leaves" -> { return mapping.withBedrockIdentifier("minecraft:leaves").withBedrockData(3); } + case "minecraft:acacia_leaves" -> { return mapping.withBedrockIdentifier("minecraft:leaves2").withBedrockData(0); } + case "minecraft:dark_oak_leaves" -> { return mapping.withBedrockIdentifier("minecraft:leaves2").withBedrockData(1); } + } + } + + return mapping; + } + + static NbtMap remapBlock(NbtMap tag) { + final String name = tag.getString("name"); + + if (!NEW_BLOCKS.contains(name)) { + return tag; + } + + String replacement; + + if (name.equals("minecraft:grass_block")) { + replacement = "minecraft:grass"; + + NbtMapBuilder builder = tag.toBuilder(); + builder.putString("name", replacement); + + return builder.build(); + } + + if (NEW_WOODS.contains(name)) { + replacement = "minecraft:wood"; + + NbtMap states = tag.getCompound("states"); + boolean stripped = name.startsWith("minecraft:stripped_"); + String woodType = name.replaceAll("minecraft:|_wood|stripped_", ""); + + NbtMapBuilder statesBuilder = states.toBuilder() + .putString("wood_type", woodType) + .putBoolean("stripped_bit", stripped); + + NbtMapBuilder builder = tag.toBuilder() + .putString("name", replacement) + .putCompound("states", statesBuilder.build()); + + return builder.build(); + } + + if (NEW_LEAVES.contains(name) || NEW_LEAVES2.contains(name)) { + boolean leaves2 = NEW_LEAVES2.contains(name); + replacement = leaves2 ? "minecraft:leaves2" : "minecraft:leaves"; + + NbtMap states = tag.getCompound("states"); + String leafType = name.replaceAll("minecraft:|_leaves", ""); + + NbtMapBuilder statesBuilder = states.toBuilder() + .putString(leaves2 ? "new_leaf_type" : "old_leaf_type", leafType); + + NbtMapBuilder builder = tag.toBuilder() + .putString("name", replacement) + .putCompound("states", statesBuilder.build()); + + return builder.build(); + } + + + if (NEW_SLABS.contains(name)) { + replacement = name.contains("double") ? "minecraft:double_wooden_slab" : "minecraft:wooden_slab"; + + NbtMap states = tag.getCompound("states"); + String woodType = name.replaceAll("minecraft:|_double|_slab", ""); + + NbtMapBuilder statesBuilder = states.toBuilder() + .putString("wood_type", woodType); + + NbtMapBuilder builder = tag.toBuilder() + .putString("name", replacement) + .putCompound("states", statesBuilder.build()); + + return builder.build(); + } + + return tag; + } +} 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 c1593447d..708f92dc5 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 @@ -41,6 +41,7 @@ import org.cloudburstmc.nbt.NbtType; import org.cloudburstmc.protocol.bedrock.codec.v622.Bedrock_v622; import org.cloudburstmc.protocol.bedrock.codec.v630.Bedrock_v630; import org.cloudburstmc.protocol.bedrock.codec.v649.Bedrock_v649; +import org.cloudburstmc.protocol.bedrock.codec.v662.Bedrock_v662; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; @@ -90,8 +91,9 @@ public class ItemRegistryPopulator { public static void populate() { List paletteVersions = new ArrayList<>(3); paletteVersions.add(new PaletteVersion("1_20_40", Bedrock_v622.CODEC.getProtocolVersion(), Collections.emptyMap(), Conversion630_622::remapItem)); - paletteVersions.add(new PaletteVersion("1_20_50", Bedrock_v630.CODEC.getProtocolVersion())); - paletteVersions.add(new PaletteVersion("1_20_60", Bedrock_v649.CODEC.getProtocolVersion(), Collections.emptyMap(), Conversion630_649::remapItem)); + paletteVersions.add(new PaletteVersion("1_20_50", Bedrock_v630.CODEC.getProtocolVersion(), Collections.emptyMap(), Conversion649_630::remapItem)); + paletteVersions.add(new PaletteVersion("1_20_60", Bedrock_v649.CODEC.getProtocolVersion(), Collections.emptyMap(), Conversion662_649::remapItem)); + paletteVersions.add(new PaletteVersion("1_20_70", Bedrock_v662.CODEC.getProtocolVersion())); GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap(); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockItemFrameDropItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockItemFrameDropItemTranslator.java index 8632dc4e1..4a5145ead 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockItemFrameDropItemTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockItemFrameDropItemTranslator.java @@ -39,10 +39,12 @@ import org.geysermc.geyser.translator.protocol.Translator; * Pre-1.16.210: used for both survival and creative item frame item removal *

* 1.16.210: only used in creative. + * 1.20.70: no longer used. */ @Translator(packet = ItemFrameDropItemPacket.class) public class BedrockItemFrameDropItemTranslator extends PacketTranslator { + // TODO: Remove when 1.20.60 is no longer supported @Override public void translate(GeyserSession session, ItemFrameDropItemPacket packet) { Entity entity = ItemFrameEntity.getItemFrameEntity(session, packet.getBlockPosition()); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockLecternUpdateTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockLecternUpdateTranslator.java index 2678128ed..6bac96206 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockLecternUpdateTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockLecternUpdateTranslator.java @@ -47,6 +47,7 @@ public class BedrockLecternUpdateTranslator extends PacketTranslatoriEQ9%3yWrUVui<|w@CMohycJki)-uZjK zw{P_>bovCbc>(---Q$)1>SOm1AXZUks9McXonN=RAa~G|_5Sy33K2F54H@?kQaOoA z5zM!sdyB~+A6dzV_0^onHAMWid_#m2&0>g)1^odo*ew6l1vr0AV>K^=i_X6fu2@i~ zG+_g>C@y{A9&{H#WsEI?6Dnev5)kwxF$Lz5giDuI&GY`1Ty=efi@+fvqXjOJ#G-gI z74T9E;l=hlTZuC8_7QgYw9}h;+oOrFp^vD9jyB?P>4)pYVg%!bj9JhkWH|Jx0gSMl zKt?5uPFEwB6>j#|g@q_g?VwcekjdIoE%?-+pxD<|uuJw#J;hmC~f=e$OzZcIqJG)x*bC zloK{DQ$37rjxSfG*=)SQXd%>SP=VnW)j@3Y`Z-lT9%72~zx?V+2!1=KuF|OGRO`58 z2lTMKN}UHAd(}H2G^8%`Bqq(^fycOT#J@ra^J0Xq3D*ZiAqXdj)PwQ#6Ehvo)B!zF z@)4ZHtr%%RQs-6Dky_Jmz8*Le&^(4MSwZ7Xwb3=2i(v9a&C;lOj7Pd2&<2n+Bcx@KwBwrAgQTWanI#A&4`fcu z(+W{O923F~wT9YoeMpQ5LEc}(MR`#Z5Q1Wa4}*JyJ~2J!W@hC``DW;DqvuO!S7n_< zIJ&Pbs{p6ewMkcsWrvWi3`t8mbQOxG0&c1G99GTI=;tD7*Gu|22=;5}d*M$FJvJTL z%ln9lFoUAI(xY}O4q$vcJprb&UfcgXdaIq@4)5Kd%i-Nluazb7Ak$E(IG;U0zc%8$ z0EXuz;0Q|x3>4fmXv&9cQN!i9oi~XskhR6y^d&HoE5gDmKB&VVe~9Ov62W#Yrv*xH z8s@<_`|P7UP+%9cheo^Z@6RqYjJOt6H9|uzoIj^x)$wiRVdjnOW6(h{GvOM=jDv3} z#%Z82C-K2rJ{;hK&|^UpVV;)RG0M4A-_Ec}lqg02fk#q(ld<6mCd-s|Mss|lh49Hg zId`o6Nv^JruT9o|TuC5KzIzE6e8aAg;WIem2Tg1O#&LZwfu%=ovK|~#!hF20)i^Cp za21)xr3sF7m>x)EDer?*>iO5yqWn+ns=Qs#V&_js&1TfqYMGUj1pf%wpR_uhaO*1R zhegOz36nZ3WyYi#Efc;n06z@Uh569kVc7>Ck=Bw?Fks05&(#XCG`uBQaI40uuwar# ziljs9t#%|G*l3-iWL*L4vu!?{@T*4KFtN!!Dw4)_*`_8|t{H3ulJ;81;Pd5!-fmxs z)U$oeQ6#;%b4)Rk8a(#<6Mcz42Kn)Kl01aTiB``#XrF?l-Q#o15>`99b6as-YELdE zF)zr%a%Jx7_~a24f(3!5F&@M~s^10@Gwmg{kzRW$Hmj&lM$)$hq+ z$xwrQKE$*(m24@T2%qOT--Iu~Dcr`|2FTrHb;If^H3Rg83>M~@Y(;Qpn{#ni%C(9M z%+S=KbAr29O~DzXO#^2fu1m@W%Jk%fhq_#hlF$B`TV2US6PJ2nmU|(tW0TG;w`Tep z_i{BE7K9a$z1HM~Kp)|T%WK?QBO@h`RvH5l~`KZ?~!Lw8_gTW z=*anl)qQ!lZIVt53bAIt*dT;>F+nNtQ(xX`II7QIV9&yvUMJt>$ep&n5)RP$bEN5O z^K%hwQx)8k4pBF3@Aohm>2>OY`SADJf*J63G;hrR4(0q+vITx#S1@~|T%}JsIJMsD zl6+L*mnvN7VY<+a;Io$t7irXDj0=QP?``>(!Vgm%$mg>ezoJ>M%t#HL-Uk%A)+Fc} zt~gw!@dGW7`W5dBu!QwJdK)10@MEVp51wbe3_LMFGw@YAT?`dQ--FWLTpy8`th^W7 fa4c?*k3lf?sBeKoFW>l(%v6ahe+T}Yhwl0hK|=ny literal 2605093 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%0Dr|j|qX{c2 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

bkIWg`I^~cgV&?1^)kY?)Q07(A8SpTQ2lKpk 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νeHj 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ⅇf_;0AHH<-@xezNx8u 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 D9);gD literal 0 HcmV?d00001 diff --git a/core/src/main/resources/bedrock/creative_items.1_20_70.json b/core/src/main/resources/bedrock/creative_items.1_20_70.json new file mode 100644 index 000000000..ed498b782 --- /dev/null +++ b/core/src/main/resources/bedrock/creative_items.1_20_70.json @@ -0,0 +1,5803 @@ +{ + "items": [ + { + "id": "minecraft:oak_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQFAAAACAQAbmFtZRQAbWluZWNyYWZ0Om9ha19wbGFua3MECQBuYW1lX2hhc2ilMDLR92rQ4wMKAG5ldHdvcmtfaWS2GotyCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:spruce_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTiAwAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9wbGFua3MECQBuYW1lX2hhc2iumBkmFGFE8gMKAG5ldHdvcmtfaWSo8TFgCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:birch_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTjAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX3BsYW5rcwQJAG5hbWVfaGFzaLrrAKJqV2WFAwoAbmV0d29ya19pZL+e3ZAKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:jungle_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTkAwAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9wbGFua3MECQBuYW1lX2hhc2iBM3k4T3FAugMKAG5ldHdvcmtfaWSXUmBCCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:acacia_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTlAwAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9wbGFua3MECQBuYW1lX2hhc2g60edJxO5/aAMKAG5ldHdvcmtfaWTUXozECgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:dark_oak_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTmAwAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX3BsYW5rcwQJAG5hbWVfaGFzaAr64wkQ9cA7AwoAbmV0d29ya19pZFbMeR0KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:mangrove_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTlAgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX3BsYW5rcwQJAG5hbWVfaGFzaPvLtcEA0F8xAwoAbmV0d29ya19pZEvnlCYKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:cherry_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAwAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9wbGFua3MECQBuYW1lX2hhc2hNIvVh/lVW7gMKAG5ldHdvcmtfaWQTXpRoCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:bamboo_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT9AgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19wbGFua3MECQBuYW1lX2hhc2gYnjNz7SCCjgMKAG5ldHdvcmtfaWTi8ySSCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:bamboo_mosaic", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT8AgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19tb3NhaWMECQBuYW1lX2hhc2izSEgiMKOp/AMKAG5ldHdvcmtfaWQZ/p8xCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:crimson_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTxAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fcGxhbmtzBAkAbmFtZV9oYXNoJc5IKqNXJnwDCgBuZXR3b3JrX2lkwtJDdQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:warped_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTyAQAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9wbGFua3MECQBuYW1lX2hhc2g3yGXEWhe6LgMKAG5ldHdvcmtfaWStTABvCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWSE4JosCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCwBjb2JibGVzdG9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWTUvV6XCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEQBtb3NzeV9jb2JibGVzdG9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWT4opb2CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBwBncmFuaXRlCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQAMQTVCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBwBkaW9yaXRlCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQIbDOcCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCABhbmRlc2l0ZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWSZKhusCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCQBzYW5kc3RvbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWSp4zgCCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlDQByZWRfc2FuZHN0b25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRbqVHTCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCwBzdG9uZV9icmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRr0ZT/CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEQBtb3NzeV9zdG9uZV9icmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRnLis3CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBQBicmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQNLzfSCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlDABuZXRoZXJfYnJpY2sIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQ5h0xwCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEAByZWRfbmV0aGVyX2JyaWNrCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWS9J0B2CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCQBlbmRfYnJpY2sIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRPbkJeCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCgBwcmlzbWFyaW5lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:blackstone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQUAgAACAQAbmFtZRkAbWluZWNyYWZ0OmJsYWNrc3RvbmVfd2FsbAQJAG5hbWVfaGFzaMP8XppUSU1RAwoAbmV0d29ya19pZMbeBBsKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:polished_blackstone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQoAgAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfd2FsbAQJAG5hbWVfaGFzaP6SwV08YwzAAwoAbmV0d29ya19pZAJLsz8KBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:polished_blackstone_brick_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQVAgAACAQAbmFtZSgAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfd2FsbAQJAG5hbWVfaGFzaBBIDZbHxiEzAwoAbmV0d29ya19pZEbLV8cKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:cobbled_deepslate_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR9AgAACAQAbmFtZSAAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3dhbGwECQBuYW1lX2hhc2iECY5oKxeT+gMKAG5ldHdvcmtfaWRCnPrFCgYAc3RhdGVzCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:deepslate_tile_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3dhbGwECQBuYW1lX2hhc2jz7N+PeuEXgQMKAG5ldHdvcmtfaWTqw4s4CgYAc3RhdGVzCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:polished_deepslate_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSBAgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV93YWxsBAkAbmFtZV9oYXNoHxjTdj9pevMDCgBuZXR3b3JrX2lkIvBYYwoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:deepslate_brick_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSJAgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja193YWxsBAkAbmFtZV9oYXNoEs3EQrjroyEDCgBuZXR3b3JrX2lkwlrCGwoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:mud_brick_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTgAgAACAQAbmFtZRgAbWluZWNyYWZ0Om11ZF9icmlja193YWxsBAkAbmFtZV9oYXNov9b98ATpUSwDCgBuZXR3b3JrX2lkH/1WZQoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:oak_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRVAAAACAQAbmFtZRMAbWluZWNyYWZ0Om9ha19mZW5jZQQJAG5hbWVfaGFzaGEmid7AaCWRAwoAbmV0d29ya19pZDvPEXcKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:spruce_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRCAwAACAQAbmFtZRYAbWluZWNyYWZ0OnNwcnVjZV9mZW5jZQQJAG5hbWVfaGFzaPQCm+aX1ZQeAwoAbmV0d29ya19pZD1QUEoKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:birch_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ/AwAACAQAbmFtZRUAbWluZWNyYWZ0OmJpcmNoX2ZlbmNlBAkAbmFtZV9oYXNo6CJ2ATpANfgDCgBuZXR3b3JrX2lkmCUV2QoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:jungle_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRBAwAACAQAbmFtZRYAbWluZWNyYWZ0Omp1bmdsZV9mZW5jZQQJAG5hbWVfaGFzaOX4cD9uAmsdAwoAbmV0d29ya19pZHz1VxkKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:acacia_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ+AwAACAQAbmFtZRYAbWluZWNyYWZ0OmFjYWNpYV9mZW5jZQQJAG5hbWVfaGFzaGjn+RlKVDH6AwoAbmV0d29ya19pZNVGubwKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:dark_oak_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRAAwAACAQAbmFtZRgAbWluZWNyYWZ0OmRhcmtfb2FrX2ZlbmNlBAkAbmFtZV9oYXNoGPj0gCgM0c0DCgBuZXR3b3JrX2lk2w+gEwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:mangrove_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTqAgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hbmdyb3ZlX2ZlbmNlBAkAbmFtZV9oYXNowwAd7tPu9bsDCgBuZXR3b3JrX2lkKEcd0goGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:cherry_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQTAwAACAQAbmFtZRYAbWluZWNyYWZ0OmNoZXJyeV9mZW5jZQQJAG5hbWVfaGFzaFmtUfHfTxcxAwoAbmV0d29ya19pZPCBxAIKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:bamboo_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQCAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJhbWJvb19mZW5jZQQJAG5hbWVfaGFzaCKRbxfXsfkiAwoAbmV0d29ya19pZJNXKFcKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:nether_brick_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRxAAAACAQAbmFtZRwAbWluZWNyYWZ0Om5ldGhlcl9icmlja19mZW5jZQQJAG5hbWVfaGFzaA6030ngawxcAwoAbmV0d29ya19pZLnjLF4KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:crimson_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT/AQAACAQAbmFtZRcAbWluZWNyYWZ0OmNyaW1zb25fZmVuY2UECQBuYW1lX2hhc2jhUhKv1HGj9AMKAG5ldHdvcmtfaWR3OH3OCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:warped_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQAAgAACAQAbmFtZRYAbWluZWNyYWZ0OndhcnBlZF9mZW5jZQQJAG5hbWVfaGFzaJfb3/YuKmOWAwoAbmV0d29ya19pZCpaGC8KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRrAAAACAQAbmFtZRQAbWluZWNyYWZ0OmZlbmNlX2dhdGUECQBuYW1lX2hhc2hTxpjEDmRzAwMKAG5ldHdvcmtfaWR+T9kTCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:spruce_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS3AAAACAQAbmFtZRsAbWluZWNyYWZ0OnNwcnVjZV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoanTVB84HRbkDCgBuZXR3b3JrX2lkEnw5egoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:birch_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS4AAAACAQAbmFtZRoAbWluZWNyYWZ0OmJpcmNoX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2jmfPklI8azSwMKAG5ldHdvcmtfaWQL77/BCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:jungle_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS5AAAACAQAbmFtZRsAbWluZWNyYWZ0Omp1bmdsZV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNobYVQkfBomIcDCgBuZXR3b3JrX2lkA1zgtgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:acacia_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS7AAAACAQAbmFtZRsAbWluZWNyYWZ0OmFjYWNpYV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoZnrLUx/XSekDCgBuZXR3b3JrX2lkHg/kTgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:dark_oak_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS6AAAACAQAbmFtZR0AbWluZWNyYWZ0OmRhcmtfb2FrX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2j2PTvdJJHcVQMKAG5ldHdvcmtfaWTwjOCeCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:mangrove_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTrAgAACAQAbmFtZR0AbWluZWNyYWZ0Om1hbmdyb3ZlX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2i/kOhBKiI/dAMKAG5ldHdvcmtfaWSfweCSCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:cherry_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQUAwAACAQAbmFtZRsAbWluZWNyYWZ0OmNoZXJyeV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoKWLgCk0z+PsDCgBuZXR3b3JrX2lk/9bTZQoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:bamboo_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAwAACAQAbmFtZRsAbWluZWNyYWZ0OmJhbWJvb19mZW5jZV9nYXRlBAkAbmFtZV9oYXNopH1JrUgwdIADCgBuZXR3b3JrX2lkzIpPywoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:crimson_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQBAgAACAQAbmFtZRwAbWluZWNyYWZ0OmNyaW1zb25fZmVuY2VfZ2F0ZQQJAG5hbWVfaGFzaHE3Gfd0Z2d2AwoAbmV0d29ya19pZDQzVbEKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQsAaW5fd2FsbF9iaXQAAQgAb3Blbl9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:warped_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQCAgAACAQAbmFtZRsAbWluZWNyYWZ0OndhcnBlZF9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoy0oIBjDIG4kDCgBuZXR3b3JrX2lkkf+/3QoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:normal_stone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSzAQAACAQAbmFtZR0AbWluZWNyYWZ0Om5vcm1hbF9zdG9uZV9zdGFpcnMECQBuYW1lX2hhc2hAEktZZOkGIwMKAG5ldHdvcmtfaWQeH1ALCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:stone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRDAAAACAQAbmFtZRYAbWluZWNyYWZ0OnN0b25lX3N0YWlycwQJAG5hbWVfaGFzaNRjqVC5GRVDAwoAbmV0d29ya19pZDcCv+MKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:mossy_cobblestone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSyAQAACAQAbmFtZSIAbWluZWNyYWZ0Om1vc3N5X2NvYmJsZXN0b25lX3N0YWlycwQJAG5hbWVfaGFzaMVSTq5z9n1RAwoAbmV0d29ya19pZFIfrhkKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:oak_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ1AAAACAQAbmFtZRQAbWluZWNyYWZ0Om9ha19zdGFpcnMECQBuYW1lX2hhc2jk/HFzdXy0FQMKAG5ldHdvcmtfaWQJjyzBCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:spruce_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSGAAAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9zdGFpcnMECQBuYW1lX2hhc2iznygw7uBPBQMKAG5ldHdvcmtfaWTv+is3CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:birch_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSHAAAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX3N0YWlycwQJAG5hbWVfaGFzaPfhbL619a3GAwoAbmV0d29ya19pZFyPlHAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:jungle_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSIAAAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9zdGFpcnMECQBuYW1lX2hhc2jodJsHUbOVxQMKAG5ldHdvcmtfaWR0z5d4CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:acacia_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSjAAAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9zdGFpcnMECQBuYW1lX2hhc2h3x1NmD43IqQMKAG5ldHdvcmtfaWS7Jwz6CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:dark_oak_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSkAAAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX3N0YWlycwQJAG5hbWVfaGFzaMfwkbYPbNmAAwoAbmV0d29ya19pZCmBYKAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:mangrove_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTnAgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX3N0YWlycwQJAG5hbWVfaGFzaNpUDY+uGMpyAwoAbmV0d29ya19pZChzUAsKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:cherry_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQcAwAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9zdGFpcnMECQBuYW1lX2hhc2jMtr0v9JY4zwMKAG5ldHdvcmtfaWRQwq31CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:bamboo_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT/AgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19zdGFpcnMECQBuYW1lX2hhc2jFOzWL8PalKwMKAG5ldHdvcmtfaWTVPh42CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:bamboo_mosaic_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQKAwAACAQAbmFtZR4AbWluZWNyYWZ0OmJhbWJvb19tb3NhaWNfc3RhaXJzBAkAbmFtZV9oYXNoNLPiveSHPaoDCgBuZXR3b3JrX2lk44PHjgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:stone_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRtAAAACAQAbmFtZRwAbWluZWNyYWZ0OnN0b25lX2JyaWNrX3N0YWlycwQJAG5hbWVfaGFzaN6tQViRo5cwAwoAbmV0d29ya19pZDMyMgIKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:mossy_stone_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSuAQAACAQAbmFtZSIAbWluZWNyYWZ0Om1vc3N5X3N0b25lX2JyaWNrX3N0YWlycwQJAG5hbWVfaGFzaIB/Zv5YBPuYAwoAbmV0d29ya19pZANTOsMKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:sandstone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSAAAAACAQAbmFtZRoAbWluZWNyYWZ0OnNhbmRzdG9uZV9zdGFpcnMECQBuYW1lX2hhc2hOyA0BoYUOPQMKAG5ldHdvcmtfaWSV/834CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:smooth_sandstone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSwAQAACAQAbmFtZSEAbWluZWNyYWZ0OnNtb290aF9zYW5kc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNoB+CuCd8Ruz8DCgBuZXR3b3JrX2lksR+m8QoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:red_sandstone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS0AAAACAQAbmFtZR4AbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNoPs0LpHPL24YDCgBuZXR3b3JrX2lkLYVt3woGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:smooth_red_sandstone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAQAACAQAbmFtZSUAbWluZWNyYWZ0OnNtb290aF9yZWRfc2FuZHN0b25lX3N0YWlycwQJAG5hbWVfaGFzaBvjtQv5pf+MAwoAbmV0d29ya19pZMHNND8KBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:granite_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAQAACAQAbmFtZRgAbWluZWNyYWZ0OmdyYW5pdGVfc3RhaXJzBAkAbmFtZV9oYXNoGzpvtoqKQjgDCgBuZXR3b3JrX2lkPkcB1goGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:polished_granite_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSrAQAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2dyYW5pdGVfc3RhaXJzBAkAbmFtZV9oYXNo3PvbSfEQklIDCgBuZXR3b3JrX2lkMmEm3AoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:diorite_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSpAQAACAQAbmFtZRgAbWluZWNyYWZ0OmRpb3JpdGVfc3RhaXJzBAkAbmFtZV9oYXNoi73T8VQuZmcDCgBuZXR3b3JrX2lk6i6nBQoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:polished_diorite_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSsAQAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2Rpb3JpdGVfc3RhaXJzBAkAbmFtZV9oYXNoFKRJd5Wk5L0DCgBuZXR3b3JrX2lkbt2ioAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:andesite_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSqAQAACAQAbmFtZRkAbWluZWNyYWZ0OmFuZGVzaXRlX3N0YWlycwQJAG5hbWVfaGFzaO5w2FKBw76EAwoAbmV0d29ya19pZKhXEgUKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:polished_andesite_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWStAQAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2FuZGVzaXRlX3N0YWlycwQJAG5hbWVfaGFzaNcZZ/zmLInIAwoAbmV0d29ya19pZJTHrlEKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRsAAAACAQAbmFtZRYAbWluZWNyYWZ0OmJyaWNrX3N0YWlycwQJAG5hbWVfaGFzaMyt+cRDk5O2AwoAbmV0d29ya19pZNeMh58KBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:nether_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRyAAAACAQAbmFtZR0AbWluZWNyYWZ0Om5ldGhlcl9icmlja19zdGFpcnMECQBuYW1lX2hhc2jRqIoOXgifBAMKAG5ldHdvcmtfaWQDiw5yCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:red_nether_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS3AQAACAQAbmFtZSEAbWluZWNyYWZ0OnJlZF9uZXRoZXJfYnJpY2tfc3RhaXJzBAkAbmFtZV9oYXNogQvosSbcj7kDCgBuZXR3b3JrX2lkx2IMtAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:end_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSxAQAACAQAbmFtZRoAbWluZWNyYWZ0OmVuZF9icmlja19zdGFpcnMECQBuYW1lX2hhc2hmlAk+QhsUsQMKAG5ldHdvcmtfaWTN7KFaCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:quartz_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWScAAAACAQAbmFtZRcAbWluZWNyYWZ0OnF1YXJ0el9zdGFpcnMECQBuYW1lX2hhc2hmvpvOqGi6egMKAG5ldHdvcmtfaWRmUTh7CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:smooth_quartz_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS4AQAACAQAbmFtZR4AbWluZWNyYWZ0OnNtb290aF9xdWFydHpfc3RhaXJzBAkAbmFtZV9oYXNoNZZ9rX0qZOsDCgBuZXR3b3JrX2lkzsgQyQoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:purpur_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTLAAAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnB1cl9zdGFpcnMECQBuYW1lX2hhc2ifwDxeezXD7gMKAG5ldHdvcmtfaWTT+rxiCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:prismarine_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQBAQAACAQAbmFtZRsAbWluZWNyYWZ0OnByaXNtYXJpbmVfc3RhaXJzBAkAbmFtZV9oYXNooTHSZ+IrYtcDCgBuZXR3b3JrX2lkxTJfeAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:dark_prismarine_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQCAQAACAQAbmFtZSAAbWluZWNyYWZ0OmRhcmtfcHJpc21hcmluZV9zdGFpcnMECQBuYW1lX2hhc2hIciLmam4o4AMKAG5ldHdvcmtfaWTVu7TCCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:prismarine_bricks_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAQAACAQAbmFtZSIAbWluZWNyYWZ0OnByaXNtYXJpbmVfYnJpY2tzX3N0YWlycwQJAG5hbWVfaGFzaNIjq1oBlZMMAwoAbmV0d29ya19pZGEFwLYKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:crimson_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT9AQAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fc3RhaXJzBAkAbmFtZV9oYXNoZJqIzCBpCq4DCgBuZXR3b3JrX2lktXE00AoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:warped_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT+AQAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9zdGFpcnMECQBuYW1lX2hhc2hOkY27jLD4RQMKAG5ldHdvcmtfaWQ+E5VrCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:blackstone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQTAgAACAQAbmFtZRsAbWluZWNyYWZ0OmJsYWNrc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNokdoUb76p9McDCgBuZXR3b3JrX2lk5fWI5goGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:polished_blackstone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQjAgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNolCFtFIE8MmADCgBuZXR3b3JrX2lkGTf7sgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:polished_blackstone_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQSAgAACAQAbmFtZSoAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfc3RhaXJzBAkAbmFtZV9oYXNonks6UlfpOmkDCgBuZXR3b3JrX2lkgYeOdAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAgAACAQAbmFtZRsAbWluZWNyYWZ0OmN1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoHfoAXYq5G3MDCgBuZXR3b3JrX2lkeetf7woGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:exposed_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAgAACAQAbmFtZSMAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcl9zdGFpcnMECQBuYW1lX2hhc2howneQGtZ9cgMKAG5ldHdvcmtfaWSg73zdCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:weathered_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAgAACAQAbmFtZSUAbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyX3N0YWlycwQJAG5hbWVfaGFzaP+R5loXxrVgAwoAbmV0d29ya19pZOnbRf4KBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:oxidized_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRkAgAACAQAbmFtZSQAbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNo6Jeoq5rsPxsDCgBuZXR3b3JrX2lkmRjDnQoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:waxed_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRlAgAACAQAbmFtZSEAbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoh07CQj0/SR8DCgBuZXR3b3JrX2lkmYqoqAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:waxed_exposed_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRmAgAACAQAbmFtZSkAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcl9zdGFpcnMECQBuYW1lX2hhc2guVct1ilmxTwMKAG5ldHdvcmtfaWQgCPROCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:waxed_weathered_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRnAgAACAQAbmFtZSsAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyX3N0YWlycwQJAG5hbWVfaGFzaPXC8Sz/phCpAwoAbmV0d29ya19pZHlwHVsKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:waxed_oxidized_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS/AgAACAQAbmFtZSoAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoaqGdkuhxVZUDCgBuZXR3b3JrX2lkYQXzzgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:cobbled_deepslate_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR8AgAACAQAbmFtZSIAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3N0YWlycwQJAG5hbWVfaGFzaPIfa+TpyJcIAwoAbmV0d29ya19pZJUvOYIKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:deepslate_tile_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3N0YWlycwQJAG5hbWVfaGFzaGFRFzB72mN2AwoAbmV0d29ya19pZJEOgIsKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:polished_deepslate_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSAAgAACAQAbmFtZSMAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV9zdGFpcnMECQBuYW1lX2hhc2iNCYxVik9sGAMKAG5ldHdvcmtfaWSRVPnYCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:deepslate_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSIAgAACAQAbmFtZSAAbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja19zdGFpcnMECQBuYW1lX2hhc2hIasOahEf83wMKAG5ldHdvcmtfaWQ1qEDCCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:mud_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTfAgAACAQAbmFtZRoAbWluZWNyYWZ0Om11ZF9icmlja19zdGFpcnMECQBuYW1lX2hhc2gt3qxK1NWajAMKAG5ldHdvcmtfaWSm9N3MCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:wooden_door" + }, + { + "id": "minecraft:spruce_door" + }, + { + "id": "minecraft:birch_door" + }, + { + "id": "minecraft:jungle_door" + }, + { + "id": "minecraft:acacia_door" + }, + { + "id": "minecraft:dark_oak_door" + }, + { + "id": "minecraft:mangrove_door" + }, + { + "id": "minecraft:cherry_door" + }, + { + "id": "minecraft:bamboo_door" + }, + { + "id": "minecraft:iron_door" + }, + { + "id": "minecraft:crimson_door" + }, + { + "id": "minecraft:warped_door" + }, + { + "id": "minecraft:trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRgAAAACAQAbmFtZRIAbWluZWNyYWZ0OnRyYXBkb29yBAkAbmFtZV9oYXNotYiAJGtN0xADCgBuZXR3b3JrX2lkyTAWkAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:spruce_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSUAQAACAQAbmFtZRkAbWluZWNyYWZ0OnNwcnVjZV90cmFwZG9vcgQJAG5hbWVfaGFzaOwlfbgBkUW4AwoAbmV0d29ya19pZPHy1K0KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:birch_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSRAQAACAQAbmFtZRgAbWluZWNyYWZ0OmJpcmNoX3RyYXBkb29yBAkAbmFtZV9oYXNoSLtLweOLJ7wDCgBuZXR3b3JrX2lkeJWDfgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:jungle_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSTAQAACAQAbmFtZRkAbWluZWNyYWZ0Omp1bmdsZV90cmFwZG9vcgQJAG5hbWVfaGFzaDP/TnM9wyCIAwoAbmV0d29ya19pZEy2fJoKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:acacia_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSQAQAACAQAbmFtZRkAbWluZWNyYWZ0OmFjYWNpYV90cmFwZG9vcgQJAG5hbWVfaGFzaMj8xi3vmEKOAwoAbmV0d29ya19pZOHj8E8KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:dark_oak_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSSAQAACAQAbmFtZRsAbWluZWNyYWZ0OmRhcmtfb2FrX3RyYXBkb29yBAkAbmFtZV9oYXNomB2GGJQ2aOMDCgBuZXR3b3JrX2lko5ZHTwoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:mangrove_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTvAgAACAQAbmFtZRsAbWluZWNyYWZ0Om1hbmdyb3ZlX3RyYXBkb29yBAkAbmFtZV9oYXNooV3kQsQUUmkDCgBuZXR3b3JrX2lkkF/mxAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:cherry_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQeAwAACAQAbmFtZRkAbWluZWNyYWZ0OmNoZXJyeV90cmFwZG9vcgQJAG5hbWVfaGFzaH/PefpfdHgtAwoAbmV0d29ya19pZOA7eNgKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:bamboo_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQHAwAACAQAbmFtZRkAbWluZWNyYWZ0OmJhbWJvb190cmFwZG9vcgQJAG5hbWVfaGFzaJrEOpsTwtKCAwoAbmV0d29ya19pZLvbPz8KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:iron_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSnAAAACAQAbmFtZRcAbWluZWNyYWZ0Omlyb25fdHJhcGRvb3IECQBuYW1lX2hhc2gwA+IumsEiGQMKAG5ldHdvcmtfaWTvSVl/CgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAEPAHVwc2lkZV9kb3duX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:crimson_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT1AQAACAQAbmFtZRoAbWluZWNyYWZ0OmNyaW1zb25fdHJhcGRvb3IECQBuYW1lX2hhc2jHXufTnwUkYgMKAG5ldHdvcmtfaWQLjMYVCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAEPAHVwc2lkZV9kb3duX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:warped_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT2AQAACAQAbmFtZRkAbWluZWNyYWZ0OndhcnBlZF90cmFwZG9vcgQJAG5hbWVfaGFzaA20wG/+vkd6AwoAbmV0d29ya19pZHKR/hYKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:iron_bars", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRlAAAACAQAbmFtZRMAbWluZWNyYWZ0Omlyb25fYmFycwQJAG5hbWVfaGFzaPuefWSNAe56AwoAbmV0d29ya19pZN2LB5IKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQUAAAACAQAbmFtZQ8AbWluZWNyYWZ0OmdsYXNzBAkAbmFtZV9oYXNowGJByfWff6gDCgBuZXR3b3JrX2lk0hdLNwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:white_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTxAAAACAQAbmFtZR0AbWluZWNyYWZ0OndoaXRlX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2iHubqoMbu9fAMKAG5ldHdvcmtfaWRndBrUCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:light_gray_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSnAwAACAQAbmFtZSIAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaKKa+LrRsHQhAwoAbmV0d29ya19pZEv2giYKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:gray_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSmAwAACAQAbmFtZRwAbWluZWNyYWZ0OmdyYXlfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaIETy7Y/HZREAwoAbmV0d29ya19pZDomVrUKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:black_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSuAwAACAQAbmFtZR0AbWluZWNyYWZ0OmJsYWNrX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2iV6BCwpfDMmwMKAG5ldHdvcmtfaWSV7doJCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:brown_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSrAwAACAQAbmFtZR0AbWluZWNyYWZ0OmJyb3duX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2igsEiq5np8JgMKAG5ldHdvcmtfaWRMzE/lCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:red_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWStAwAACAQAbmFtZRsAbWluZWNyYWZ0OnJlZF9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNoCa2J12/lQoIDCgBuZXR3b3JrX2lk283lWAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:orange_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSgAwAACAQAbmFtZR4AbWluZWNyYWZ0Om9yYW5nZV9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNozgjAuvzhxGsDCgBuZXR3b3JrX2lkW5CkhQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:yellow_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSjAwAACAQAbmFtZR4AbWluZWNyYWZ0OnllbGxvd19zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNo7EbHMd5WVugDCgBuZXR3b3JrX2lkkdDyXQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:lime_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSkAwAACAQAbmFtZRwAbWluZWNyYWZ0OmxpbWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaBtZA1nZtwcFAwoAbmV0d29ya19pZDxX85UKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:green_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSsAwAACAQAbmFtZR0AbWluZWNyYWZ0OmdyZWVuX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2h91ptDgbehWwMKAG5ldHdvcmtfaWTlDhnECgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:cyan_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAwAACAQAbmFtZRwAbWluZWNyYWZ0OmN5YW5fc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaBkIYQ8nQLqbAwoAbmV0d29ya19pZOL1lHsKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:light_blue_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSiAwAACAQAbmFtZSIAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaLt05n1G0fiSAwoAbmV0d29ya19pZNbwulIKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:blue_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSqAwAACAQAbmFtZRwAbWluZWNyYWZ0OmJsdWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaPhLocSfzduRAwoAbmV0d29ya19pZENsjFwKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:purple_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSpAwAACAQAbmFtZR4AbWluZWNyYWZ0OnB1cnBsZV9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNoJk0DhRO0szUDCgBuZXR3b3JrX2lkD98ZxgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:magenta_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAwAACAQAbmFtZR8AbWluZWNyYWZ0Om1hZ2VudGFfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaFEDeFiJj3zSAwoAbmV0d29ya19pZG+iFRoKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:pink_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAwAACAQAbmFtZRwAbWluZWNyYWZ0OnBpbmtfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaDijTX87ywxhAwoAbmV0d29ya19pZKdEricKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:tinted_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRNAgAACAQAbmFtZRYAbWluZWNyYWZ0OnRpbnRlZF9nbGFzcwQJAG5hbWVfaGFzaAFZWSamk6KdAwoAbmV0d29ya19pZGSvWX8KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRmAAAACAQAbmFtZRQAbWluZWNyYWZ0OmdsYXNzX3BhbmUECQBuYW1lX2hhc2gRSBHwNMQ4gQMKAG5ldHdvcmtfaWRGwixuCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:white_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSgAAAACAQAbmFtZSIAbWluZWNyYWZ0OndoaXRlX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaHgxQmgJVtRrAwoAbmV0d29ya19pZBEr/DYKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:light_gray_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSJAwAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNon0aQw9lNkSEDCgBuZXR3b3JrX2lk9dp5VgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:gray_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSIAwAACAQAbmFtZSEAbWluZWNyYWZ0OmdyYXlfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNors74IIw+2MMDCgBuZXR3b3JrX2lkmrGO5woGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:black_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSQAwAACAQAbmFtZSIAbWluZWNyYWZ0OmJsYWNrX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaOK/5ZRRd+M1AwoAbmV0d29ya19pZDv++oQKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:brown_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSNAwAACAQAbmFtZSIAbWluZWNyYWZ0OmJyb3duX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaLHeGJyRFTIWAwoAbmV0d29ya19pZMz9L0wKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:red_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSPAwAACAQAbmFtZSAAbWluZWNyYWZ0OnJlZF9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2gGr4x6JheAywMKAG5ldHdvcmtfaWQBjCTmCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:orange_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSCAwAACAQAbmFtZSMAbWluZWNyYWZ0Om9yYW5nZV9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2hbHxPD2gEbEAMKAG5ldHdvcmtfaWSt/7a5CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:yellow_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAwAACAQAbmFtZSMAbWluZWNyYWZ0OnllbGxvd19zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2g9tl4aOCyZBwMKAG5ldHdvcmtfaWTXRAS7CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:lime_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSGAwAACAQAbmFtZSEAbWluZWNyYWZ0OmxpbWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNo3CtUyLwoGegDCgBuZXR3b3JrX2lkYJDnggoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:green_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSOAwAACAQAbmFtZSIAbWluZWNyYWZ0OmdyZWVuX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaJo6YP7IMy9SAwoAbmV0d29ya19pZHOnixoKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:cyan_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSKAwAACAQAbmFtZSEAbWluZWNyYWZ0OmN5YW5fc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoti97c6QrbLQDCgBuZXR3b3JrX2lkUqFUeQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:light_blue_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAwAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNovDg/gQle104DCgBuZXR3b3JrX2lkFuy4MQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:blue_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSMAwAACAQAbmFtZSEAbWluZWNyYWZ0OmJsdWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoGc57tiexbQMDCgBuZXR3b3JrX2lk1eBLUAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:purple_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAwAACAQAbmFtZSMAbWluZWNyYWZ0OnB1cnBsZV9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2hDJHYdd0FdfQMKAG5ldHdvcmtfaWSNsdK5CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:magenta_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAwAACAQAbmFtZSQAbWluZWNyYWZ0Om1hZ2VudGFfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNo3pcOw5bs5XoDCgBuZXR3b3JrX2lkVbOR7AoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:pink_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSHAwAACAQAbmFtZSEAbWluZWNyYWZ0OnBpbmtfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoWRhSACMWgswDCgBuZXR3b3JrX2lkIR92xwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:ladder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRBAAAACAQAbmFtZRAAbWluZWNyYWZ0OmxhZGRlcgQJAG5hbWVfaGFzaKBhqheJVOz+AwoAbmV0d29ya19pZCgvzlsKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:scaffolding", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSkAQAACAQAbmFtZRUAbWluZWNyYWZ0OnNjYWZmb2xkaW5nBAkAbmFtZV9oYXNoYrkevrqcljwDCgBuZXR3b3JrX2lkD13mlAoGAHN0YXRlcwMJAHN0YWJpbGl0eQAAAAABDwBzdGFiaWxpdHlfY2hlY2sAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAAAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWTkNl0JCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQwAc21vb3RoX3N0b25lAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:stone_block_slab4", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkQJoxlgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNAUAc3RvbmUAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAAAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWRHh04KCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQsAY29iYmxlc3RvbmUAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkVRZB+woGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhEAbW9zc3lfY29iYmxlc3RvbmUAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:oak_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSeAAAACAQAbmFtZRIAbWluZWNyYWZ0Om9ha19zbGFiBAkAbmFtZV9oYXNoJp1Cp1M4jlwDCgBuZXR3b3JrX2lkZH6+owoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:spruce_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQjBAAACAQAbmFtZRUAbWluZWNyYWZ0OnNwcnVjZV9zbGFiBAkAbmFtZV9oYXNodQi70jB238cDCgBuZXR3b3JrX2lkrriOYQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:birch_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQkBAAACAQAbmFtZRQAbWluZWNyYWZ0OmJpcmNoX3NsYWIECQBuYW1lX2hhc2gZPpfMxoOsTAMKAG5ldHdvcmtfaWThR9jyCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:jungle_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQlBAAACAQAbmFtZRUAbWluZWNyYWZ0Omp1bmdsZV9zbGFiBAkAbmFtZV9oYXNo6gLs79NXak4DCgBuZXR3b3JrX2lk5ZiKgwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:acacia_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmBAAACAQAbmFtZRUAbWluZWNyYWZ0OmFjYWNpYV9zbGFiBAkAbmFtZV9oYXNomSdFmDnv4OUDCgBuZXR3b3JrX2lkHttaXAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:dark_oak_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQnBAAACAQAbmFtZRcAbWluZWNyYWZ0OmRhcmtfb2FrX3NsYWIECQBuYW1lX2hhc2hJjTohRFyhIQMKAG5ldHdvcmtfaWRMzDTyCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:mangrove_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWToAgAACAQAbmFtZRcAbWluZWNyYWZ0Om1hbmdyb3ZlX3NsYWIECQBuYW1lX2hhc2jYCcmhJPeNMwMKAG5ldHdvcmtfaWQx6U1yCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:cherry_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQaAwAACAQAbmFtZRUAbWluZWNyYWZ0OmNoZXJyeV9zbGFiBAkAbmFtZV9oYXNoTt0MmVn/mqoDCgBuZXR3b3JrX2lk2VVsZQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:bamboo_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQAAwAACAQAbmFtZRUAbWluZWNyYWZ0OmJhbWJvb19zbGFiBAkAbmFtZV9oYXNoo1xuFqINeLYDCgBuZXR3b3JrX2lkVC+0twoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:bamboo_mosaic_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQLAwAACAQAbmFtZRwAbWluZWNyYWZ0OmJhbWJvb19tb3NhaWNfc2xhYgQJAG5hbWVfaGFzaNbVRBZ/ChI3AwoAbmV0d29ya19pZOLZHFMKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAAAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWQSiInOCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQsAc3RvbmVfYnJpY2sAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:stone_block_slab4", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkoF89tgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNBEAbW9zc3lfc3RvbmVfYnJpY2sAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAAAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWSkoAE4CgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQkAc2FuZHN0b25lAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:stone_block_slab4", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkWfF7pgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNA0AY3V0X3NhbmRzdG9uZQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkbKRChAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAc21vb3RoX3NhbmRzdG9uZQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkBlrvqAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMg0AcmVkX3NhbmRzdG9uZQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:stone_block_slab4", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkRWFXuwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNBEAY3V0X3JlZF9zYW5kc3RvbmUAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkom8neQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxQAc21vb3RoX3JlZF9zYW5kc3RvbmUAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkd1ZaWgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMwcAZ3Jhbml0ZQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkISH4iwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxAAcG9saXNoZWRfZ3Jhbml0ZQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkqxEDMwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMwcAZGlvcml0ZQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkSYs86QoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxAAcG9saXNoZWRfZGlvcml0ZQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkq6BU6goGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMwgAYW5kZXNpdGUAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkTSXY8AoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxEAcG9saXNoZWRfYW5kZXNpdGUAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAAAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWQiYHKTCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQUAYnJpY2sAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAAAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWTk/0LfCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQwAbmV0aGVyX2JyaWNrAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lk/hXQ7AoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAcmVkX25ldGhlcl9icmljawADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkYJNxrwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMw8AZW5kX3N0b25lX2JyaWNrAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAAAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWRlj0/sCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQYAcXVhcnR6AAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:stone_block_slab4", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkMae+2goGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNA0Ac21vb3RoX3F1YXJ0egADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lk+kMHGAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMgYAcHVycHVyAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkKOSOMAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAcHJpc21hcmluZV9yb3VnaAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lk8igLCQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMg8AcHJpc21hcmluZV9kYXJrAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkSFbyEwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAcHJpc21hcmluZV9icmljawADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:crimson_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQHAgAACAQAbmFtZRYAbWluZWNyYWZ0OmNyaW1zb25fc2xhYgQJAG5hbWVfaGFzaKZ+EfP0ZYOZAwoAbmV0d29ya19pZAxRUWAKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:warped_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQIAgAACAQAbmFtZRUAbWluZWNyYWZ0OndhcnBlZF9zbGFiBAkAbmFtZV9oYXNo/AT0e/Z9W7UDCgBuZXR3b3JrX2lk1yq11AoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:blackstone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQZAgAACAQAbmFtZRkAbWluZWNyYWZ0OmJsYWNrc3RvbmVfc2xhYgQJAG5hbWVfaGFzaF/DD4ZUlNgtAwoAbmV0d29ya19pZGy1DjwKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:polished_blackstone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQkAgAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfc2xhYgQJAG5hbWVfaGFzaDYnuUs86EWfAwoAbmV0d29ya19pZJj2bXIKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:polished_blackstone_brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQbAgAACAQAbmFtZSgAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfc2xhYgQJAG5hbWVfaGFzaKySLqvHc4xXAwoAbmV0d29ya19pZOyWX94KBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRoAgAACAQAbmFtZRkAbWluZWNyYWZ0OmN1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaDsNpb2qs4iBAwoAbmV0d29ya19pZOTm2nsKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:exposed_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRpAgAACAQAbmFtZSEAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcl9zbGFiBAkAbmFtZV9oYXNoahQ5OwIQb7kDCgBuZXR3b3JrX2lkrUlZLwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:weathered_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRqAgAACAQAbmFtZSMAbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyX3NsYWIECQBuYW1lX2hhc2hBIuGIOVVXogMKAG5ldHdvcmtfaWQgnaDiCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:oxidized_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRrAgAACAQAbmFtZSIAbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaOptj9ycfpaDAwoAbmV0d29ya19pZMzFSRgKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:waxed_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRsAgAACAQAbmFtZR8AbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaAlx6DZOCTHzAwoAbmV0d29ya19pZFRBvDAKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:waxed_exposed_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRtAgAACAQAbmFtZScAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcl9zbGFiBAkAbmFtZV9oYXNo3KqS5OnhtRIDCgBuZXR3b3JrX2lkHTGcTgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:waxed_weathered_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRuAgAACAQAbmFtZSkAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyX3NsYWIECQBuYW1lX2hhc2gzZ1oX0HCFtwMKAG5ldHdvcmtfaWSgJR+XCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:waxed_oxidized_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTAAgAACAQAbmFtZSgAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaMjjTnLu1KcqAwoAbmV0d29ya19pZIxsnFYKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:cobbled_deepslate_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR7AgAACAQAbmFtZSAAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3NsYWIECQBuYW1lX2hhc2gwJIVWK1TM2QMKAG5ldHdvcmtfaWTYAoX5CgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:polished_deepslate_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR/AgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV9zbGFiBAkAbmFtZV9oYXNoC/Adiz8k6RYDCgBuZXR3b3JrX2lkuFYMAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:deepslate_tile_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3NsYWIECQBuYW1lX2hhc2hPydV6emzIXAMKAG5ldHdvcmtfaWQwlbFCCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:deepslate_brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSHAgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja19zbGFiBAkAbmFtZV9oYXNoSv62V7iw10UDCgBuZXR3b3JrX2lkWMoragoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:mud_brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTdAgAACAQAbmFtZRgAbWluZWNyYWZ0Om11ZF9icmlja19zbGFiBAkAbmFtZV9oYXNoq/tGBQWkv08DCgBuZXR3b3JrX2lkl4nnMwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:brick_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQtAAAACAQAbmFtZRUAbWluZWNyYWZ0OmJyaWNrX2Jsb2NrBAkAbmFtZV9oYXNo5Qc2E005S3oDCgBuZXR3b3JrX2lkqeGWRgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:chiseled_nether_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQtAgAACAQAbmFtZSAAbWluZWNyYWZ0OmNoaXNlbGVkX25ldGhlcl9icmlja3MECQBuYW1lX2hhc2g31SBPTcUK1QMKAG5ldHdvcmtfaWS8TJ+TCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:cracked_nether_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQuAgAACAQAbmFtZR8AbWluZWNyYWZ0OmNyYWNrZWRfbmV0aGVyX2JyaWNrcwQJAG5hbWVfaGFzaAdC6eKzXT5tAwoAbmV0d29ya19pZIUSejwKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:quartz_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQvAgAACAQAbmFtZRcAbWluZWNyYWZ0OnF1YXJ0el9icmlja3MECQBuYW1lX2hhc2jSZO590dd8sAMKAG5ldHdvcmtfaWSc5xCLCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:stonebrick", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAAAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWQ5kni1CgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQcAZGVmYXVsdAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:stonebrick", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAAAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWTDw813CgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQUAbW9zc3kAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:stonebrick", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAAAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWSTvQGECgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQcAY3JhY2tlZAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:stonebrick", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAAAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWQIM0OwCgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQgAY2hpc2VsZWQAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:end_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTOAAAACAQAbmFtZRQAbWluZWNyYWZ0OmVuZF9icmlja3MECQBuYW1lX2hhc2hIUFfxNLZaFgMKAG5ldHdvcmtfaWQ/vDihCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:prismarine", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAAAACAQAbmFtZRQAbWluZWNyYWZ0OnByaXNtYXJpbmUECQBuYW1lX2hhc2jcnQCHi9CspQMKAG5ldHdvcmtfaWSH021WCgYAc3RhdGVzCBUAcHJpc21hcmluZV9ibG9ja190eXBlBgBicmlja3MAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:polished_blackstone_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQRAgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tzBAkAbmFtZV9oYXNoIHgsgIdzKXcDCgBuZXR3b3JrX2lkUw9b3woGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:cracked_polished_blackstone_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQXAgAACAQAbmFtZSwAbWluZWNyYWZ0OmNyYWNrZWRfcG9saXNoZWRfYmxhY2tzdG9uZV9icmlja3MECQBuYW1lX2hhc2jQIO1GQDk80AMKAG5ldHdvcmtfaWQ3UlRYCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:gilded_blackstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAgAACAQAbmFtZRsAbWluZWNyYWZ0OmdpbGRlZF9ibGFja3N0b25lBAkAbmFtZV9oYXNoNoWt1ocG0HEDCgBuZXR3b3JrX2lktL8gUwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:chiseled_polished_blackstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQWAgAACAQAbmFtZSYAbWluZWNyYWZ0OmNoaXNlbGVkX3BvbGlzaGVkX2JsYWNrc3RvbmUECQBuYW1lX2hhc2gzFa+kEjCJgAMKAG5ldHdvcmtfaWR2NJX2CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:deepslate_tiles", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSCAgAACAQAbmFtZRkAbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlcwQJAG5hbWVfaGFzaGcLLx3NXAFvAwoAbmV0d29ya19pZI/G/xYKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:cracked_deepslate_tiles", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSYAgAACAQAbmFtZSEAbWluZWNyYWZ0OmNyYWNrZWRfZGVlcHNsYXRlX3RpbGVzBAkAbmFtZV9oYXNo9zWgkFuMM1QDCgBuZXR3b3JrX2lkGwY6OgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:deepslate_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSGAgAACAQAbmFtZRoAbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja3MECQBuYW1lX2hhc2gucvFmPdZxigMKAG5ldHdvcmtfaWSH4HDPCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:cracked_deepslate_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSZAgAACAQAbmFtZSIAbWluZWNyYWZ0OmNyYWNrZWRfZGVlcHNsYXRlX2JyaWNrcwQJAG5hbWVfaGFzaN40aqhh9WqHAwoAbmV0d29ya19pZO9GPBQKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:chiseled_deepslate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSKAgAACAQAbmFtZRwAbWluZWNyYWZ0OmNoaXNlbGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaEU7/uRG8HSBAwoAbmV0d29ya19pZEqmI0EKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:cobblestone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQEAAAACAQAbmFtZRUAbWluZWNyYWZ0OmNvYmJsZXN0b25lBAkAbmFtZV9oYXNoPoK7mGlSUz4DCgBuZXR3b3JrX2lkLm7RZwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:mossy_cobblestone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQwAAAACAQAbmFtZRsAbWluZWNyYWZ0Om1vc3N5X2NvYmJsZXN0b25lBAkAbmFtZV9oYXNoGJ67FCbkChMDCgBuZXR3b3JrX2lk/pYs1AoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:cobbled_deepslate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR6AgAACAQAbmFtZRsAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlBAkAbmFtZV9oYXNoLUz9Y/ywmLwDCgBuZXR3b3JrX2lkNwzZ+AoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:smooth_stone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AQAACAQAbmFtZRYAbWluZWNyYWZ0OnNtb290aF9zdG9uZQQJAG5hbWVfaGFzaMwf87/JaTNvAwoAbmV0d29ya19pZLkZICEKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAAAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZB2wApMKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGUHAGRlZmF1bHQAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAAAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZB7E+eQKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGULAGhlaXJvZ2x5cGhzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAAAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZFQnDaEKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGUDAGN1dAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAAAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZPO4A3IKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGUGAHNtb290aAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:red_sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSzAAAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWRhNYiFCgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlBwBkZWZhdWx0AAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:red_sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSzAAAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWTqXJr1CgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlCwBoZWlyb2dseXBocwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:red_sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSzAAAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWTQRGkFCgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlAwBjdXQAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:red_sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSzAAAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWTvAHWDCgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlBgBzbW9vdGgAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:coal_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWStAAAACAQAbmFtZRQAbWluZWNyYWZ0OmNvYWxfYmxvY2sECQBuYW1lX2hhc2jH8QQP3t5PiAMKAG5ldHdvcmtfaWRo+sR+CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:dried_kelp_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSKAQAACAQAbmFtZRoAbWluZWNyYWZ0OmRyaWVkX2tlbHBfYmxvY2sECQBuYW1lX2hhc2iRoucexkrl8wMKAG5ldHdvcmtfaWQQCCrvCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:gold_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQpAAAACAQAbmFtZRQAbWluZWNyYWZ0OmdvbGRfYmxvY2sECQBuYW1lX2hhc2iYLshvjtXzFwMKAG5ldHdvcmtfaWTDJGBcCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:iron_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQqAAAACAQAbmFtZRQAbWluZWNyYWZ0Omlyb25fYmxvY2sECQBuYW1lX2hhc2jYINmJQbvV/gMKAG5ldHdvcmtfaWRf7AbICgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:copper_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRTAgAACAQAbmFtZRYAbWluZWNyYWZ0OmNvcHBlcl9ibG9jawQJAG5hbWVfaGFzaDVxnehsGaZ1AwoAbmV0d29ya19pZIiUodwKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:exposed_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRUAgAACAQAbmFtZRgAbWluZWNyYWZ0OmV4cG9zZWRfY29wcGVyBAkAbmFtZV9oYXNoQH3Fukmu3CEDCgBuZXR3b3JrX2lk72jFIwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:weathered_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRVAgAACAQAbmFtZRoAbWluZWNyYWZ0OndlYXRoZXJlZF9jb3BwZXIECQBuYW1lX2hhc2hJCQXbvobv+gMKAG5ldHdvcmtfaWQwM0lJCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:oxidized_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRWAgAACAQAbmFtZRkAbWluZWNyYWZ0Om94aWRpemVkX2NvcHBlcgQJAG5hbWVfaGFzaMDtJqR0G5Y7AwoAbmV0d29ya19pZGjN8bUKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:waxed_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRXAgAACAQAbmFtZRYAbWluZWNyYWZ0OndheGVkX2NvcHBlcgQJAG5hbWVfaGFzaPF+FG6Eh5fsAwoAbmV0d29ya19pZIjtz/0KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:waxed_exposed_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRYAgAACAQAbmFtZR4AbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY29wcGVyBAkAbmFtZV9oYXNoig8IOc+SCikDCgBuZXR3b3JrX2lklz8yWQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:waxed_weathered_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRZAgAACAQAbmFtZSAAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jb3BwZXIECQBuYW1lX2hhc2gjtPq8MOdvKgMKAG5ldHdvcmtfaWSQ9Ln9CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:waxed_oxidized_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS9AgAACAQAbmFtZR8AbWluZWNyYWZ0OndheGVkX294aWRpemVkX2NvcHBlcgQJAG5hbWVfaGFzaMaORhsO+LzjAwoAbmV0d29ya19pZJhGfLEKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRaAgAACAQAbmFtZRQAbWluZWNyYWZ0OmN1dF9jb3BwZXIECQBuYW1lX2hhc2hAfN3NGax3eAMKAG5ldHdvcmtfaWTnFBtYCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:exposed_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRbAgAACAQAbmFtZRwAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcgQJAG5hbWVfaGFzaA85G3yv/w6pAwoAbmV0d29ya19pZMQhr0QKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:weathered_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRcAgAACAQAbmFtZR4AbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyBAkAbmFtZV9oYXNoVgRV0fBaz88DCgBuZXR3b3JrX2lk/0cYugoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:oxidized_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRdAgAACAQAbmFtZR0AbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2iP8WmFWOkriwMKAG5ldHdvcmtfaWQPdce7CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:waxed_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWReAgAACAQAbmFtZRoAbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2jumiwOZIqv2AMKAG5ldHdvcmtfaWQvuxx9CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:waxed_exposed_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRfAgAACAQAbmFtZSIAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcgQJAG5hbWVfaGFzaPE/OfK6IoVMAwoAbmV0d29ya19pZHy5HkcKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:waxed_weathered_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRgAgAACAQAbmFtZSQAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyBAkAbmFtZV9oYXNoCA1xDp11bnwDCgBuZXR3b3JrX2lkDyEDVQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:waxed_oxidized_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS+AgAACAQAbmFtZSMAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2i1pZAsZYHLDAMKAG5ldHdvcmtfaWQ/wSkCCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:emerald_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAAAACAQAbmFtZRcAbWluZWNyYWZ0OmVtZXJhbGRfYmxvY2sECQBuYW1lX2hhc2hK6QunqJznNAMKAG5ldHdvcmtfaWRk5+otCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:diamond_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ5AAAACAQAbmFtZRcAbWluZWNyYWZ0OmRpYW1vbmRfYmxvY2sECQBuYW1lX2hhc2iGKrxuvkytFQMKAG5ldHdvcmtfaWQQeQZXCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:lapis_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQWAAAACAQAbmFtZRUAbWluZWNyYWZ0OmxhcGlzX2Jsb2NrBAkAbmFtZV9oYXNoDZ44xdb2zVoDCgBuZXR3b3JrX2lktVy0BAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:raw_iron_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTCAgAACAQAbmFtZRgAbWluZWNyYWZ0OnJhd19pcm9uX2Jsb2NrBAkAbmFtZV9oYXNo9XyzNIQXxvwDCgBuZXR3b3JrX2lknms1QAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:raw_copper_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTDAgAACAQAbmFtZRoAbWluZWNyYWZ0OnJhd19jb3BwZXJfYmxvY2sECQBuYW1lX2hhc2hw1KG0TNUGgwMKAG5ldHdvcmtfaWS1vGo/CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:raw_gold_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTEAgAACAQAbmFtZRgAbWluZWNyYWZ0OnJhd19nb2xkX2Jsb2NrBAkAbmFtZV9oYXNo6YuwuLwfOBwDCgBuZXR3b3JrX2lkLiQ5gQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:quartz_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAAAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZEupC1AKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQcAZGVmYXVsdAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:quartz_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAAAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZM97+l0KBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQUAbGluZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:quartz_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAAAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZCbTfssKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQgAY2hpc2VsZWQICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:quartz_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAAAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZJss8V0KBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQYAc21vb3RoCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:prismarine", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAAAACAQAbmFtZRQAbWluZWNyYWZ0OnByaXNtYXJpbmUECQBuYW1lX2hhc2jcnQCHi9CspQMKAG5ldHdvcmtfaWRFIsoGCgYAc3RhdGVzCBUAcHJpc21hcmluZV9ibG9ja190eXBlBwBkZWZhdWx0AAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:prismarine", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAAAACAQAbmFtZRQAbWluZWNyYWZ0OnByaXNtYXJpbmUECQBuYW1lX2hhc2jcnQCHi9CspQMKAG5ldHdvcmtfaWTDNWOvCgYAc3RhdGVzCBUAcHJpc21hcmluZV9ibG9ja190eXBlBABkYXJrAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:slime", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAAAACAQAbmFtZQ8AbWluZWNyYWZ0OnNsaW1lBAkAbmFtZV9oYXNoHJiEEJx+JlkDCgBuZXR3b3JrX2lkfgfVzAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:honey_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTbAQAACAQAbmFtZRUAbWluZWNyYWZ0OmhvbmV5X2Jsb2NrBAkAbmFtZV9oYXNo9zLYSUlelywDCgBuZXR3b3JrX2lko+dyWgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:honeycomb_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTcAQAACAQAbmFtZRkAbWluZWNyYWZ0OmhvbmV5Y29tYl9ibG9jawQJAG5hbWVfaGFzaASIPuOCYd1oAwoAbmV0d29ya19pZKys4n4KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:hay_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSqAAAACAQAbmFtZRMAbWluZWNyYWZ0OmhheV9ibG9jawQJAG5hbWVfaGFzaIB2VxKxX8EpAwoAbmV0d29ya19pZKuQSloKBgBzdGF0ZXMDCgBkZXByZWNhdGVkAAAAAAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:bone_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTYAAAACAQAbmFtZRQAbWluZWNyYWZ0OmJvbmVfYmxvY2sECQBuYW1lX2hhc2i4ZX576W9AWgMKAG5ldHdvcmtfaWTWGacQCgYAc3RhdGVzAwoAZGVwcmVjYXRlZAAAAAAICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:nether_brick", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRwAAAACAQAbmFtZRYAbWluZWNyYWZ0Om5ldGhlcl9icmljawQJAG5hbWVfaGFzaMxcRiheU+nXAwoAbmV0d29ya19pZMkmzloKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:red_nether_brick", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTXAAAACAQAbmFtZRoAbWluZWNyYWZ0OnJlZF9uZXRoZXJfYnJpY2sECQBuYW1lX2hhc2j8pRO4LfoECAMKAG5ldHdvcmtfaWRpdF0YCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:netherite_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQNAgAACAQAbmFtZRkAbWluZWNyYWZ0Om5ldGhlcml0ZV9ibG9jawQJAG5hbWVfaGFzaMghh6Zib/ZKAwoAbmV0d29ya19pZIz0mq0KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:lodestone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTdAQAACAQAbmFtZRMAbWluZWNyYWZ0OmxvZGVzdG9uZQQJAG5hbWVfaGFzaJ2gmHOTlXv8AwoAbmV0d29ya19pZEfgB4wKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:white_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQjAAAACAQAbmFtZRQAbWluZWNyYWZ0OndoaXRlX3dvb2wECQBuYW1lX2hhc2jRWB7vaIEDiQMKAG5ldHdvcmtfaWSO8paQCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:light_gray_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQnAwAACAQAbmFtZRkAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfd29vbAQJAG5hbWVfaGFzaOpdQ1a2v4b3AwoAbmV0d29ya19pZIqZCYEKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:gray_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQoAwAACAQAbmFtZRMAbWluZWNyYWZ0OmdyYXlfd29vbAQJAG5hbWVfaGFzaLsc1Lp1xdIOAwoAbmV0d29ya19pZFUs+HgKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:black_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQpAwAACAQAbmFtZRQAbWluZWNyYWZ0OmJsYWNrX3dvb2wECQBuYW1lX2hhc2hP2HC6o0X4HAMKAG5ldHdvcmtfaWRUbORcCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:brown_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQqAwAACAQAbmFtZRQAbWluZWNyYWZ0OmJyb3duX3dvb2wECQBuYW1lX2hhc2ig5IW89PrREwMKAG5ldHdvcmtfaWRjT9j8CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:red_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQrAwAACAQAbmFtZRIAbWluZWNyYWZ0OnJlZF93b29sBAkAbmFtZV9oYXNoY4TBDq+mFgUDCgBuZXR3b3JrX2lktn9lcAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:orange_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAwAACAQAbmFtZRUAbWluZWNyYWZ0Om9yYW5nZV93b29sBAkAbmFtZV9oYXNoFstfrTZfSCgDCgBuZXR3b3JrX2lk+rqywwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:yellow_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQtAwAACAQAbmFtZRUAbWluZWNyYWZ0OnllbGxvd193b29sBAkAbmFtZV9oYXNoTFyus2RHegcDCgBuZXR3b3JrX2lkkKBhXAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:lime_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQuAwAACAQAbmFtZRMAbWluZWNyYWZ0OmxpbWVfd29vbAQJAG5hbWVfaGFzaNVnnzKiMxmeAwoAbmV0d29ya19pZG9b32kKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:green_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQvAwAACAQAbmFtZRQAbWluZWNyYWZ0OmdyZWVuX3dvb2wECQBuYW1lX2hhc2i3mElRYHIcSQMKAG5ldHdvcmtfaWSssprwCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:cyan_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQwAwAACAQAbmFtZRMAbWluZWNyYWZ0OmN5YW5fd29vbAQJAG5hbWVfaGFzaBNDfvHn8dqFAwoAbmV0d29ya19pZK0hAbgKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:light_blue_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQxAwAACAQAbmFtZRkAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfd29vbAQJAG5hbWVfaGFzaLWFAUfyxFPNAwoAbmV0d29ya19pZL2oEugKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:blue_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQyAwAACAQAbmFtZRMAbWluZWNyYWZ0OmJsdWVfd29vbAQJAG5hbWVfaGFzaLjHyxxbTWCLAwoAbmV0d29ya19pZPaLdFQKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:purple_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQzAwAACAQAbmFtZRUAbWluZWNyYWZ0OnB1cnBsZV93b29sBAkAbmFtZV9oYXNojvFtqzjAf/4DCgBuZXR3b3JrX2lklqASNQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:magenta_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ0AwAACAQAbmFtZRYAbWluZWNyYWZ0Om1hZ2VudGFfd29vbAQJAG5hbWVfaGFzaGuOHvf+Pd4yAwoAbmV0d29ya19pZI4UoDQKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:pink_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ1AwAACAQAbmFtZRMAbWluZWNyYWZ0OnBpbmtfd29vbAQJAG5hbWVfaGFzaPiVA2pFeoFLAwoAbmV0d29ya19pZOZRO6oKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:white_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSrAAAACAQAbmFtZRYAbWluZWNyYWZ0OndoaXRlX2NhcnBldAQJAG5hbWVfaGFzaNeMHTI1fWPXAwoAbmV0d29ya19pZEahDFcKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:light_gray_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRbAwAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY2FycGV0BAkAbmFtZV9oYXNoHPw6ArBAsP0DCgBuZXR3b3JrX2lkQoAeUAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:gray_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRaAwAACAQAbmFtZRUAbWluZWNyYWZ0OmdyYXlfY2FycGV0BAkAbmFtZV9oYXNoZVR0OI+1VRADCgBuZXR3b3JrX2lkETF4WwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:black_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJsYWNrX2NhcnBldAQJAG5hbWVfaGFzaOk7LP9NptyhAwoAbmV0d29ya19pZFjmXtIKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:brown_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRfAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJyb3duX2NhcnBldAQJAG5hbWVfaGFzaNaXFyOsAvIvAwoAbmV0d29ya19pZHPjFuoKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:red_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAwAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9jYXJwZXQECQBuYW1lX2hhc2i9eSKBf6SO3wMKAG5ldHdvcmtfaWQuhI/KCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:orange_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRUAwAACAQAbmFtZRcAbWluZWNyYWZ0Om9yYW5nZV9jYXJwZXQECQBuYW1lX2hhc2hIUkO4HlAdygMKAG5ldHdvcmtfaWSyKV9OCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:yellow_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRXAwAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19jYXJwZXQECQBuYW1lX2hhc2hSDKX3scCamwMKAG5ldHdvcmtfaWT8nq+ECgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:lime_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRYAwAACAQAbmFtZRUAbWluZWNyYWZ0OmxpbWVfY2FycGV0BAkAbmFtZV9oYXNo+6KFOpzsib4DCgBuZXR3b3JrX2lkT+DS4woGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:green_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRgAwAACAQAbmFtZRYAbWluZWNyYWZ0OmdyZWVuX2NhcnBldAQJAG5hbWVfaGFzaCHPMP9ltqFJAwoAbmV0d29ya19pZBgwAvAKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:cyan_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRcAwAACAQAbmFtZRUAbWluZWNyYWZ0OmN5YW5fY2FycGV0BAkAbmFtZV9oYXNobXf62dQBJj8DCgBuZXR3b3JrX2lkKVppLgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:light_blue_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRWAwAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY2FycGV0BAkAbmFtZV9oYXNo20l4oktdZ3sDCgBuZXR3b3JrX2lkjdeMiwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:blue_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWReAwAACAQAbmFtZRUAbWluZWNyYWZ0OmJsdWVfY2FycGV0BAkAbmFtZV9oYXNo3p3lsW0eQwsDCgBuZXR3b3JrX2lkAovdPQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:purple_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRdAwAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnBsZV9jYXJwZXQECQBuYW1lX2hhc2jwIA9pW/qp7QMKAG5ldHdvcmtfaWTqJqhjCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:magenta_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRVAwAACAQAbmFtZRgAbWluZWNyYWZ0Om1hZ2VudGFfY2FycGV0BAkAbmFtZV9oYXNoFXT36YNNZhMDCgBuZXR3b3JrX2lk+tqsGAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:pink_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRZAwAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfY2FycGV0BAkAbmFtZV9oYXNoHll72oqk+OoDCgBuZXR3b3JrX2lkrnBYDwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:white_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTtAAAACAQAbmFtZR8AbWluZWNyYWZ0OndoaXRlX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaFUk9iXVjwV8AwoAbmV0d29ya19pZJPZY8AKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:light_gray_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTLAwAACAQAbmFtZSQAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNo7EUk30hmUtYDCgBuZXR3b3JrX2lkh8jVIwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:gray_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTKAwAACAQAbmFtZR4AbWluZWNyYWZ0OmdyYXlfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoW77af6WihdwDCgBuZXR3b3JrX2lkSsqC1woGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:black_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTSAwAACAQAbmFtZR8AbWluZWNyYWZ0OmJsYWNrX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaAfWYp0xtgcfAwoAbmV0d29ya19pZMWTC8EKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:brown_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTPAwAACAQAbmFtZR8AbWluZWNyYWZ0OmJyb3duX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaB74EeiLO46XAwoAbmV0d29ya19pZEDHKqwKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:red_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTRAwAACAQAbmFtZR0AbWluZWNyYWZ0OnJlZF9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2gjFut6Z/VH1gMKAG5ldHdvcmtfaWSvcmwYCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:orange_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTEAwAACAQAbmFtZSAAbWluZWNyYWZ0Om9yYW5nZV9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2gADDj2IJiw+gMKAG5ldHdvcmtfaWTHph0FCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:yellow_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTHAwAACAQAbmFtZSAAbWluZWNyYWZ0OnllbGxvd19jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2iy6qKNn3ob5wMKAG5ldHdvcmtfaWQZAI39CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:lime_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTIAwAACAQAbmFtZR4AbWluZWNyYWZ0OmxpbWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNo4dYIPslbXPUDCgBuZXR3b3JrX2lk2O8X0AoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:green_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTQAwAACAQAbmFtZR8AbWluZWNyYWZ0OmdyZWVuX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaM/c9x2aJh3HAwoAbmV0d29ya19pZA0VfBMKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:cyan_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTMAwAACAQAbmFtZR4AbWluZWNyYWZ0OmN5YW5fY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNok+xKAe7XXjoDCgBuZXR3b3JrX2lkmkn6uwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:light_blue_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTGAwAACAQAbmFtZSQAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNogScpIQceyAEDCgBuZXR3b3JrX2lkOmVSbgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:blue_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTOAwAACAQAbmFtZR4AbWluZWNyYWZ0OmJsdWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoFp7mmeL86r0DCgBuZXR3b3JrX2lkS3b3RQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:purple_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTNAwAACAQAbmFtZSAAbWluZWNyYWZ0OnB1cnBsZV9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2iYcVU04hoStwMKAG5ldHdvcmtfaWQXimEjCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:magenta_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTFAwAACAQAbmFtZSEAbWluZWNyYWZ0Om1hZ2VudGFfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoy/70q6VPsWgDCgBuZXR3b3JrX2lkf9mxQwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:pink_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAwAACAQAbmFtZR4AbWluZWNyYWZ0OnBpbmtfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoVikSAf8DwV0DCgBuZXR3b3JrX2lku2MivwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:white_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTsAAAACAQAbmFtZRgAbWluZWNyYWZ0OndoaXRlX2NvbmNyZXRlBAkAbmFtZV9oYXNo6zAp7lsLlvkDCgBuZXR3b3JrX2lk3MAYQAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:light_gray_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR6AwAACAQAbmFtZR0AbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY29uY3JldGUECQBuYW1lX2hhc2hEtet5wuDIKAMKAG5ldHdvcmtfaWQISs02CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:gray_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR5AwAACAQAbmFtZRcAbWluZWNyYWZ0OmdyYXlfY29uY3JldGUECQBuYW1lX2hhc2j92INnb0a83AMKAG5ldHdvcmtfaWQj8RHwCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:black_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSBAwAACAQAbmFtZRgAbWluZWNyYWZ0OmJsYWNrX2NvbmNyZXRlBAkAbmFtZV9oYXNo2X7NDIQmZ70DCgBuZXR3b3JrX2lk2uiVDQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:brown_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR+AwAACAQAbmFtZRgAbWluZWNyYWZ0OmJyb3duX2NvbmNyZXRlBAkAbmFtZV9oYXNoeka02BwXf6oDCgBuZXR3b3JrX2lkYf+xDQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:red_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSAAwAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZF9jb25jcmV0ZQQJAG5hbWVfaGFzaPWmNowLGubqAwoAbmV0d29ya19pZKwyx58KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:orange_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRzAwAACAQAbmFtZRkAbWluZWNyYWZ0Om9yYW5nZV9jb25jcmV0ZQQJAG5hbWVfaGFzaAgE8XmaAi6+AwoAbmV0d29ya19pZMDQNz8KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:yellow_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR2AwAACAQAbmFtZRkAbWluZWNyYWZ0OnllbGxvd19jb25jcmV0ZQQJAG5hbWVfaGFzaE6ONfJPBd0+AwoAbmV0d29ya19pZMarutwKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:lime_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR3AwAACAQAbmFtZRcAbWluZWNyYWZ0OmxpbWVfY29uY3JldGUECQBuYW1lX2hhc2gnd8JW6wmJcAMKAG5ldHdvcmtfaWTd47aoCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:green_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR/AwAACAQAbmFtZRgAbWluZWNyYWZ0OmdyZWVuX2NvbmNyZXRlBAkAbmFtZV9oYXNokbFxRKchQZkDCgBuZXR3b3JrX2lkmhZWUgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:cyan_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR7AwAACAQAbmFtZRcAbWluZWNyYWZ0OmN5YW5fY29uY3JldGUECQBuYW1lX2hhc2hFRrWJ33qj1wMKAG5ldHdvcmtfaWQbi5b8CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:light_blue_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR1AwAACAQAbmFtZR0AbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY29uY3JldGUECQBuYW1lX2hhc2gHAe0kl0SE4AMKAG5ldHdvcmtfaWRL/GbSCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:blue_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR9AwAACAQAbmFtZRcAbWluZWNyYWZ0OmJsdWVfY29uY3JldGUECQBuYW1lX2hhc2hiay301nnj1wMKAG5ldHdvcmtfaWRMvFXNCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:purple_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR8AwAACAQAbmFtZRkAbWluZWNyYWZ0OnB1cnBsZV9jb25jcmV0ZQQJAG5hbWVfaGFzaHBHflsPIwdXAwoAbmV0d29ya19pZCyKA5gKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:magenta_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR0AwAACAQAbmFtZRoAbWluZWNyYWZ0Om1hZ2VudGFfY29uY3JldGUECQBuYW1lX2hhc2gN7LuB/OvdZAMKAG5ldHdvcmtfaWTc6ZOdCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:pink_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR4AwAACAQAbmFtZRcAbWluZWNyYWZ0OnBpbmtfY29uY3JldGUECQBuYW1lX2hhc2ii2G5F0u3SOAMKAG5ldHdvcmtfaWSszGgrCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:clay", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRSAAAACAQAbmFtZQ4AbWluZWNyYWZ0OmNsYXkECQBuYW1lX2hhc2j/S6sKXRcpzwMKAG5ldHdvcmtfaWRmsb8nCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:hardened_clay", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSsAAAACAQAbmFtZRcAbWluZWNyYWZ0OmhhcmRlbmVkX2NsYXkECQBuYW1lX2hhc2jrnRwCJ0krJAMKAG5ldHdvcmtfaWRBCOrrCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:white_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSfAAAACAQAbmFtZRoAbWluZWNyYWZ0OndoaXRlX3RlcnJhY290dGEECQBuYW1lX2hhc2j3RSdgmnAIewMKAG5ldHdvcmtfaWSimKw+CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:light_gray_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTaAwAACAQAbmFtZR8AbWluZWNyYWZ0OmxpZ2h0X2dyYXlfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAz1Ri3wIxomAwoAbmV0d29ya19pZH5qgOcKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:gray_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTZAwAACAQAbmFtZRkAbWluZWNyYWZ0OmdyYXlfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAXdSLAaNZ9vAwoAbmV0d29ya19pZM1QDV0KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:black_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWThAwAACAQAbmFtZRoAbWluZWNyYWZ0OmJsYWNrX3RlcnJhY290dGEECQBuYW1lX2hhc2jxssdv5vlbpgMKAG5ldHdvcmtfaWRE3Ru/CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:brown_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTeAwAACAQAbmFtZRoAbWluZWNyYWZ0OmJyb3duX3RlcnJhY290dGEECQBuYW1lX2hhc2gG4kPenmOF9gMKAG5ldHdvcmtfaWQ/i0iNCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:red_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTgAwAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNo7fX56HXFejEDCgBuZXR3b3JrX2lk8tTF8QoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:orange_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTTAwAACAQAbmFtZRsAbWluZWNyYWZ0Om9yYW5nZV90ZXJyYWNvdHRhBAkAbmFtZV9oYXNo0Hjmql3sruMDCgBuZXR3b3JrX2lklmqmkAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:yellow_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTWAwAACAQAbmFtZRsAbWluZWNyYWZ0OnllbGxvd190ZXJyYWNvdHRhBAkAbmFtZV9oYXNoqkyKKrmA3VcDCgBuZXR3b3JrX2lkaM/orAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:lime_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTXAwAACAQAbmFtZRkAbWluZWNyYWZ0OmxpbWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaANjADFOF9v7AwoAbmV0d29ya19pZJt0XsgKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:green_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTfAwAACAQAbmFtZRoAbWluZWNyYWZ0OmdyZWVuX3RlcnJhY290dGEECQBuYW1lX2hhc2j5Ybq36yYwRQMKAG5ldHdvcmtfaWQ8kGdHCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:cyan_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTbAwAACAQAbmFtZRkAbWluZWNyYWZ0OmN5YW5fdGVycmFjb3R0YQQJAG5hbWVfaGFzaN09COzMuHwAAwoAbmV0d29ya19pZIWPCzoKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:light_blue_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTVAwAACAQAbmFtZR8AbWluZWNyYWZ0OmxpZ2h0X2JsdWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaOMytez7cOZiAwoAbmV0d29ya19pZFHK1UsKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:blue_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTdAwAACAQAbmFtZRkAbWluZWNyYWZ0OmJsdWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaF6inyTK5RpAAwoAbmV0d29ya19pZF5mVZIKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:purple_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTcAwAACAQAbmFtZRsAbWluZWNyYWZ0OnB1cnBsZV90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoKF7YG61yTbEDCgBuZXR3b3JrX2lkhtRDlwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:magenta_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTUAwAACAQAbmFtZRwAbWluZWNyYWZ0Om1hZ2VudGFfdGVycmFjb3R0YQQJAG5hbWVfaGFzaLWvtpAVtztyAwoAbmV0d29ya19pZN5SoakKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:pink_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTYAwAACAQAbmFtZRkAbWluZWNyYWZ0OnBpbmtfdGVycmFjb3R0YQQJAG5hbWVfaGFzaJ7mzvyzSQZTAwoAbmV0d29ya19pZDJWe4YKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:white_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTcAAAACAQAbmFtZSEAbWluZWNyYWZ0OndoaXRlX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoiVzCdoHAJo0DCgBuZXR3b3JrX2lkIlj9AAoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:silver_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTkAAAACAQAbmFtZSIAbWluZWNyYWZ0OnNpbHZlcl9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAVsA0CnhzA4AwoAbmV0d29ya19pZPnxtJEKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:gray_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTjAAAACAQAbmFtZSAAbWluZWNyYWZ0OmdyYXlfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2jvLZt9u/lF/AMKAG5ldHdvcmtfaWQVU8eFCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:black_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTrAAAACAQAbmFtZSEAbWluZWNyYWZ0OmJsYWNrX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoe8I4xAXbO5UDCgBuZXR3b3JrX2lk2Icb9AoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:brown_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWToAAAACAQAbmFtZSEAbWluZWNyYWZ0OmJyb3duX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoSiNZOobbpjoDCgBuZXR3b3JrX2lkJy0jwgoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:red_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTqAAAACAQAbmFtZR8AbWluZWNyYWZ0OnJlZF9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaBdWFGLmCLFVAwoAbmV0d29ya19pZMYBJSEKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:orange_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTdAAAACAQAbmFtZSIAbWluZWNyYWZ0Om9yYW5nZV9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaMyJMrnPr7szAwoAbmV0d29ya19pZN6+7TUKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:yellow_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTgAAAACAQAbmFtZSIAbWluZWNyYWZ0OnllbGxvd19nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaN6NaIhf6m0uAwoAbmV0d29ya19pZKRHXeoKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:lime_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWThAAAACAQAbmFtZSAAbWluZWNyYWZ0OmxpbWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2iF3E68/rB2EAMKAG5ldHdvcmtfaWSP7qQWCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:green_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTpAAAACAQAbmFtZSEAbWluZWNyYWZ0OmdyZWVuX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNow5mo8aQDFboDCgBuZXR3b3JrX2lkoF11kgoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:cyan_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTlAAAACAQAbmFtZSAAbWluZWNyYWZ0OmN5YW5fZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2gnNB+cCFRJhwMKAG5ldHdvcmtfaWT9buMtCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:light_blue_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTfAAAACAQAbmFtZSYAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2gladnCDBKCigMKAG5ldHdvcmtfaWS5CszFCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:blue_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTnAAAACAQAbmFtZSAAbWluZWNyYWZ0OmJsdWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2giOZK+2nB1igMKAG5ldHdvcmtfaWR+e22CCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:purple_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTbAAAACAQAbmFtZSIAbWluZWNyYWZ0OnB1cnBsZV9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaIQU03txeAfHAwoAbmV0d29ya19pZLKbSE4KBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:magenta_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTeAAAACAQAbmFtZSMAbWluZWNyYWZ0Om1hZ2VudGFfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2i/SNqDJbfjMgMKAG5ldHdvcmtfaWQKf9UvCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:pink_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTiAAAACAQAbmFtZSAAbWluZWNyYWZ0OnBpbmtfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2hik8DVt4g+twMKAG5ldHdvcmtfaWTKzav2CgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:purpur_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAAAACAQAbmFtZRYAbWluZWNyYWZ0OnB1cnB1cl9ibG9jawQJAG5hbWVfaGFzaAgLwnUZGlzsAwoAbmV0d29ya19pZLD8ox4KBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQcAZGVmYXVsdAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:purpur_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAAAACAQAbmFtZRYAbWluZWNyYWZ0OnB1cnB1cl9ibG9jawQJAG5hbWVfaGFzaAgLwnUZGlzsAwoAbmV0d29ya19pZPSAFFsKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQUAbGluZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:packed_mud", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTcAgAACAQAbmFtZRQAbWluZWNyYWZ0OnBhY2tlZF9tdWQECQBuYW1lX2hhc2gHOMa121h4FgMKAG5ldHdvcmtfaWTUb6LyCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:mud_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTaAgAACAQAbmFtZRQAbWluZWNyYWZ0Om11ZF9icmlja3MECQBuYW1lX2hhc2iDL/SVl/PewQMKAG5ldHdvcmtfaWSkBjaDCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:nether_wart_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTWAAAACAQAbmFtZRsAbWluZWNyYWZ0Om5ldGhlcl93YXJ0X2Jsb2NrBAkAbmFtZV9oYXNo9XGS4GNnlV4DCgBuZXR3b3JrX2lkh3apIgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:warped_wart_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTiAQAACAQAbmFtZRsAbWluZWNyYWZ0OndhcnBlZF93YXJ0X2Jsb2NrBAkAbmFtZV9oYXNo9IqDS9yUPJoDCgBuZXR3b3JrX2lkMpKAbAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:shroomlight", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTlAQAACAQAbmFtZRUAbWluZWNyYWZ0OnNocm9vbWxpZ2h0BAkAbmFtZV9oYXNoZHCHcHX/HYADCgBuZXR3b3JrX2lkLG2JiwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:crimson_nylium", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTnAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fbnlsaXVtBAkAbmFtZV9oYXNoOr6DJYW2bFYDCgBuZXR3b3JrX2lkuWpRDgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:warped_nylium", + "block_state_b64": "CgAAAwgAYmxvY2tfaWToAQAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9ueWxpdW0ECQBuYW1lX2hhc2g0Zf89cfr3rwMKAG5ldHdvcmtfaWSu/kekCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:netherrack", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRXAAAACAQAbmFtZRQAbWluZWNyYWZ0Om5ldGhlcnJhY2sECQBuYW1lX2hhc2i/r5ZyRsvPyQMKAG5ldHdvcmtfaWTAiTOACgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:basalt", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTpAQAACAQAbmFtZRAAbWluZWNyYWZ0OmJhc2FsdAQJAG5hbWVfaGFzaH+UQO2yWodiAwoAbmV0d29ya19pZBPNSV4KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:polished_basalt", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTqAQAACAQAbmFtZRkAbWluZWNyYWZ0OnBvbGlzaGVkX2Jhc2FsdAQJAG5hbWVfaGFzaMS+L0gMnRcBAwoAbmV0d29ya19pZF+/mHwKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:smooth_basalt", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR4AgAACAQAbmFtZRcAbWluZWNyYWZ0OnNtb290aF9iYXNhbHQECQBuYW1lX2hhc2jKPUdz89kuNAMKAG5ldHdvcmtfaWTkb/oVCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:soul_soil", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTrAQAACAQAbmFtZRMAbWluZWNyYWZ0OnNvdWxfc29pbAQJAG5hbWVfaGFzaC1/87ccutuTAwoAbmV0d29ya19pZKc63SMKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:dirt", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAAAACAQAbmFtZQ4AbWluZWNyYWZ0OmRpcnQECQBuYW1lX2hhc2hXp6jnXAe+kQMKAG5ldHdvcmtfaWQmkQtoCgYAc3RhdGVzCAkAZGlydF90eXBlBgBub3JtYWwAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:dirt", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAAAACAQAbmFtZQ4AbWluZWNyYWZ0OmRpcnQECQBuYW1lX2hhc2hXp6jnXAe+kQMKAG5ldHdvcmtfaWQId9pLCgYAc3RhdGVzCAkAZGlydF90eXBlBgBjb2Fyc2UAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:farmland", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ8AAAACAQAbmFtZRIAbWluZWNyYWZ0OmZhcm1sYW5kBAkAbmFtZV9oYXNoxyQ5ag7LolADCgBuZXR3b3JrX2lkX618FQoGAHN0YXRlcwMSAG1vaXN0dXJpemVkX2Ftb3VudAAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:grass_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQCAAAACAQAbmFtZRUAbWluZWNyYWZ0OmdyYXNzX2Jsb2NrBAkAbmFtZV9oYXNojPyGp3/CSZwDCgBuZXR3b3JrX2lktCgx3goGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:grass_path", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTGAAAACAQAbmFtZRQAbWluZWNyYWZ0OmdyYXNzX3BhdGgECQBuYW1lX2hhc2i0/KZV8Qsy+gMKAG5ldHdvcmtfaWT7CcdzCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:podzol", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTzAAAACAQAbmFtZRAAbWluZWNyYWZ0OnBvZHpvbAQJAG5hbWVfaGFzaBzqokRjH4Z1AwoAbmV0d29ya19pZPPS/GUKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:mycelium", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRuAAAACAQAbmFtZRIAbWluZWNyYWZ0Om15Y2VsaXVtBAkAbmFtZV9oYXNojTN09cKickIDCgBuZXR3b3JrX2lkLNPxXQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:mud", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTYAgAACAQAbmFtZQ0AbWluZWNyYWZ0Om11ZAQJAG5hbWVfaGFzaPb/3P+uLy+9AwoAbmV0d29ya19pZPIUlUkKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:stone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQBAAAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lkIQ4xgAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:iron_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQPAAAACAQAbmFtZRIAbWluZWNyYWZ0Omlyb25fb3JlBAkAbmFtZV9oYXNoS7BYtLnfx3gDCgBuZXR3b3JrX2lk3loneQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:gold_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQOAAAACAQAbmFtZRIAbWluZWNyYWZ0OmdvbGRfb3JlBAkAbmFtZV9oYXNoC5Y+DUGXLC4DCgBuZXR3b3JrX2lkNhvMfwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:diamond_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ4AAAACAQAbmFtZRUAbWluZWNyYWZ0OmRpYW1vbmRfb3JlBAkAbmFtZV9oYXNokUOJ2wZZrGQDCgBuZXR3b3JrX2lk/dChVAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:lapis_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQVAAAACAQAbmFtZRMAbWluZWNyYWZ0OmxhcGlzX29yZQQJAG5hbWVfaGFzaMrmrUrSzb7qAwoAbmV0d29ya19pZMg+qK4KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:redstone_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRJAAAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZHN0b25lX29yZQQJAG5hbWVfaGFzaFHVnp8Wc4JbAwoAbmV0d29ya19pZKDYvQoKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:coal_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQQAAAACAQAbmFtZRIAbWluZWNyYWZ0OmNvYWxfb3JlBAkAbmFtZV9oYXNo1OjA+Iuy51oDCgBuZXR3b3JrX2lk+R/aKAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:copper_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ2AgAACAQAbmFtZRQAbWluZWNyYWZ0OmNvcHBlcl9vcmUECQBuYW1lX2hhc2iSZduSntOzOwMKAG5ldHdvcmtfaWQtIuCnCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:emerald_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSBAAAACAQAbmFtZRUAbWluZWNyYWZ0OmVtZXJhbGRfb3JlBAkAbmFtZV9oYXNoJTovr+VgINsDCgBuZXR3b3JrX2lknbkqCgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:quartz_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSZAAAACAQAbmFtZRQAbWluZWNyYWZ0OnF1YXJ0el9vcmUECQBuYW1lX2hhc2g0yNHLMK9TaQMKAG5ldHdvcmtfaWSzN7nzCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:nether_gold_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQfAgAACAQAbmFtZRkAbWluZWNyYWZ0Om5ldGhlcl9nb2xkX29yZQQJAG5hbWVfaGFzaEJZ7segIBgBAwoAbmV0d29ya19pZNI9pDgKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:ancient_debris", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQOAgAACAQAbmFtZRgAbWluZWNyYWZ0OmFuY2llbnRfZGVicmlzBAkAbmFtZV9oYXNoNrbxMc9AwKcDCgBuZXR3b3JrX2lkrSNjEAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:deepslate_iron_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSQAgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9pcm9uX29yZQQJAG5hbWVfaGFzaB/fDL9pgvXXAwoAbmV0d29ya19pZFA0bz4KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:deepslate_gold_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSRAgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9nb2xkX29yZQQJAG5hbWVfaGFzaF9G7WYhKFinAwoAbmV0d29ya19pZHQTfBUKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:deepslate_diamond_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSUAgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV9kaWFtb25kX29yZQQJAG5hbWVfaGFzaEUH5USh+iD3AwoAbmV0d29ya19pZHP6VzAKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:deepslate_lapis_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSPAgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV9sYXBpc19vcmUECQBuYW1lX2hhc2j+yFxU/KZs1gMKAG5ldHdvcmtfaWRKINzICgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:deepslate_redstone_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSSAgAACAQAbmFtZSAAbWluZWNyYWZ0OmRlZXBzbGF0ZV9yZWRzdG9uZV9vcmUECQBuYW1lX2hhc2iVgM3wWWD6ugMKAG5ldHdvcmtfaWReBdYRCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:deepslate_emerald_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSWAgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV9lbWVyYWxkX29yZQQJAG5hbWVfaGFzaNlfo5HTwS6wAwoAbmV0d29ya19pZNeie6sKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:deepslate_coal_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSVAgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9jb2FsX29yZQQJAG5hbWVfaGFzaIjikmcbRrPPAwoAbmV0d29ya19pZD9TiygKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:deepslate_copper_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSXAgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9jb3BwZXJfb3JlBAkAbmFtZV9oYXNottjV4Ev5LAQDCgBuZXR3b3JrX2lkP23rgQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:gravel", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQNAAAACAQAbmFtZRAAbWluZWNyYWZ0OmdyYXZlbAQJAG5hbWVfaGFzaOFxz8XJd2r/AwoAbmV0d29ya19pZBpfI1sKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:granite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRNAwAACAQAbmFtZREAbWluZWNyYWZ0OmdyYW5pdGUECQBuYW1lX2hhc2iq+Dur2pw4AwMKAG5ldHdvcmtfaWT2NMfJCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:diorite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRPAwAACAQAbmFtZREAbWluZWNyYWZ0OmRpb3JpdGUECQBuYW1lX2hhc2iaFsq2iinZBQMKAG5ldHdvcmtfaWQqGE6XCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:andesite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRRAwAACAQAbmFtZRIAbWluZWNyYWZ0OmFuZGVzaXRlBAkAbmFtZV9oYXNosaLIEnQQoSYDCgBuZXR3b3JrX2lkEApRZAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:blackstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQQAgAACAQAbmFtZRQAbWluZWNyYWZ0OmJsYWNrc3RvbmUECQBuYW1lX2hhc2iMFYziD80D6QMKAG5ldHdvcmtfaWSrUryHCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:deepslate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR5AgAACAQAbmFtZRMAbWluZWNyYWZ0OmRlZXBzbGF0ZQQJAG5hbWVfaGFzaKX5pAblxz8TAwoAbmV0d29ya19pZOJoQjsKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:polished_granite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWROAwAACAQAbmFtZRoAbWluZWNyYWZ0OnBvbGlzaGVkX2dyYW5pdGUECQBuYW1lX2hhc2iLiEfys8pFIAMKAG5ldHdvcmtfaWTCxxcHCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:polished_diorite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRQAwAACAQAbmFtZRoAbWluZWNyYWZ0OnBvbGlzaGVkX2Rpb3JpdGUECQBuYW1lX2hhc2hTxY4fKmNmlAMKAG5ldHdvcmtfaWTmtjdRCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:polished_andesite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRSAwAACAQAbmFtZRsAbWluZWNyYWZ0OnBvbGlzaGVkX2FuZGVzaXRlBAkAbmFtZV9oYXNovl28uFk4HuQDCgBuZXR3b3JrX2lklFjuCwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:polished_blackstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQiAgAACAQAbmFtZR0AbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmUECQBuYW1lX2hhc2jT9fHCl6vWQQMKAG5ldHdvcmtfaWR/Ho6oCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:polished_deepslate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR+AgAACAQAbmFtZRwAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaHC1edoaWF3uAwoAbmV0d29ya19pZCPeQsEKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:sand", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQMAAAACAQAbmFtZQ4AbWluZWNyYWZ0OnNhbmQECQBuYW1lX2hhc2i6lthXXbAyWAMKAG5ldHdvcmtfaWTekU/mCgYAc3RhdGVzCAkAc2FuZF90eXBlBgBub3JtYWwAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:sand", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQMAAAACAQAbmFtZQ4AbWluZWNyYWZ0OnNhbmQECQBuYW1lX2hhc2i6lthXXbAyWAMKAG5ldHdvcmtfaWSTgcqmCgYAc3RhdGVzCAkAc2FuZF90eXBlAwByZWQAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:cactus", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRRAAAACAQAbmFtZRAAbWluZWNyYWZ0OmNhY3R1cwQJAG5hbWVfaGFzaCG9zL0N4wvGAwoAbmV0d29ya19pZDeCERAKBgBzdGF0ZXMDAwBhZ2UAAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:oak_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQRAAAACAQAbmFtZREAbWluZWNyYWZ0Om9ha19sb2cECQBuYW1lX2hhc2ho6TS+K7PZFQMKAG5ldHdvcmtfaWQjfjoxCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:stripped_oak_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQJAQAACAQAbmFtZRoAbWluZWNyYWZ0OnN0cmlwcGVkX29ha19sb2cECQBuYW1lX2hhc2h8dqh+OOHU4wMKAG5ldHdvcmtfaWSYKjdrCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:spruce_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ4AwAACAQAbmFtZRQAbWluZWNyYWZ0OnNwcnVjZV9sb2cECQBuYW1lX2hhc2hZ03qaLoF3WgMKAG5ldHdvcmtfaWRlFD8eCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:stripped_spruce_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQEAQAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX3NwcnVjZV9sb2cECQBuYW1lX2hhc2iNrhKjS5IyrgMKAG5ldHdvcmtfaWRQcEC3CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:birch_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ5AwAACAQAbmFtZRMAbWluZWNyYWZ0OmJpcmNoX2xvZwQJAG5hbWVfaGFzaBUzT3NxsZAnAwoAbmV0d29ya19pZBKN3VQKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:stripped_birch_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQFAQAACAQAbmFtZRwAbWluZWNyYWZ0OnN0cmlwcGVkX2JpcmNoX2xvZwQJAG5hbWVfaGFzaCFKS4AeuSidAwoAbmV0d29ya19pZN0IONIKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:jungle_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ6AwAACAQAbmFtZRQAbWluZWNyYWZ0Omp1bmdsZV9sb2cECQBuYW1lX2hhc2gkwW0KNulqDgMKAG5ldHdvcmtfaWQaziU/CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:stripped_jungle_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAQAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2p1bmdsZV9sb2cECQBuYW1lX2hhc2hAwMsgOk02JAMKAG5ldHdvcmtfaWQvls0eCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:acacia_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSiAAAACAQAbmFtZRQAbWluZWNyYWZ0OmFjYWNpYV9sb2cECQBuYW1lX2hhc2iV48VpYhjoYQMKAG5ldHdvcmtfaWRxEqe0CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:stripped_acacia_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQHAQAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2FjYWNpYV9sb2cECQBuYW1lX2hhc2hJb0lQqnEqlgMKAG5ldHdvcmtfaWRg3IdRCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:dark_oak_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ7AwAACAQAbmFtZRYAbWluZWNyYWZ0OmRhcmtfb2FrX2xvZwQJAG5hbWVfaGFzaIWfVRd0XUo3AwoAbmV0d29ya19pZPMM7LYKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:stripped_dark_oak_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQIAQAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2Rhcmtfb2FrX2xvZwQJAG5hbWVfaGFzaPFTdxRdPwkOAwoAbmV0d29ya19pZDIzenIKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:mangrove_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTjAgAACAQAbmFtZRYAbWluZWNyYWZ0Om1hbmdyb3ZlX2xvZwQJAG5hbWVfaGFzaHZe6DzPZBobAwoAbmV0d29ya19pZG6DuYkKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:stripped_mangrove_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTkAgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX21hbmdyb3ZlX2xvZwQJAG5hbWVfaGFzaLqIBo4hwA//AwoAbmV0d29ya19pZPtRn7UKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:cherry_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQXAwAACAQAbmFtZRQAbWluZWNyYWZ0OmNoZXJyeV9sb2cECQBuYW1lX2hhc2hwFlaioppB1wMKAG5ldHdvcmtfaWS2sdXECgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:stripped_cherry_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQWAwAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2NoZXJyeV9sb2cECQBuYW1lX2hhc2i85H6G+WhXaAMKAG5ldHdvcmtfaWRjzoglCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:crimson_stem", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTgAQAACAQAbmFtZRYAbWluZWNyYWZ0OmNyaW1zb25fc3RlbQQJAG5hbWVfaGFzaM0FzfL0UTKZAwoAbmV0d29ya19pZKvzID0KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:stripped_crimson_stem", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTvAQAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2NyaW1zb25fc3RlbQQJAG5hbWVfaGFzaDlA6nood57EAwoAbmV0d29ya19pZHrIqjIKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:warped_stem", + "block_state_b64": "CgAAAwgAYmxvY2tfaWThAQAACAQAbmFtZRUAbWluZWNyYWZ0OndhcnBlZF9zdGVtBAkAbmFtZV9oYXNon7cKfPZxdrUDCgBuZXR3b3JrX2lkerWyMwoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:stripped_warped_stem", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTwAQAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX3dhcnBlZF9zdGVtBAkAbmFtZV9oYXNoEw+y0dDPSd8DCgBuZXR3b3JrX2lkIQ9vBAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:oak_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTTAQAACAQAbmFtZRIAbWluZWNyYWZ0Om9ha193b29kBAkAbmFtZV9oYXNoqQIkuVPyJX0DCgBuZXR3b3JrX2lku2G1YAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:spruce_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQtBAAACAQAbmFtZRUAbWluZWNyYWZ0OnNwcnVjZV93b29kBAkAbmFtZV9oYXNoTrIJ5TAQ+OgDCgBuZXR3b3JrX2lkaXLxCwoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:birch_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQuBAAACAQAbmFtZRQAbWluZWNyYWZ0OmJpcmNoX3dvb2QECQBuYW1lX2hhc2iqVjG4xt0cKQMKAG5ldHdvcmtfaWS06c5VCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:jungle_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQvBAAACAQAbmFtZRUAbWluZWNyYWZ0Omp1bmdsZV93b29kBAkAbmFtZV9oYXNo9bYW29ORWCoDCgBuZXR3b3JrX2lkyFyKLQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:acacia_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQwBAAACAQAbmFtZRUAbWluZWNyYWZ0OmFjYWNpYV93b29kBAkAbmFtZV9oYXNoKkDfgzlJUcIDCgBuZXR3b3JrX2lkuTWlcgoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:dark_oak_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQxBAAACAQAbmFtZRcAbWluZWNyYWZ0OmRhcmtfb2FrX3dvb2QECQBuYW1lX2hhc2jaKv4ORLadAAMKAG5ldHdvcmtfaWSDrNQ8CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:stripped_oak_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQyBAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0cmlwcGVkX29ha193b29kBAkAbmFtZV9oYXNovW6KCv+VZnsDCgBuZXR3b3JrX2lkkhWGegoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:stripped_spruce_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQzBAAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX3NwcnVjZV93b29kBAkAbmFtZV9oYXNoMnuUk4Xo6icDCgBuZXR3b3JrX2lkes2ydAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:stripped_birch_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ0BAAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2JpcmNoX3dvb2QECQBuYW1lX2hhc2hm88R604TKbAMKAG5ldHdvcmtfaWRleEMJCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:stripped_jungle_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ1BAAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX2p1bmdsZV93b29kBAkAbmFtZV9oYXNoUVs6KsZQRBoDCgBuZXR3b3JrX2lk92k8HQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:stripped_acacia_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ2BAAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX2FjYWNpYV93b29kBAkAbmFtZV9oYXNo/kOPN2bCJhUDCgBuZXR3b3JrX2lktl6LwQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:stripped_dark_oak_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ3BAAACAQAbmFtZSAAbWluZWNyYWZ0OnN0cmlwcGVkX2Rhcmtfb2FrX3dvb2QECQBuYW1lX2hhc2h2jFDfKVFgfAMKAG5ldHdvcmtfaWTgZQ5VCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:mangrove_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTwAgAACAQAbmFtZRcAbWluZWNyYWZ0Om1hbmdyb3ZlX3dvb2QECQBuYW1lX2hhc2iXVxG0JG2fVAMKAG5ldHdvcmtfaWTok1JCCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:stripped_mangrove_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTxAgAACAQAbmFtZSAAbWluZWNyYWZ0OnN0cmlwcGVkX21hbmdyb3ZlX3dvb2QECQBuYW1lX2hhc2h7CkbaBF7/WAMKAG5ldHdvcmtfaWQLAX88CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:cherry_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQhAwAACAQAbmFtZRUAbWluZWNyYWZ0OmNoZXJyeV93b29kBAkAbmFtZV9oYXNoAW8srlmpBM8DCgBuZXR3b3JrX2lkEALMfAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AQwAc3RyaXBwZWRfYml0AAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:stripped_cherry_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQgAwAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX2NoZXJyeV93b29kBAkAbmFtZV9oYXNo/e7KXv+CB38DCgBuZXR3b3JrX2lkg5aVtQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:crimson_hyphae", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQqAgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25faHlwaGFlBAkAbmFtZV9oYXNouRmKmfSqEWADCgBuZXR3b3JrX2lk+Tm5rQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:stripped_crimson_hyphae", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQrAgAACAQAbmFtZSEAbWluZWNyYWZ0OnN0cmlwcGVkX2NyaW1zb25faHlwaGFlBAkAbmFtZV9oYXNoFffwmABq4LUDCgBuZXR3b3JrX2lkZAlUbgoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:warped_hyphae", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQpAgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9oeXBoYWUECQBuYW1lX2hhc2hn8plQUr6pmQMKAG5ldHdvcmtfaWRU2AIBCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:stripped_warped_hyphae", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAgAACAQAbmFtZSAAbWluZWNyYWZ0OnN0cmlwcGVkX3dhcnBlZF9oeXBoYWUECQBuYW1lX2hhc2irKq+HYPSgjQMKAG5ldHdvcmtfaWSbrOPDCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:bamboo_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQOAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJhbWJvb19ibG9jawQJAG5hbWVfaGFzaAbDeur6stIBAwoAbmV0d29ya19pZCJAwn0KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:stripped_bamboo_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQPAwAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2JhbWJvb19ibG9jawQJAG5hbWVfaGFzaJpwytpZOZM9AwoAbmV0d29ya19pZKuRbNEKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:oak_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQSAAAACAQAbmFtZRQAbWluZWNyYWZ0Om9ha19sZWF2ZXMECQBuYW1lX2hhc2h6O4xGqA2oKgMKAG5ldHdvcmtfaWT98c59CgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:spruce_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQfBAAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9sZWF2ZXMECQBuYW1lX2hhc2i9x1CtNAuqZwMKAG5ldHdvcmtfaWSzF7pTCgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:birch_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQgBAAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX2xlYXZlcwQJAG5hbWVfaGFzaBlAGHaoaLZSAwoAbmV0d29ya19pZOjtvWcKBgBzdGF0ZXMBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:jungle_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQhBAAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9sZWF2ZXMECQBuYW1lX2hhc2iW1uAH07zGhgMKAG5ldHdvcmtfaWSA5KX0CgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:acacia_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAAAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9sZWF2ZXMECQBuYW1lX2hhc2iZJf8dAgDRNQMKAG5ldHdvcmtfaWQ/G7VuCgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:dark_oak_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQiBAAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX2xlYXZlcwQJAG5hbWVfaGFzaCk7rDipWFSjAwoAbmV0d29ya19pZJ2AkbYKBgBzdGF0ZXMBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:mangrove_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTXAgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX2xlYXZlcwQJAG5hbWVfaGFzaKyI/dWvhEG8AwoAbmV0d29ya19pZPQxCZ8KBgBzdGF0ZXMBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:cherry_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQjAwAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9sZWF2ZXMECQBuYW1lX2hhc2giTs9ChhYBlQMKAG5ldHdvcmtfaWR8bPpwCgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:azalea_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRDAgAACAQAbmFtZRcAbWluZWNyYWZ0OmF6YWxlYV9sZWF2ZXMECQBuYW1lX2hhc2iXFhD57wFS7AMKAG5ldHdvcmtfaWTNB/9ECgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:azalea_leaves_flowered", + "block_state_b64": "CgAAAwgAYmxvY2tfaWREAgAACAQAbmFtZSAAbWluZWNyYWZ0OmF6YWxlYV9sZWF2ZXNfZmxvd2VyZWQECQBuYW1lX2hhc2gs8jxlS/pMrwMKAG5ldHdvcmtfaWQ7W4PyCgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAAAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWQmoOEvCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUDAG9hawADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAAAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWQO8pAmCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUGAHNwcnVjZQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAAAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWQDHhokCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUFAGJpcmNoAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAAAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWTdQrcyCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUGAGp1bmdsZQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAAAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWRCDffNCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUGAGFjYWNpYQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAAAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWR0BRzPCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUIAGRhcmtfb2FrAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:mangrove_propagule", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTZAgAACAQAbmFtZRwAbWluZWNyYWZ0Om1hbmdyb3ZlX3Byb3BhZ3VsZQQJAG5hbWVfaGFzaJGeox6hkfLFAwoAbmV0d29ya19pZAIpvpYKBgBzdGF0ZXMBBwBoYW5naW5nAAMPAHByb3BhZ3VsZV9zdGFnZQAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:cherry_sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQiAwAACAQAbmFtZRgAbWluZWNyYWZ0OmNoZXJyeV9zYXBsaW5nBAkAbmFtZV9oYXNoGrPpNMf1LtcDCgBuZXR3b3JrX2lkypakXQoGAHN0YXRlcwEHAGFnZV9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:bee_nest", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTZAQAACAQAbmFtZRIAbWluZWNyYWZ0OmJlZV9uZXN0BAkAbmFtZV9oYXNo2R2WBxUHEZIDCgBuZXR3b3JrX2lkiXWLEAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAADCwBob25leV9sZXZlbAAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:wheat_seeds" + }, + { + "id": "minecraft:pumpkin_seeds" + }, + { + "id": "minecraft:melon_seeds" + }, + { + "id": "minecraft:beetroot_seeds" + }, + { + "id": "minecraft:torchflower_seeds" + }, + { + "id": "minecraft:pitcher_pod" + }, + { + "id": "minecraft:wheat" + }, + { + "id": "minecraft:beetroot" + }, + { + "id": "minecraft:potato" + }, + { + "id": "minecraft:poisonous_potato" + }, + { + "id": "minecraft:carrot" + }, + { + "id": "minecraft:golden_carrot" + }, + { + "id": "minecraft:apple" + }, + { + "id": "minecraft:golden_apple" + }, + { + "id": "minecraft:enchanted_golden_apple" + }, + { + "id": "minecraft:melon_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRnAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1lbG9uX2Jsb2NrBAkAbmFtZV9oYXNoXxSm0iYpAx8DCgBuZXR3b3JrX2lkC9rqygoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:melon_slice" + }, + { + "id": "minecraft:glistering_melon_slice" + }, + { + "id": "minecraft:sweet_berries" + }, + { + "id": "minecraft:glow_berries" + }, + { + "id": "minecraft:pumpkin", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRWAAAACAQAbmFtZREAbWluZWNyYWZ0OnB1bXBraW4ECQBuYW1lX2hhc2gc8A3jaSzWbgMKAG5ldHdvcmtfaWRFGA+xCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:carved_pumpkin", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSaAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNhcnZlZF9wdW1wa2luBAkAbmFtZV9oYXNoPu1T0MJuG90DCgBuZXR3b3JrX2lkXNNn5QoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:lit_pumpkin", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRbAAAACAQAbmFtZRUAbWluZWNyYWZ0OmxpdF9wdW1wa2luBAkAbmFtZV9oYXNo7gWtEm2uPL0DCgBuZXR3b3JrX2lki8sU4AoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:honeycomb" + }, + { + "id": "minecraft:tallgrass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQfAAAACAQAbmFtZRMAbWluZWNyYWZ0OnRhbGxncmFzcwQJAG5hbWVfaGFzaC3PXpAXXYswAwoAbmV0d29ya19pZOh33DMKBgBzdGF0ZXMIDwB0YWxsX2dyYXNzX3R5cGUEAGZlcm4AAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:double_plant", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAAAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZMx1sfgKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQQAZmVybgEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:tallgrass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQfAAAACAQAbmFtZRMAbWluZWNyYWZ0OnRhbGxncmFzcwQJAG5hbWVfaGFzaC3PXpAXXYswAwoAbmV0d29ya19pZErptfIKBgBzdGF0ZXMIDwB0YWxsX2dyYXNzX3R5cGUEAHRhbGwAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:double_plant", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAAAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZAbadmIKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQUAZ3Jhc3MBDwB1cHBlcl9ibG9ja19iaXQAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:nether_sprouts" + }, + { + "id": "minecraft:fire_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRGAwAACAQAbmFtZRQAbWluZWNyYWZ0OmZpcmVfY29yYWwECQBuYW1lX2hhc2hOHyyECVQVJwMKAG5ldHdvcmtfaWS9vF0UCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:brain_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWREAwAACAQAbmFtZRUAbWluZWNyYWZ0OmJyYWluX2NvcmFsBAkAbmFtZV9oYXNoRiWlLCwA2ycDCgBuZXR3b3JrX2lkrjAuhgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:bubble_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRFAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJ1YmJsZV9jb3JhbAQJAG5hbWVfaGFzaJz6rWnl+v2qAwoAbmV0d29ya19pZImIWy0KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:tube_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSCAQAACAQAbmFtZRQAbWluZWNyYWZ0OnR1YmVfY29yYWwECQBuYW1lX2hhc2iYa8oO/tgk7wMKAG5ldHdvcmtfaWRTfND5CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:horn_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRHAwAACAQAbmFtZRQAbWluZWNyYWZ0Omhvcm5fY29yYWwECQBuYW1lX2hhc2iZnRHjZbnLPgMKAG5ldHdvcmtfaWR+GGp8CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:dead_fire_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRLAwAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfZmlyZV9jb3JhbAQJAG5hbWVfaGFzaEPU6tFy/latAwoAbmV0d29ya19pZNMa7V4KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:dead_brain_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRJAwAACAQAbmFtZRoAbWluZWNyYWZ0OmRlYWRfYnJhaW5fY29yYWwECQBuYW1lX2hhc2j5L6QJCISvzwMKAG5ldHdvcmtfaWQkKzeiCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:dead_bubble_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRKAwAACAQAbmFtZRsAbWluZWNyYWZ0OmRlYWRfYnViYmxlX2NvcmFsBAkAbmFtZV9oYXNoSTOZ/8wpeNYDCgBuZXR3b3JrX2lka6w9DAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:dead_tube_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRIAwAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfdHViZV9jb3JhbAQJAG5hbWVfaGFzaJGjNWhlaIJeAwoAbmV0d29ya19pZO3Z0ygKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:dead_horn_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRMAwAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfaG9ybl9jb3JhbAQJAG5hbWVfaGFzaJBkz3qt+g2cAwoAbmV0d29ya19pZBAN+eYKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAQAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZOg7iS4KBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgMAcmVkAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAQAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZIDj8HMKBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgQAcGluawMTAGNvcmFsX2Zhbl9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAQAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZLCJP0kKBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgYAcHVycGxlAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAQAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZFz2ly4KBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgQAYmx1ZQMTAGNvcmFsX2Zhbl9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAQAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZE4TgnYKBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgYAeWVsbG93AxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:coral_fan_dead", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkdhLQzwoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yAwByZWQDEwBjb3JhbF9mYW5fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:coral_fan_dead", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkSi6srQoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABwaW5rAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:coral_fan_dead", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkGiGSzAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgBwdXJwbGUDEwBjb3JhbF9mYW5fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:coral_fan_dead", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkmvZKOgoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABibHVlAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:coral_fan_dead", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lknLw+4QoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgB5ZWxsb3cDEwBjb3JhbF9mYW5fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:crimson_roots", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTeAQAACAQAbmFtZRcAbWluZWNyYWZ0OmNyaW1zb25fcm9vdHMECQBuYW1lX2hhc2j1fWgQLViv5QMKAG5ldHdvcmtfaWRLh5DXCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:warped_roots", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTfAQAACAQAbmFtZRYAbWluZWNyYWZ0OndhcnBlZF9yb290cwQJAG5hbWVfaGFzaBc3WvbJOLlkAwoAbmV0d29ya19pZNLgDnAKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:yellow_flower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQlAAAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19mbG93ZXIECQBuYW1lX2hhc2jWbU1pF0OUGAMKAG5ldHdvcmtfaWQgO3hpCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWSqsqQGCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUFAHBvcHB5AAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWTqDajjCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUGAG9yY2hpZAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWT5CjveCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUGAGFsbGl1bQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWTORIBJCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUJAGhvdXN0b25pYQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWTuNhmYCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUJAHR1bGlwX3JlZAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWT0O4nfCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUMAHR1bGlwX29yYW5nZQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWTqkthyCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGULAHR1bGlwX3doaXRlAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWRMbBA7CgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUKAHR1bGlwX3BpbmsAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWRexMAuCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUFAG94ZXllAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWQgs7BECgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUKAGNvcm5mbG93ZXIAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWRvDuNbCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUSAGxpbHlfb2ZfdGhlX3ZhbGxleQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:double_plant", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAAAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZOemRt4KBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQkAc3VuZmxvd2VyAQ8AdXBwZXJfYmxvY2tfYml0AAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:double_plant", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAAAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZOFugoEKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQcAc3lyaW5nYQEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:double_plant", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAAAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZN4O+/gKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQQAcm9zZQEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:double_plant", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAAAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZI3w4GMKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQcAcGFlb25pYQEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:pitcher_plant", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAwAACAQAbmFtZRcAbWluZWNyYWZ0OnBpdGNoZXJfcGxhbnQECQBuYW1lX2hhc2hRJHzsbDH+SQMKAG5ldHdvcmtfaWRnY76VCgYAc3RhdGVzAQ8AdXBwZXJfYmxvY2tfYml0AAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:pink_petals", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQkAwAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfcGV0YWxzBAkAbmFtZV9oYXNo6DQwN9SwV3QDCgBuZXR3b3JrX2lkNWneGgoGAHN0YXRlcwMGAGdyb3d0aAAAAAAIHABtaW5lY3JhZnQ6Y2FyZGluYWxfZGlyZWN0aW9uBQBzb3V0aAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:wither_rose", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTXAQAACAQAbmFtZRUAbWluZWNyYWZ0OndpdGhlcl9yb3NlBAkAbmFtZV9oYXNoaSKxl3I516gDCgBuZXR3b3JrX2lkATXLPwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:torchflower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ3AwAACAQAbmFtZRUAbWluZWNyYWZ0OnRvcmNoZmxvd2VyBAkAbmFtZV9oYXNoL+mHtElwbqQDCgBuZXR3b3JrX2lkI34O+AoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:white_dye" + }, + { + "id": "minecraft:light_gray_dye" + }, + { + "id": "minecraft:gray_dye" + }, + { + "id": "minecraft:black_dye" + }, + { + "id": "minecraft:brown_dye" + }, + { + "id": "minecraft:red_dye" + }, + { + "id": "minecraft:orange_dye" + }, + { + "id": "minecraft:yellow_dye" + }, + { + "id": "minecraft:lime_dye" + }, + { + "id": "minecraft:green_dye" + }, + { + "id": "minecraft:cyan_dye" + }, + { + "id": "minecraft:light_blue_dye" + }, + { + "id": "minecraft:blue_dye" + }, + { + "id": "minecraft:purple_dye" + }, + { + "id": "minecraft:magenta_dye" + }, + { + "id": "minecraft:pink_dye" + }, + { + "id": "minecraft:ink_sac" + }, + { + "id": "minecraft:glow_ink_sac" + }, + { + "id": "minecraft:cocoa_beans" + }, + { + "id": "minecraft:lapis_lazuli" + }, + { + "id": "minecraft:bone_meal" + }, + { + "id": "minecraft:vine", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRqAAAACAQAbmFtZQ4AbWluZWNyYWZ0OnZpbmUECQBuYW1lX2hhc2j0Sj8/XeXOLAMKAG5ldHdvcmtfaWSUkDtbCgYAc3RhdGVzAxMAdmluZV9kaXJlY3Rpb25fYml0cwAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:weeping_vines", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTmAQAACAQAbmFtZRcAbWluZWNyYWZ0OndlZXBpbmdfdmluZXMECQBuYW1lX2hhc2jrLgLHkQygiwMKAG5ldHdvcmtfaWQ8NHSJCgYAc3RhdGVzAxEAd2VlcGluZ192aW5lc19hZ2UAAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:twisting_vines", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQeAgAACAQAbmFtZRgAbWluZWNyYWZ0OnR3aXN0aW5nX3ZpbmVzBAkAbmFtZV9oYXNoDYR5QgVUQJADCgBuZXR3b3JrX2lk5kYVIQoGAHN0YXRlcwMSAHR3aXN0aW5nX3ZpbmVzX2FnZQAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:waterlily", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRvAAAACAQAbmFtZRMAbWluZWNyYWZ0OndhdGVybGlseQQJAG5hbWVfaGFzaEHgC4c1SXg0AwoAbmV0d29ya19pZOOerp8KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:seagrass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSBAQAACAQAbmFtZRIAbWluZWNyYWZ0OnNlYWdyYXNzBAkAbmFtZV9oYXNoHSBFtoHdWxIDCgBuZXR3b3JrX2lkd3lhEAoGAHN0YXRlcwgOAHNlYV9ncmFzc190eXBlBwBkZWZhdWx0AAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:kelp" + }, + { + "id": "minecraft:deadbush", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQgAAAACAQAbmFtZRIAbWluZWNyYWZ0OmRlYWRidXNoBAkAbmFtZV9oYXNoPFODe4IScnYDCgBuZXR3b3JrX2lkVfnl+goGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:bamboo", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSiAQAACAQAbmFtZRAAbWluZWNyYWZ0OmJhbWJvbwQJAG5hbWVfaGFzaBgpGmyzhedCAwoAbmV0d29ya19pZIZv1nYKBgBzdGF0ZXMBBwBhZ2VfYml0AAgQAGJhbWJvb19sZWFmX3NpemUJAG5vX2xlYXZlcwgWAGJhbWJvb19zdGFsa190aGlja25lc3MEAHRoaW4AAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:snow", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRQAAAACAQAbmFtZQ4AbWluZWNyYWZ0OnNub3cECQBuYW1lX2hhc2gVHr5XXdETWAMKAG5ldHdvcmtfaWQ0zCeHCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:ice", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRPAAAACAQAbmFtZQ0AbWluZWNyYWZ0OmljZQQJAG5hbWVfaGFzaNF26f+uUT29AwoAbmV0d29ya19pZOUMaQYKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:packed_ice", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSuAAAACAQAbmFtZRQAbWluZWNyYWZ0OnBhY2tlZF9pY2UECQBuYW1lX2hhc2hk4bu123ZrFgMKAG5ldHdvcmtfaWTr/ooaCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:blue_ice", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQKAQAACAQAbmFtZRIAbWluZWNyYWZ0OmJsdWVfaWNlBAkAbmFtZV9oYXNo+EKxYgFhKcgDCgBuZXR3b3JrX2lkxfsA8goGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:snow_layer", + "block_state_b64": "CgAAAwgAYmxvY2tfaWROAAAACAQAbmFtZRQAbWluZWNyYWZ0OnNub3dfbGF5ZXIECQBuYW1lX2hhc2hXka6atMYUCQMKAG5ldHdvcmtfaWRCrIPcCgYAc3RhdGVzAQsAY292ZXJlZF9iaXQAAwYAaGVpZ2h0AAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:pointed_dripstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQzAgAACAQAbmFtZRsAbWluZWNyYWZ0OnBvaW50ZWRfZHJpcHN0b25lBAkAbmFtZV9oYXNoJMISzmHQgt8DCgBuZXR3b3JrX2lkbWrtYgoGAHN0YXRlcwgTAGRyaXBzdG9uZV90aGlja25lc3MDAHRpcAEHAGhhbmdpbmcBAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:dripstone_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ8AgAACAQAbmFtZRkAbWluZWNyYWZ0OmRyaXBzdG9uZV9ibG9jawQJAG5hbWVfaGFzaIIXnEqY77YsAwoAbmV0d29ya19pZMZi2kwKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:moss_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWROAgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vc3NfY2FycGV0BAkAbmFtZV9oYXNo/NEDxRPTshYDCgBuZXR3b3JrX2lkaGG3QwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:moss_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ/AgAACAQAbmFtZRQAbWluZWNyYWZ0Om1vc3NfYmxvY2sECQBuYW1lX2hhc2iovcsPUYX2tgMKAG5ldHdvcmtfaWT3JSbfCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:dirt_with_roots", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ9AgAACAQAbmFtZRkAbWluZWNyYWZ0OmRpcnRfd2l0aF9yb290cwQJAG5hbWVfaGFzaLCNDYPviDCIAwoAbmV0d29ya19pZNCkwzoKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:hanging_roots", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ+AgAACAQAbmFtZRcAbWluZWNyYWZ0Omhhbmdpbmdfcm9vdHMECQBuYW1lX2hhc2jaXn+Y5UZpDAMKAG5ldHdvcmtfaWRU4c2vCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:mangrove_roots", + "block_state_b64": "CgAAAwgAYmxvY2tfaWThAgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hbmdyb3ZlX3Jvb3RzBAkAbmFtZV9oYXNoa786PzQGZ6kDCgBuZXR3b3JrX2lklA0AHgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:muddy_mangrove_roots", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTiAgAACAQAbmFtZR4AbWluZWNyYWZ0Om11ZGR5X21hbmdyb3ZlX3Jvb3RzBAkAbmFtZV9oYXNo9YApdHpo1RkDCgBuZXR3b3JrX2lkH0Oc4woGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:big_dripleaf", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRCAgAACAQAbmFtZRYAbWluZWNyYWZ0OmJpZ19kcmlwbGVhZgQJAG5hbWVfaGFzaGBEhXjo6qSdAwoAbmV0d29ya19pZMETsb8KBgBzdGF0ZXMBEQBiaWdfZHJpcGxlYWZfaGVhZAEIEQBiaWdfZHJpcGxlYWZfdGlsdAQAbm9uZQgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:small_dripleaf_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRPAgAACAQAbmFtZR4AbWluZWNyYWZ0OnNtYWxsX2RyaXBsZWFmX2Jsb2NrBAkAbmFtZV9oYXNojxRAgXP9uWADCgBuZXR3b3JrX2lkozbVPwoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24EAGVhc3QBDwB1cHBlcl9ibG9ja19iaXQBAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:spore_blossom", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRAAgAACAQAbmFtZRcAbWluZWNyYWZ0OnNwb3JlX2Jsb3Nzb20ECQBuYW1lX2hhc2il3U72Gbco2gMKAG5ldHdvcmtfaWSbbbgcCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:azalea", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRQAgAACAQAbmFtZRAAbWluZWNyYWZ0OmF6YWxlYQQJAG5hbWVfaGFzaNyUl+BW9JrBAwoAbmV0d29ya19pZO/XZtQKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:flowering_azalea", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRRAgAACAQAbmFtZRoAbWluZWNyYWZ0OmZsb3dlcmluZ19hemFsZWEECQBuYW1lX2hhc2ie9r33wz8kiwMKAG5ldHdvcmtfaWQ3ij0VCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:glow_lichen", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSaAgAACAQAbmFtZRUAbWluZWNyYWZ0Omdsb3dfbGljaGVuBAkAbmFtZV9oYXNobyPUrIYlo44DCgBuZXR3b3JrX2lkCh8lSAoGAHN0YXRlcwMZAG11bHRpX2ZhY2VfZGlyZWN0aW9uX2JpdHM/AAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:amethyst_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRGAgAACAQAbmFtZRgAbWluZWNyYWZ0OmFtZXRoeXN0X2Jsb2NrBAkAbmFtZV9oYXNob+JK1iiAthcDCgBuZXR3b3JrX2lk8HtpzgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:budding_amethyst", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRHAgAACAQAbmFtZRoAbWluZWNyYWZ0OmJ1ZGRpbmdfYW1ldGh5c3QECQBuYW1lX2hhc2gJvAwfI14fxgMKAG5ldHdvcmtfaWTQYqfACgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:amethyst_cluster", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRIAgAACAQAbmFtZRoAbWluZWNyYWZ0OmFtZXRoeXN0X2NsdXN0ZXIECQBuYW1lX2hhc2jK82S88Jgm8wMKAG5ldHdvcmtfaWSCPMPGCgYAc3RhdGVzCBQAbWluZWNyYWZ0OmJsb2NrX2ZhY2UCAHVwAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:large_amethyst_bud", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRJAgAACAQAbmFtZRwAbWluZWNyYWZ0OmxhcmdlX2FtZXRoeXN0X2J1ZAQJAG5hbWVfaGFzaAHhdpWD+sd5AwoAbmV0d29ya19pZKkQxOcKBgBzdGF0ZXMIFABtaW5lY3JhZnQ6YmxvY2tfZmFjZQIAdXAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:medium_amethyst_bud", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRKAgAACAQAbmFtZR0AbWluZWNyYWZ0Om1lZGl1bV9hbWV0aHlzdF9idWQECQBuYW1lX2hhc2g5lBGtC0DzZQMKAG5ldHdvcmtfaWSYiP4gCgYAc3RhdGVzCBQAbWluZWNyYWZ0OmJsb2NrX2ZhY2UCAHVwAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:small_amethyst_bud", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRLAgAACAQAbmFtZRwAbWluZWNyYWZ0OnNtYWxsX2FtZXRoeXN0X2J1ZAQJAG5hbWVfaGFzaEnb4+q9PO4YAwoAbmV0d29ya19pZGWzxrQKBgBzdGF0ZXMIFABtaW5lY3JhZnQ6YmxvY2tfZmFjZQIAdXAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:tuff", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRMAgAACAQAbmFtZQ4AbWluZWNyYWZ0OnR1ZmYECQBuYW1lX2hhc2h1Rwc1XYsBGwMKAG5ldHdvcmtfaWRwQGn0CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:calcite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRFAgAACAQAbmFtZREAbWluZWNyYWZ0OmNhbGNpdGUECQBuYW1lX2hhc2ixKLu8ZIdzDQMKAG5ldHdvcmtfaWQlSbJDCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:chicken" + }, + { + "id": "minecraft:porkchop" + }, + { + "id": "minecraft:beef" + }, + { + "id": "minecraft:mutton" + }, + { + "id": "minecraft:rabbit" + }, + { + "id": "minecraft:cod" + }, + { + "id": "minecraft:salmon" + }, + { + "id": "minecraft:tropical_fish" + }, + { + "id": "minecraft:pufferfish" + }, + { + "id": "minecraft:brown_mushroom", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQnAAAACAQAbmFtZRgAbWluZWNyYWZ0OmJyb3duX211c2hyb29tBAkAbmFtZV9oYXNonYw/FO78WDoDCgBuZXR3b3JrX2lkLh1OXAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:red_mushroom", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQoAAAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZF9tdXNocm9vbQQJAG5hbWVfaGFzaPpzJua7669xAwoAbmV0d29ya19pZCvWPYkKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:crimson_fungus", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTjAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fZnVuZ3VzBAkAbmFtZV9oYXNolIcCUuFM2u0DCgBuZXR3b3JrX2lkD2NN0QoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:warped_fungus", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTkAQAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9mdW5ndXMECQBuYW1lX2hhc2gq8bSnRVTAFgMKAG5ldHdvcmtfaWTkwS+rCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:brown_mushroom_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAAAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkdOMhDAoGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cw4AAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:red_mushroom_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRkAAAACAQAbmFtZRwAbWluZWNyYWZ0OnJlZF9tdXNocm9vbV9ibG9jawQJAG5hbWVfaGFzaJTTyJbth9M9AwoAbmV0d29ya19pZM+AyboKBgBzdGF0ZXMDEgBodWdlX211c2hyb29tX2JpdHMOAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:brown_mushroom_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAAAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkbdt3CAoGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cw8AAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:brown_mushroom_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAAAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkSrMl9goGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cwAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:egg" + }, + { + "id": "minecraft:sugar_cane" + }, + { + "id": "minecraft:sugar" + }, + { + "id": "minecraft:rotten_flesh" + }, + { + "id": "minecraft:bone" + }, + { + "id": "minecraft:web", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQeAAAACAQAbmFtZQ0AbWluZWNyYWZ0OndlYgQJAG5hbWVfaGFzaA4GKQCvG4i9AwoAbmV0d29ya19pZApt+jgKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:spider_eye" + }, + { + "id": "minecraft:mob_spawner", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ0AAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vYl9zcGF3bmVyBAkAbmFtZV9oYXNoNwGrCV/Fkh8DCgBuZXR3b3JrX2lkM1wTmgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:end_portal_frame", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR4AAAACAQAbmFtZRoAbWluZWNyYWZ0OmVuZF9wb3J0YWxfZnJhbWUECQBuYW1lX2hhc2gqofyUIjGOpQMKAG5ldHdvcmtfaWRbGHf8CgYAc3RhdGVzARIAZW5kX3BvcnRhbF9leWVfYml0AAgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:monster_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkqXH7RgoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGUFAHN0b25lAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:monster_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkeIBb6QoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGULAGNvYmJsZXN0b25lAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:monster_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkDZ2cFQoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGULAHN0b25lX2JyaWNrAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:monster_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkOR/cTAoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGURAG1vc3N5X3N0b25lX2JyaWNrAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:monster_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkqdwlHAoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGUTAGNyYWNrZWRfc3RvbmVfYnJpY2sAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:monster_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkFqqPggoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGUUAGNoaXNlbGVkX3N0b25lX2JyaWNrAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:infested_deepslate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTFAgAACAQAbmFtZRwAbWluZWNyYWZ0OmluZmVzdGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaICF2VYccxF1AwoAbmV0d29ya19pZDa/624KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:dragon_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR6AAAACAQAbmFtZRQAbWluZWNyYWZ0OmRyYWdvbl9lZ2cECQBuYW1lX2hhc2inMzXrV+/e1wMKAG5ldHdvcmtfaWTgO1yRCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:turtle_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSeAQAACAQAbmFtZRQAbWluZWNyYWZ0OnR1cnRsZV9lZ2cECQBuYW1lX2hhc2iwSRcxOJIJ9gMKAG5ldHdvcmtfaWSIRNUhCgYAc3RhdGVzCA0AY3JhY2tlZF9zdGF0ZQkAbm9fY3JhY2tzCBAAdHVydGxlX2VnZ19jb3VudAcAb25lX2VnZwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:sniffer_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRTAwAACAQAbmFtZRUAbWluZWNyYWZ0OnNuaWZmZXJfZWdnBAkAbmFtZV9oYXNoY1lozc8lPcYDCgBuZXR3b3JrX2lk7yb/2QoGAHN0YXRlcwgNAGNyYWNrZWRfc3RhdGUJAG5vX2NyYWNrcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:frog_spawn", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTTAgAACAQAbmFtZRQAbWluZWNyYWZ0OmZyb2dfc3Bhd24ECQBuYW1lX2hhc2iWmd7idp3ZZwMKAG5ldHdvcmtfaWRFzJudCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:pearlescent_froglight", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTUAgAACAQAbmFtZR8AbWluZWNyYWZ0OnBlYXJsZXNjZW50X2Zyb2dsaWdodAQJAG5hbWVfaGFzaKkcFRyycYGyAwoAbmV0d29ya19pZJqYakAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:verdant_froglight", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTVAgAACAQAbmFtZRsAbWluZWNyYWZ0OnZlcmRhbnRfZnJvZ2xpZ2h0BAkAbmFtZV9oYXNoA+eXuTBohrQDCgBuZXR3b3JrX2lkDIVnsQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:ochre_froglight", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTWAgAACAQAbmFtZRkAbWluZWNyYWZ0Om9jaHJlX2Zyb2dsaWdodAQJAG5hbWVfaGFzaMY59kjPe+c3AwoAbmV0d29ya19pZO2TD50KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:chicken_spawn_egg" + }, + { + "id": "minecraft:bee_spawn_egg" + }, + { + "id": "minecraft:cow_spawn_egg" + }, + { + "id": "minecraft:pig_spawn_egg" + }, + { + "id": "minecraft:sheep_spawn_egg" + }, + { + "id": "minecraft:wolf_spawn_egg" + }, + { + "id": "minecraft:polar_bear_spawn_egg" + }, + { + "id": "minecraft:ocelot_spawn_egg" + }, + { + "id": "minecraft:cat_spawn_egg" + }, + { + "id": "minecraft:mooshroom_spawn_egg" + }, + { + "id": "minecraft:bat_spawn_egg" + }, + { + "id": "minecraft:parrot_spawn_egg" + }, + { + "id": "minecraft:rabbit_spawn_egg" + }, + { + "id": "minecraft:llama_spawn_egg" + }, + { + "id": "minecraft:horse_spawn_egg" + }, + { + "id": "minecraft:donkey_spawn_egg" + }, + { + "id": "minecraft:mule_spawn_egg" + }, + { + "id": "minecraft:skeleton_horse_spawn_egg" + }, + { + "id": "minecraft:zombie_horse_spawn_egg" + }, + { + "id": "minecraft:tropical_fish_spawn_egg" + }, + { + "id": "minecraft:cod_spawn_egg" + }, + { + "id": "minecraft:pufferfish_spawn_egg" + }, + { + "id": "minecraft:salmon_spawn_egg" + }, + { + "id": "minecraft:dolphin_spawn_egg" + }, + { + "id": "minecraft:turtle_spawn_egg" + }, + { + "id": "minecraft:panda_spawn_egg" + }, + { + "id": "minecraft:fox_spawn_egg" + }, + { + "id": "minecraft:creeper_spawn_egg" + }, + { + "id": "minecraft:enderman_spawn_egg" + }, + { + "id": "minecraft:silverfish_spawn_egg" + }, + { + "id": "minecraft:skeleton_spawn_egg" + }, + { + "id": "minecraft:wither_skeleton_spawn_egg" + }, + { + "id": "minecraft:stray_spawn_egg" + }, + { + "id": "minecraft:slime_spawn_egg" + }, + { + "id": "minecraft:spider_spawn_egg" + }, + { + "id": "minecraft:zombie_spawn_egg" + }, + { + "id": "minecraft:zombie_pigman_spawn_egg" + }, + { + "id": "minecraft:husk_spawn_egg" + }, + { + "id": "minecraft:drowned_spawn_egg" + }, + { + "id": "minecraft:squid_spawn_egg" + }, + { + "id": "minecraft:glow_squid_spawn_egg" + }, + { + "id": "minecraft:cave_spider_spawn_egg" + }, + { + "id": "minecraft:witch_spawn_egg" + }, + { + "id": "minecraft:guardian_spawn_egg" + }, + { + "id": "minecraft:elder_guardian_spawn_egg" + }, + { + "id": "minecraft:endermite_spawn_egg" + }, + { + "id": "minecraft:magma_cube_spawn_egg" + }, + { + "id": "minecraft:strider_spawn_egg" + }, + { + "id": "minecraft:hoglin_spawn_egg" + }, + { + "id": "minecraft:piglin_spawn_egg" + }, + { + "id": "minecraft:zoglin_spawn_egg" + }, + { + "id": "minecraft:piglin_brute_spawn_egg" + }, + { + "id": "minecraft:goat_spawn_egg" + }, + { + "id": "minecraft:axolotl_spawn_egg" + }, + { + "id": "minecraft:warden_spawn_egg" + }, + { + "id": "minecraft:allay_spawn_egg" + }, + { + "id": "minecraft:frog_spawn_egg" + }, + { + "id": "minecraft:tadpole_spawn_egg" + }, + { + "id": "minecraft:trader_llama_spawn_egg" + }, + { + "id": "minecraft:camel_spawn_egg" + }, + { + "id": "minecraft:ghast_spawn_egg" + }, + { + "id": "minecraft:blaze_spawn_egg" + }, + { + "id": "minecraft:shulker_spawn_egg" + }, + { + "id": "minecraft:vindicator_spawn_egg" + }, + { + "id": "minecraft:evoker_spawn_egg" + }, + { + "id": "minecraft:vex_spawn_egg" + }, + { + "id": "minecraft:villager_spawn_egg" + }, + { + "id": "minecraft:wandering_trader_spawn_egg" + }, + { + "id": "minecraft:zombie_villager_spawn_egg" + }, + { + "id": "minecraft:phantom_spawn_egg" + }, + { + "id": "minecraft:pillager_spawn_egg" + }, + { + "id": "minecraft:ravager_spawn_egg" + }, + { + "id": "minecraft:iron_golem_spawn_egg" + }, + { + "id": "minecraft:snow_golem_spawn_egg" + }, + { + "id": "minecraft:sniffer_spawn_egg" + }, + { + "id": "minecraft:obsidian", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQxAAAACAQAbmFtZRIAbWluZWNyYWZ0Om9ic2lkaWFuBAkAbmFtZV9oYXNoiz4qrb8QjyEDCgBuZXR3b3JrX2lkuqnPpQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:crying_obsidian", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQgAgAACAQAbmFtZRkAbWluZWNyYWZ0OmNyeWluZ19vYnNpZGlhbgQJAG5hbWVfaGFzaKT0JlA7Z1K+AwoAbmV0d29ya19pZCjbPV4KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:bedrock", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQHAAAACAQAbmFtZREAbWluZWNyYWZ0OmJlZHJvY2sECQBuYW1lX2hhc2hWfFrh4LVtxwMKAG5ldHdvcmtfaWT7fKz1CgYAc3RhdGVzAQ4AaW5maW5pYnVybl9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:soul_sand", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRYAAAACAQAbmFtZRMAbWluZWNyYWZ0OnNvdWxfc2FuZAQJAG5hbWVfaGFzaMaf+bccu+KTAwoAbmV0d29ya19pZBQSHrMKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:magma", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTVAAAACAQAbmFtZQ8AbWluZWNyYWZ0Om1hZ21hBAkAbmFtZV9oYXNoqyTjKaIsWfYDCgBuZXR3b3JrX2lkyfWAZgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:nether_wart" + }, + { + "id": "minecraft:end_stone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR5AAAACAQAbmFtZRMAbWluZWNyYWZ0OmVuZF9zdG9uZQQJAG5hbWVfaGFzaH1J9jA39GJNAwoAbmV0d29ya19pZFeFQ7UKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:chorus_flower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTIAAAACAQAbmFtZRcAbWluZWNyYWZ0OmNob3J1c19mbG93ZXIECQBuYW1lX2hhc2iMpSodli5uawMKAG5ldHdvcmtfaWRnd1ZWCgYAc3RhdGVzAwMAYWdlAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:chorus_plant", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTwAAAACAQAbmFtZRYAbWluZWNyYWZ0OmNob3J1c19wbGFudAQJAG5hbWVfaGFzaJhSrmNGKwaMAwoAbmV0d29ya19pZA3uVqMKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:chorus_fruit" + }, + { + "id": "minecraft:popped_chorus_fruit" + }, + { + "id": "minecraft:sponge", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQTAAAACAQAbmFtZRAAbWluZWNyYWZ0OnNwb25nZQQJAG5hbWVfaGFzaLrd2ScYRDMiAwoAbmV0d29ya19pZF01rO0KBgBzdGF0ZXMICwBzcG9uZ2VfdHlwZQMAZHJ5AAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:sponge", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQTAAAACAQAbmFtZRAAbWluZWNyYWZ0OnNwb25nZQQJAG5hbWVfaGFzaLrd2ScYRDMiAwoAbmV0d29ya19pZPiOc4QKBgBzdGF0ZXMICwBzcG9uZ2VfdHlwZQMAd2V0AAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkGnlaAwoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABibHVlAQgAZGVhZF9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkSnHuagoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABwaW5rAQgAZGVhZF9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkmkHyegoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgBwdXJwbGUBCABkZWFkX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkdpUDxgoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yAwByZWQBCABkZWFkX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkYNWvYgoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgB5ZWxsb3cBCABkZWFkX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkZSxBQgoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABibHVlAQgAZGVhZF9iaXQBAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lklSTVqQoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABwaW5rAQgAZGVhZF9iaXQBAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lk5fTYuQoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgBwdXJwbGUBCABkZWFkX2JpdAEAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkwUjqBAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yAwByZWQBCABkZWFkX2JpdAEAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkq4iWoQoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgB5ZWxsb3cBCABkZWFkX2JpdAEAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:sculk", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAgAACAQAbmFtZQ8AbWluZWNyYWZ0OnNjdWxrBAkAbmFtZV9oYXNo2Lq7T5yQF8kDCgBuZXR3b3JrX2lkyqUPPgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:sculk_vein", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTKAgAACAQAbmFtZRQAbWluZWNyYWZ0OnNjdWxrX3ZlaW4ECQBuYW1lX2hhc2gJUdhVooV4zwMKAG5ldHdvcmtfaWSUfn1XCgYAc3RhdGVzAxkAbXVsdGlfZmFjZV9kaXJlY3Rpb25fYml0cwAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:sculk_catalyst", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTLAgAACAQAbmFtZRgAbWluZWNyYWZ0OnNjdWxrX2NhdGFseXN0BAkAbmFtZV9oYXNo+gCpbrCHST4DCgBuZXR3b3JrX2lkMJ2n/woGAHN0YXRlcwEFAGJsb29tAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:sculk_shrieker", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTMAgAACAQAbmFtZRgAbWluZWNyYWZ0OnNjdWxrX3Nocmlla2VyBAkAbmFtZV9oYXNo5OXtyObniQ4DCgBuZXR3b3JrX2lkxapoNAoGAHN0YXRlcwEGAGFjdGl2ZQABCgBjYW5fc3VtbW9uAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:sculk_sensor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQyAgAACAQAbmFtZRYAbWluZWNyYWZ0OnNjdWxrX3NlbnNvcgQJAG5hbWVfaGFzaCkmHreeTgNnAwoAbmV0d29ya19pZLj2WPcKBgBzdGF0ZXMDEgBzY3Vsa19zZW5zb3JfcGhhc2UAAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:calibrated_sculk_sensor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRDAwAACAQAbmFtZSEAbWluZWNyYWZ0OmNhbGlicmF0ZWRfc2N1bGtfc2Vuc29yBAkAbmFtZV9oYXNoffAcXXN/iJUDCgBuZXR3b3JrX2lkwOx3QQoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAxIAc2N1bGtfc2Vuc29yX3BoYXNlAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:reinforced_deepslate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTRAgAACAQAbmFtZR4AbWluZWNyYWZ0OnJlaW5mb3JjZWRfZGVlcHNsYXRlBAkAbmFtZV9oYXNoldDmj91EapQDCgBuZXR3b3JrX2lkHIt+aQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:leather_helmet" + }, + { + "id": "minecraft:chainmail_helmet" + }, + { + "id": "minecraft:iron_helmet" + }, + { + "id": "minecraft:golden_helmet" + }, + { + "id": "minecraft:diamond_helmet" + }, + { + "id": "minecraft:netherite_helmet" + }, + { + "id": "minecraft:leather_chestplate" + }, + { + "id": "minecraft:chainmail_chestplate" + }, + { + "id": "minecraft:iron_chestplate" + }, + { + "id": "minecraft:golden_chestplate" + }, + { + "id": "minecraft:diamond_chestplate" + }, + { + "id": "minecraft:netherite_chestplate" + }, + { + "id": "minecraft:leather_leggings" + }, + { + "id": "minecraft:chainmail_leggings" + }, + { + "id": "minecraft:iron_leggings" + }, + { + "id": "minecraft:golden_leggings" + }, + { + "id": "minecraft:diamond_leggings" + }, + { + "id": "minecraft:netherite_leggings" + }, + { + "id": "minecraft:leather_boots" + }, + { + "id": "minecraft:chainmail_boots" + }, + { + "id": "minecraft:iron_boots" + }, + { + "id": "minecraft:golden_boots" + }, + { + "id": "minecraft:diamond_boots" + }, + { + "id": "minecraft:netherite_boots" + }, + { + "id": "minecraft:wooden_sword" + }, + { + "id": "minecraft:stone_sword" + }, + { + "id": "minecraft:iron_sword" + }, + { + "id": "minecraft:golden_sword" + }, + { + "id": "minecraft:diamond_sword" + }, + { + "id": "minecraft:netherite_sword" + }, + { + "id": "minecraft:wooden_axe" + }, + { + "id": "minecraft:stone_axe" + }, + { + "id": "minecraft:iron_axe" + }, + { + "id": "minecraft:golden_axe" + }, + { + "id": "minecraft:diamond_axe" + }, + { + "id": "minecraft:netherite_axe" + }, + { + "id": "minecraft:wooden_pickaxe" + }, + { + "id": "minecraft:stone_pickaxe" + }, + { + "id": "minecraft:iron_pickaxe" + }, + { + "id": "minecraft:golden_pickaxe" + }, + { + "id": "minecraft:diamond_pickaxe" + }, + { + "id": "minecraft:netherite_pickaxe" + }, + { + "id": "minecraft:wooden_shovel" + }, + { + "id": "minecraft:stone_shovel" + }, + { + "id": "minecraft:iron_shovel" + }, + { + "id": "minecraft:golden_shovel" + }, + { + "id": "minecraft:diamond_shovel" + }, + { + "id": "minecraft:netherite_shovel" + }, + { + "id": "minecraft:wooden_hoe" + }, + { + "id": "minecraft:stone_hoe" + }, + { + "id": "minecraft:iron_hoe" + }, + { + "id": "minecraft:golden_hoe" + }, + { + "id": "minecraft:diamond_hoe" + }, + { + "id": "minecraft:netherite_hoe" + }, + { + "id": "minecraft:bow" + }, + { + "id": "minecraft:crossbow" + }, + { + "id": "minecraft:arrow" + }, + { + "id": "minecraft:arrow", + "damage": 6 + }, + { + "id": "minecraft:arrow", + "damage": 7 + }, + { + "id": "minecraft:arrow", + "damage": 8 + }, + { + "id": "minecraft:arrow", + "damage": 9 + }, + { + "id": "minecraft:arrow", + "damage": 10 + }, + { + "id": "minecraft:arrow", + "damage": 11 + }, + { + "id": "minecraft:arrow", + "damage": 12 + }, + { + "id": "minecraft:arrow", + "damage": 13 + }, + { + "id": "minecraft:arrow", + "damage": 14 + }, + { + "id": "minecraft:arrow", + "damage": 15 + }, + { + "id": "minecraft:arrow", + "damage": 16 + }, + { + "id": "minecraft:arrow", + "damage": 17 + }, + { + "id": "minecraft:arrow", + "damage": 18 + }, + { + "id": "minecraft:arrow", + "damage": 19 + }, + { + "id": "minecraft:arrow", + "damage": 20 + }, + { + "id": "minecraft:arrow", + "damage": 21 + }, + { + "id": "minecraft:arrow", + "damage": 22 + }, + { + "id": "minecraft:arrow", + "damage": 23 + }, + { + "id": "minecraft:arrow", + "damage": 24 + }, + { + "id": "minecraft:arrow", + "damage": 25 + }, + { + "id": "minecraft:arrow", + "damage": 26 + }, + { + "id": "minecraft:arrow", + "damage": 27 + }, + { + "id": "minecraft:arrow", + "damage": 28 + }, + { + "id": "minecraft:arrow", + "damage": 29 + }, + { + "id": "minecraft:arrow", + "damage": 30 + }, + { + "id": "minecraft:arrow", + "damage": 31 + }, + { + "id": "minecraft:arrow", + "damage": 32 + }, + { + "id": "minecraft:arrow", + "damage": 33 + }, + { + "id": "minecraft:arrow", + "damage": 34 + }, + { + "id": "minecraft:arrow", + "damage": 35 + }, + { + "id": "minecraft:arrow", + "damage": 36 + }, + { + "id": "minecraft:arrow", + "damage": 37 + }, + { + "id": "minecraft:arrow", + "damage": 38 + }, + { + "id": "minecraft:arrow", + "damage": 39 + }, + { + "id": "minecraft:arrow", + "damage": 40 + }, + { + "id": "minecraft:arrow", + "damage": 41 + }, + { + "id": "minecraft:arrow", + "damage": 42 + }, + { + "id": "minecraft:arrow", + "damage": 43 + }, + { + "id": "minecraft:shield" + }, + { + "id": "minecraft:cooked_chicken" + }, + { + "id": "minecraft:cooked_porkchop" + }, + { + "id": "minecraft:cooked_beef" + }, + { + "id": "minecraft:cooked_mutton" + }, + { + "id": "minecraft:cooked_rabbit" + }, + { + "id": "minecraft:cooked_cod" + }, + { + "id": "minecraft:cooked_salmon" + }, + { + "id": "minecraft:bread" + }, + { + "id": "minecraft:mushroom_stew" + }, + { + "id": "minecraft:beetroot_soup" + }, + { + "id": "minecraft:rabbit_stew" + }, + { + "id": "minecraft:baked_potato" + }, + { + "id": "minecraft:cookie" + }, + { + "id": "minecraft:pumpkin_pie" + }, + { + "id": "minecraft:cake" + }, + { + "id": "minecraft:dried_kelp" + }, + { + "id": "minecraft:fishing_rod" + }, + { + "id": "minecraft:carrot_on_a_stick" + }, + { + "id": "minecraft:warped_fungus_on_a_stick" + }, + { + "id": "minecraft:snowball" + }, + { + "id": "minecraft:shears" + }, + { + "id": "minecraft:flint_and_steel" + }, + { + "id": "minecraft:lead" + }, + { + "id": "minecraft:clock" + }, + { + "id": "minecraft:compass" + }, + { + "id": "minecraft:recovery_compass" + }, + { + "id": "minecraft:goat_horn" + }, + { + "id": "minecraft:goat_horn", + "damage": 1 + }, + { + "id": "minecraft:goat_horn", + "damage": 2 + }, + { + "id": "minecraft:goat_horn", + "damage": 3 + }, + { + "id": "minecraft:goat_horn", + "damage": 4 + }, + { + "id": "minecraft:goat_horn", + "damage": 5 + }, + { + "id": "minecraft:goat_horn", + "damage": 6 + }, + { + "id": "minecraft:goat_horn", + "damage": 7 + }, + { + "id": "minecraft:empty_map" + }, + { + "id": "minecraft:empty_map", + "damage": 2 + }, + { + "id": "minecraft:saddle" + }, + { + "id": "minecraft:leather_horse_armor" + }, + { + "id": "minecraft:iron_horse_armor" + }, + { + "id": "minecraft:golden_horse_armor" + }, + { + "id": "minecraft:diamond_horse_armor" + }, + { + "id": "minecraft:trident" + }, + { + "id": "minecraft:turtle_helmet" + }, + { + "id": "minecraft:elytra" + }, + { + "id": "minecraft:totem_of_undying" + }, + { + "id": "minecraft:glass_bottle" + }, + { + "id": "minecraft:experience_bottle" + }, + { + "id": "minecraft:potion" + }, + { + "id": "minecraft:potion", + "damage": 1 + }, + { + "id": "minecraft:potion", + "damage": 2 + }, + { + "id": "minecraft:potion", + "damage": 3 + }, + { + "id": "minecraft:potion", + "damage": 4 + }, + { + "id": "minecraft:potion", + "damage": 5 + }, + { + "id": "minecraft:potion", + "damage": 6 + }, + { + "id": "minecraft:potion", + "damage": 7 + }, + { + "id": "minecraft:potion", + "damage": 8 + }, + { + "id": "minecraft:potion", + "damage": 9 + }, + { + "id": "minecraft:potion", + "damage": 10 + }, + { + "id": "minecraft:potion", + "damage": 11 + }, + { + "id": "minecraft:potion", + "damage": 12 + }, + { + "id": "minecraft:potion", + "damage": 13 + }, + { + "id": "minecraft:potion", + "damage": 14 + }, + { + "id": "minecraft:potion", + "damage": 15 + }, + { + "id": "minecraft:potion", + "damage": 16 + }, + { + "id": "minecraft:potion", + "damage": 17 + }, + { + "id": "minecraft:potion", + "damage": 18 + }, + { + "id": "minecraft:potion", + "damage": 19 + }, + { + "id": "minecraft:potion", + "damage": 20 + }, + { + "id": "minecraft:potion", + "damage": 21 + }, + { + "id": "minecraft:potion", + "damage": 22 + }, + { + "id": "minecraft:potion", + "damage": 23 + }, + { + "id": "minecraft:potion", + "damage": 24 + }, + { + "id": "minecraft:potion", + "damage": 25 + }, + { + "id": "minecraft:potion", + "damage": 26 + }, + { + "id": "minecraft:potion", + "damage": 27 + }, + { + "id": "minecraft:potion", + "damage": 28 + }, + { + "id": "minecraft:potion", + "damage": 29 + }, + { + "id": "minecraft:potion", + "damage": 30 + }, + { + "id": "minecraft:potion", + "damage": 31 + }, + { + "id": "minecraft:potion", + "damage": 32 + }, + { + "id": "minecraft:potion", + "damage": 33 + }, + { + "id": "minecraft:potion", + "damage": 34 + }, + { + "id": "minecraft:potion", + "damage": 35 + }, + { + "id": "minecraft:potion", + "damage": 36 + }, + { + "id": "minecraft:potion", + "damage": 37 + }, + { + "id": "minecraft:potion", + "damage": 38 + }, + { + "id": "minecraft:potion", + "damage": 39 + }, + { + "id": "minecraft:potion", + "damage": 40 + }, + { + "id": "minecraft:potion", + "damage": 41 + }, + { + "id": "minecraft:potion", + "damage": 42 + }, + { + "id": "minecraft:splash_potion" + }, + { + "id": "minecraft:splash_potion", + "damage": 1 + }, + { + "id": "minecraft:splash_potion", + "damage": 2 + }, + { + "id": "minecraft:splash_potion", + "damage": 3 + }, + { + "id": "minecraft:splash_potion", + "damage": 4 + }, + { + "id": "minecraft:splash_potion", + "damage": 5 + }, + { + "id": "minecraft:splash_potion", + "damage": 6 + }, + { + "id": "minecraft:splash_potion", + "damage": 7 + }, + { + "id": "minecraft:splash_potion", + "damage": 8 + }, + { + "id": "minecraft:splash_potion", + "damage": 9 + }, + { + "id": "minecraft:splash_potion", + "damage": 10 + }, + { + "id": "minecraft:splash_potion", + "damage": 11 + }, + { + "id": "minecraft:splash_potion", + "damage": 12 + }, + { + "id": "minecraft:splash_potion", + "damage": 13 + }, + { + "id": "minecraft:splash_potion", + "damage": 14 + }, + { + "id": "minecraft:splash_potion", + "damage": 15 + }, + { + "id": "minecraft:splash_potion", + "damage": 16 + }, + { + "id": "minecraft:splash_potion", + "damage": 17 + }, + { + "id": "minecraft:splash_potion", + "damage": 18 + }, + { + "id": "minecraft:splash_potion", + "damage": 19 + }, + { + "id": "minecraft:splash_potion", + "damage": 20 + }, + { + "id": "minecraft:splash_potion", + "damage": 21 + }, + { + "id": "minecraft:splash_potion", + "damage": 22 + }, + { + "id": "minecraft:splash_potion", + "damage": 23 + }, + { + "id": "minecraft:splash_potion", + "damage": 24 + }, + { + "id": "minecraft:splash_potion", + "damage": 25 + }, + { + "id": "minecraft:splash_potion", + "damage": 26 + }, + { + "id": "minecraft:splash_potion", + "damage": 27 + }, + { + "id": "minecraft:splash_potion", + "damage": 28 + }, + { + "id": "minecraft:splash_potion", + "damage": 29 + }, + { + "id": "minecraft:splash_potion", + "damage": 30 + }, + { + "id": "minecraft:splash_potion", + "damage": 31 + }, + { + "id": "minecraft:splash_potion", + "damage": 32 + }, + { + "id": "minecraft:splash_potion", + "damage": 33 + }, + { + "id": "minecraft:splash_potion", + "damage": 34 + }, + { + "id": "minecraft:splash_potion", + "damage": 35 + }, + { + "id": "minecraft:splash_potion", + "damage": 36 + }, + { + "id": "minecraft:splash_potion", + "damage": 37 + }, + { + "id": "minecraft:splash_potion", + "damage": 38 + }, + { + "id": "minecraft:splash_potion", + "damage": 39 + }, + { + "id": "minecraft:splash_potion", + "damage": 40 + }, + { + "id": "minecraft:splash_potion", + "damage": 41 + }, + { + "id": "minecraft:splash_potion", + "damage": 42 + }, + { + "id": "minecraft:lingering_potion" + }, + { + "id": "minecraft:lingering_potion", + "damage": 1 + }, + { + "id": "minecraft:lingering_potion", + "damage": 2 + }, + { + "id": "minecraft:lingering_potion", + "damage": 3 + }, + { + "id": "minecraft:lingering_potion", + "damage": 4 + }, + { + "id": "minecraft:lingering_potion", + "damage": 5 + }, + { + "id": "minecraft:lingering_potion", + "damage": 6 + }, + { + "id": "minecraft:lingering_potion", + "damage": 7 + }, + { + "id": "minecraft:lingering_potion", + "damage": 8 + }, + { + "id": "minecraft:lingering_potion", + "damage": 9 + }, + { + "id": "minecraft:lingering_potion", + "damage": 10 + }, + { + "id": "minecraft:lingering_potion", + "damage": 11 + }, + { + "id": "minecraft:lingering_potion", + "damage": 12 + }, + { + "id": "minecraft:lingering_potion", + "damage": 13 + }, + { + "id": "minecraft:lingering_potion", + "damage": 14 + }, + { + "id": "minecraft:lingering_potion", + "damage": 15 + }, + { + "id": "minecraft:lingering_potion", + "damage": 16 + }, + { + "id": "minecraft:lingering_potion", + "damage": 17 + }, + { + "id": "minecraft:lingering_potion", + "damage": 18 + }, + { + "id": "minecraft:lingering_potion", + "damage": 19 + }, + { + "id": "minecraft:lingering_potion", + "damage": 20 + }, + { + "id": "minecraft:lingering_potion", + "damage": 21 + }, + { + "id": "minecraft:lingering_potion", + "damage": 22 + }, + { + "id": "minecraft:lingering_potion", + "damage": 23 + }, + { + "id": "minecraft:lingering_potion", + "damage": 24 + }, + { + "id": "minecraft:lingering_potion", + "damage": 25 + }, + { + "id": "minecraft:lingering_potion", + "damage": 26 + }, + { + "id": "minecraft:lingering_potion", + "damage": 27 + }, + { + "id": "minecraft:lingering_potion", + "damage": 28 + }, + { + "id": "minecraft:lingering_potion", + "damage": 29 + }, + { + "id": "minecraft:lingering_potion", + "damage": 30 + }, + { + "id": "minecraft:lingering_potion", + "damage": 31 + }, + { + "id": "minecraft:lingering_potion", + "damage": 32 + }, + { + "id": "minecraft:lingering_potion", + "damage": 33 + }, + { + "id": "minecraft:lingering_potion", + "damage": 34 + }, + { + "id": "minecraft:lingering_potion", + "damage": 35 + }, + { + "id": "minecraft:lingering_potion", + "damage": 36 + }, + { + "id": "minecraft:lingering_potion", + "damage": 37 + }, + { + "id": "minecraft:lingering_potion", + "damage": 38 + }, + { + "id": "minecraft:lingering_potion", + "damage": 39 + }, + { + "id": "minecraft:lingering_potion", + "damage": 40 + }, + { + "id": "minecraft:lingering_potion", + "damage": 41 + }, + { + "id": "minecraft:lingering_potion", + "damage": 42 + }, + { + "id": "minecraft:spyglass" + }, + { + "id": "minecraft:brush" + }, + { + "id": "minecraft:stick" + }, + { + "id": "minecraft:bed" + }, + { + "id": "minecraft:bed", + "damage": 8 + }, + { + "id": "minecraft:bed", + "damage": 7 + }, + { + "id": "minecraft:bed", + "damage": 15 + }, + { + "id": "minecraft:bed", + "damage": 12 + }, + { + "id": "minecraft:bed", + "damage": 14 + }, + { + "id": "minecraft:bed", + "damage": 1 + }, + { + "id": "minecraft:bed", + "damage": 4 + }, + { + "id": "minecraft:bed", + "damage": 5 + }, + { + "id": "minecraft:bed", + "damage": 13 + }, + { + "id": "minecraft:bed", + "damage": 9 + }, + { + "id": "minecraft:bed", + "damage": 3 + }, + { + "id": "minecraft:bed", + "damage": 11 + }, + { + "id": "minecraft:bed", + "damage": 10 + }, + { + "id": "minecraft:bed", + "damage": 2 + }, + { + "id": "minecraft:bed", + "damage": 6 + }, + { + "id": "minecraft:torch", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQyAAAACAQAbmFtZQ8AbWluZWNyYWZ0OnRvcmNoBAkAbmFtZV9oYXNoagn7rmDBzisDCgBuZXR3b3JrX2lk+BwwuQoGAHN0YXRlcwgWAHRvcmNoX2ZhY2luZ19kaXJlY3Rpb24HAHVua25vd24AAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:soul_torch", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQLAgAACAQAbmFtZRQAbWluZWNyYWZ0OnNvdWxfdG9yY2gECQBuYW1lX2hhc2huixOT04BRdQMKAG5ldHdvcmtfaWShbFILCgYAc3RhdGVzCBYAdG9yY2hfZmFjaW5nX2RpcmVjdGlvbgcAdW5rbm93bgADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:sea_pickle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAQAACAQAbmFtZRQAbWluZWNyYWZ0OnNlYV9waWNrbGUECQBuYW1lX2hhc2iONEfZJB+glgMKAG5ldHdvcmtfaWSINWQyCgYAc3RhdGVzAw0AY2x1c3Rlcl9jb3VudAAAAAABCABkZWFkX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:lantern", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTPAQAACAQAbmFtZREAbWluZWNyYWZ0OmxhbnRlcm4ECQBuYW1lX2hhc2hMw44VI2HWygMKAG5ldHdvcmtfaWRkjQvzCgYAc3RhdGVzAQcAaGFuZ2luZwAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:soul_lantern", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQMAgAACAQAbmFtZRYAbWluZWNyYWZ0OnNvdWxfbGFudGVybgQJAG5hbWVfaGFzaGjIpjxk9z+RAwoAbmV0d29ya19pZGfoP8cKBgBzdGF0ZXMBBwBoYW5naW5nAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAgAACAQAbmFtZRAAbWluZWNyYWZ0OmNhbmRsZQQJAG5hbWVfaGFzaHPd+MsNdWTfAwoAbmV0d29ya19pZHsBMA0KBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:white_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWScAgAACAQAbmFtZRYAbWluZWNyYWZ0OndoaXRlX2NhbmRsZQQJAG5hbWVfaGFzaN1EG5Q1mHiEAwoAbmV0d29ya19pZKN1mmgKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:orange_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSdAgAACAQAbmFtZRcAbWluZWNyYWZ0Om9yYW5nZV9jYW5kbGUECQBuYW1lX2hhc2jySEVWHgUIHQMKAG5ldHdvcmtfaWSfVz82CgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:magenta_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSeAgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hZ2VudGFfY2FuZGxlBAkAbmFtZV9oYXNoG0u6YIOoBSEDCgBuZXR3b3JrX2lk9xGNkQoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:light_blue_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSfAgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY2FuZGxlBAkAbmFtZV9oYXNocXGeK0zgrG0DCgBuZXR3b3JrX2lk2m1y8goGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:yellow_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSgAgAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19jYW5kbGUECQBuYW1lX2hhc2i00dtusU3CqQMKAG5ldHdvcmtfaWR9LTmpCgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:lime_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAgAACAQAbmFtZRUAbWluZWNyYWZ0OmxpbWVfY2FuZGxlBAkAbmFtZV9oYXNokcmrw5xvz7ADCgBuZXR3b3JrX2lkIAUu6QoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:pink_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSiAgAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfY2FuZGxlBAkAbmFtZV9oYXNoQJdEY4sZ0dwDCgBuZXR3b3JrX2lk23Rn5AoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:gray_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSjAgAACAQAbmFtZRUAbWluZWNyYWZ0OmdyYXlfY2FuZGxlBAkAbmFtZV9oYXNoS5poSo9wBDEDCgBuZXR3b3JrX2lk3trRCAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:light_gray_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSkAgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY2FuZGxlBAkAbmFtZV9oYXNo9ruTZLBNMasDCgBuZXR3b3JrX2lkb6DOegoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:cyan_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAgAACAQAbmFtZRUAbWluZWNyYWZ0OmN5YW5fY2FuZGxlBAkAbmFtZV9oYXNoc/M8PNVcjOwDCgBuZXR3b3JrX2lkZoIQOQoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:purple_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSmAgAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnBsZV9jYW5kbGUECQBuYW1lX2hhc2jaI3xUW0/myQMKAG5ldHdvcmtfaWSnLI2BCgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:blue_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSnAgAACAQAbmFtZRUAbWluZWNyYWZ0OmJsdWVfY2FuZGxlBAkAbmFtZV9oYXNoAASSPW6TgQADCgBuZXR3b3JrX2lkrxrjQAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:brown_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAgAACAQAbmFtZRYAbWluZWNyYWZ0OmJyb3duX2NhbmRsZQQJAG5hbWVfaGFzaDia0l6s1+WYAwoAbmV0d29ya19pZKSkBXYKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:green_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSpAgAACAQAbmFtZRYAbWluZWNyYWZ0OmdyZWVuX2NhbmRsZQQJAG5hbWVfaGFzaLeFPO1l+fIoAwoAbmV0d29ya19pZBkznDsKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:red_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSqAgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9jYW5kbGUECQBuYW1lX2hhc2jjAQpGf59ZdwMKAG5ldHdvcmtfaWRbb88GCgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:black_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSrAgAACAQAbmFtZRYAbWluZWNyYWZ0OmJsYWNrX2NhbmRsZQQJAG5hbWVfaGFzaB+wRDpOqREKAwoAbmV0d29ya19pZNnOnuEKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:crafting_table", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ6AAAACAQAbmFtZRgAbWluZWNyYWZ0OmNyYWZ0aW5nX3RhYmxlBAkAbmFtZV9oYXNoe76VAmjvbpYDCgBuZXR3b3JrX2lkwCxwaAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:cartography_table", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTHAQAACAQAbmFtZRsAbWluZWNyYWZ0OmNhcnRvZ3JhcGh5X3RhYmxlBAkAbmFtZV9oYXNomaWiiD/znP8DCgBuZXR3b3JrX2lkI6FzMwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:fletching_table", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTIAQAACAQAbmFtZRkAbWluZWNyYWZ0OmZsZXRjaGluZ190YWJsZQQJAG5hbWVfaGFzaPFibh8unKyUAwoAbmV0d29ya19pZJ2mW0oKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:smithing_table", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAQAACAQAbmFtZRgAbWluZWNyYWZ0OnNtaXRoaW5nX3RhYmxlBAkAbmFtZV9oYXNo4tFES2xOXEYDCgBuZXR3b3JrX2lkXWMBzQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:beehive", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTaAQAACAQAbmFtZREAbWluZWNyYWZ0OmJlZWhpdmUECQBuYW1lX2hhc2hCcqn12UbNpwMKAG5ldHdvcmtfaWR/idcaCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAMLAGhvbmV5X2xldmVsAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:suspicious_sand", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQQAwAACAQAbmFtZRkAbWluZWNyYWZ0OnN1c3BpY2lvdXNfc2FuZAQJAG5hbWVfaGFzaL67QsuvLP00AwoAbmV0d29ya19pZKnkaIAKBgBzdGF0ZXMDEABicnVzaGVkX3Byb2dyZXNzAAAAAAEHAGhhbmdpbmcBAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:suspicious_gravel", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ8AwAACAQAbmFtZRsAbWluZWNyYWZ0OnN1c3BpY2lvdXNfZ3JhdmVsBAkAbmFtZV9oYXNoJSVbGNk7C3oDCgBuZXR3b3JrX2lkvIEJAAoGAHN0YXRlcwMQAGJydXNoZWRfcHJvZ3Jlc3MAAAAAAQcAaGFuZ2luZwEAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:campfire" + }, + { + "id": "minecraft:soul_campfire" + }, + { + "id": "minecraft:furnace", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ9AAAACAQAbmFtZREAbWluZWNyYWZ0OmZ1cm5hY2UECQBuYW1lX2hhc2ioOQrludYY8wMKAG5ldHdvcmtfaWRZxnDOCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:blast_furnace", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTDAQAACAQAbmFtZRcAbWluZWNyYWZ0OmJsYXN0X2Z1cm5hY2UECQBuYW1lX2hhc2ivDbnjkpGm5QMKAG5ldHdvcmtfaWTcEbV/CgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:smoker", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTFAQAACAQAbmFtZRAAbWluZWNyYWZ0OnNtb2tlcgQJAG5hbWVfaGFzaJd1rDMkRWomAwoAbmV0d29ya19pZGWswMwKBgBzdGF0ZXMIHABtaW5lY3JhZnQ6Y2FyZGluYWxfZGlyZWN0aW9uBQBzb3V0aAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:respawn_anchor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQPAgAACAQAbmFtZRgAbWluZWNyYWZ0OnJlc3Bhd25fYW5jaG9yBAkAbmFtZV9oYXNoZOdcjW05qigDCgBuZXR3b3JrX2lkmhMcaQoGAHN0YXRlcwMVAHJlc3Bhd25fYW5jaG9yX2NoYXJnZQAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:brewing_stand" + }, + { + "id": "minecraft:anvil", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSRAAAACAQAbmFtZQ8AbWluZWNyYWZ0OmFudmlsBAkAbmFtZV9oYXNoNqB3fgcUCbwDCgBuZXR3b3JrX2lk8Z3VowoGAHN0YXRlcwgGAGRhbWFnZQkAdW5kYW1hZ2VkCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:anvil", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSRAAAACAQAbmFtZQ8AbWluZWNyYWZ0OmFudmlsBAkAbmFtZV9oYXNoNqB3fgcUCbwDCgBuZXR3b3JrX2lkpiv8BAoGAHN0YXRlcwgGAGRhbWFnZRAAc2xpZ2h0bHlfZGFtYWdlZAgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:anvil", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSRAAAACAQAbmFtZQ8AbWluZWNyYWZ0OmFudmlsBAkAbmFtZV9oYXNoNqB3fgcUCbwDCgBuZXR3b3JrX2lkFu+pdwoGAHN0YXRlcwgGAGRhbWFnZQwAdmVyeV9kYW1hZ2VkCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:grindstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTCAQAACAQAbmFtZRQAbWluZWNyYWZ0OmdyaW5kc3RvbmUECQBuYW1lX2hhc2id56zc0nk99wMKAG5ldHdvcmtfaWS4Es07CgYAc3RhdGVzCAoAYXR0YWNobWVudAgAc3RhbmRpbmcDCQBkaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:enchanting_table", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR0AAAACAQAbmFtZRoAbWluZWNyYWZ0OmVuY2hhbnRpbmdfdGFibGUECQBuYW1lX2hhc2jgIx24VLvMvwMKAG5ldHdvcmtfaWRliFFJCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:bookshelf", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQvAAAACAQAbmFtZRMAbWluZWNyYWZ0OmJvb2tzaGVsZgQJAG5hbWVfaGFzaDU04DrgJCS9AwoAbmV0d29ya19pZBcWwIwKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:chiseled_bookshelf", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQNAwAACAQAbmFtZRwAbWluZWNyYWZ0OmNoaXNlbGVkX2Jvb2tzaGVsZgQJAG5hbWVfaGFzaNXDBnsIsywYAwoAbmV0d29ya19pZIprt5IKBgBzdGF0ZXMDDABib29rc19zdG9yZWQAAAAAAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:lectern", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTBAQAACAQAbmFtZREAbWluZWNyYWZ0OmxlY3Rlcm4ECQBuYW1lX2hhc2j5Z4Mmi/1QxAMKAG5ldHdvcmtfaWR4JfDHCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgBCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:cauldron" + }, + { + "id": "minecraft:composter", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTUAQAACAQAbmFtZRMAbWluZWNyYWZ0OmNvbXBvc3RlcgQJAG5hbWVfaGFzaPAADHptzeWJAwoAbmV0d29ya19pZHIL6i4KBgBzdGF0ZXMDFABjb21wb3N0ZXJfZmlsbF9sZXZlbAAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:chest", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ2AAAACAQAbmFtZQ8AbWluZWNyYWZ0OmNoZXN0BAkAbmFtZV9oYXNog9ozMxlcA88DCgBuZXR3b3JrX2lkDkOFvAoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAG5vcnRoAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:trapped_chest", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSSAAAACAQAbmFtZRcAbWluZWNyYWZ0OnRyYXBwZWRfY2hlc3QECQBuYW1lX2hhc2g2qpF9stsEjgMKAG5ldHdvcmtfaWTjJWYxCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAbm9ydGgAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:ender_chest", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSCAAAACAQAbmFtZRUAbWluZWNyYWZ0OmVuZGVyX2NoZXN0BAkAbmFtZV9oYXNohEZzOFdg0WUDCgBuZXR3b3JrX2lkx4jiSQoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAG5vcnRoAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:barrel", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTKAQAACAQAbmFtZRAAbWluZWNyYWZ0OmJhcnJlbAQJAG5hbWVfaGFzaHDkRPGymiRqAwoAbmV0d29ya19pZPnxzgsKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:undyed_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTNAAAACAQAbmFtZRwAbWluZWNyYWZ0OnVuZHllZF9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaOC9mypm/MlBAwoAbmV0d29ya19pZJ8rxp0KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:white_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTaAAAACAQAbmFtZRsAbWluZWNyYWZ0OndoaXRlX3NodWxrZXJfYm94BAkAbmFtZV9oYXNosK79m1rPUBwDCgBuZXR3b3JrX2lkjrET6goGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:light_gray_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRrAwAACAQAbmFtZSAAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2iBe5zq7PxHmgMKAG5ldHdvcmtfaWSCVJv0CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:gray_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRqAwAACAQAbmFtZRoAbWluZWNyYWZ0OmdyYXlfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2ga2s8ctjHUhgMKAG5ldHdvcmtfaWS3WMsWCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:black_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRyAwAACAQAbmFtZRsAbWluZWNyYWZ0OmJsYWNrX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoPm03OZphrp8DCgBuZXR3b3JrX2lkXHztNAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:brown_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRvAwAACAQAbmFtZRsAbWluZWNyYWZ0OmJyb3duX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoT3DD6qAL9cADCgBuZXR3b3JrX2lkaXxpYQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:red_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRxAwAACAQAbmFtZRkAbWluZWNyYWZ0OnJlZF9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaMIlKSCzqSZoAwoAbmV0d29ya19pZNrf+icKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:orange_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRkAwAACAQAbmFtZRwAbWluZWNyYWZ0Om9yYW5nZV9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaG2MAXU67wGrAwoAbmV0d29ya19pZGoO05gKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:yellow_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRnAwAACAQAbmFtZRwAbWluZWNyYWZ0OnllbGxvd19zaHVsa2VyX2JveAQJAG5hbWVfaGFzaIsLwQHYjcIEAwoAbmV0d29ya19pZBCBSiYKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:lime_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRoAwAACAQAbmFtZRoAbWluZWNyYWZ0OmxpbWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2hUwBkg+faUGAMKAG5ldHdvcmtfaWRJeKqqCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:green_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRwAwAACAQAbmFtZRsAbWluZWNyYWZ0OmdyZWVuX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoZgUeT3LupLUDCgBuZXR3b3JrX2lkzJiohQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:cyan_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRsAwAACAQAbmFtZRoAbWluZWNyYWZ0OmN5YW5fc2h1bGtlcl9ib3gECQBuYW1lX2hhc2gSfbjteXg5yAMKAG5ldHdvcmtfaWTHeliECgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:light_blue_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRmAwAACAQAbmFtZSAAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2h0VFCX0qsRxQMKAG5ldHdvcmtfaWQXD8U0CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:blue_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRuAwAACAQAbmFtZRoAbWluZWNyYWZ0OmJsdWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2hn9gS0XIe6rAMKAG5ldHdvcmtfaWTO4PJaCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:purple_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRtAwAACAQAbmFtZRwAbWluZWNyYWZ0OnB1cnBsZV9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaEV/lkNPxRDdAwoAbmV0d29ya19pZFK25GAKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:magenta_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRlAwAACAQAbmFtZR0AbWluZWNyYWZ0Om1hZ2VudGFfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2iqWM7IJHxcFgMKAG5ldHdvcmtfaWTyyudTCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:pink_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRpAwAACAQAbmFtZRoAbWluZWNyYWZ0OnBpbmtfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2in1tkJ1GNcZgMKAG5ldHdvcmtfaWQOEGXjCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:armor_stand" + }, + { + "id": "minecraft:noteblock", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQZAAAACAQAbmFtZRMAbWluZWNyYWZ0Om5vdGVibG9jawQJAG5hbWVfaGFzaHPA8dBBH0UaAwoAbmV0d29ya19pZH1U5QkKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:jukebox", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRUAAAACAQAbmFtZREAbWluZWNyYWZ0Omp1a2Vib3gECQBuYW1lX2hhc2ieAIPExf/ZfgMKAG5ldHdvcmtfaWSmR7JfCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:music_disc_13" + }, + { + "id": "minecraft:music_disc_cat" + }, + { + "id": "minecraft:music_disc_blocks" + }, + { + "id": "minecraft:music_disc_chirp" + }, + { + "id": "minecraft:music_disc_far" + }, + { + "id": "minecraft:music_disc_mall" + }, + { + "id": "minecraft:music_disc_mellohi" + }, + { + "id": "minecraft:music_disc_stal" + }, + { + "id": "minecraft:music_disc_strad" + }, + { + "id": "minecraft:music_disc_ward" + }, + { + "id": "minecraft:music_disc_11" + }, + { + "id": "minecraft:music_disc_wait" + }, + { + "id": "minecraft:music_disc_otherside" + }, + { + "id": "minecraft:music_disc_5" + }, + { + "id": "minecraft:music_disc_pigstep" + }, + { + "id": "minecraft:music_disc_relic" + }, + { + "id": "minecraft:disc_fragment_5" + }, + { + "id": "minecraft:glowstone_dust" + }, + { + "id": "minecraft:glowstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRZAAAACAQAbmFtZRMAbWluZWNyYWZ0Omdsb3dzdG9uZQQJAG5hbWVfaGFzaFYqXNkefIlPAwoAbmV0d29ya19pZGT7WYYKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:redstone_lamp", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR7AAAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZHN0b25lX2xhbXAECQBuYW1lX2hhc2hJ9V80caPvEgMKAG5ldHdvcmtfaWRvNPwnCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:sea_lantern", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSpAAAACAQAbmFtZRUAbWluZWNyYWZ0OnNlYV9sYW50ZXJuBAkAbmFtZV9oYXNoLPsv1TX9M+QDCgBuZXR3b3JrX2lk1PPVyAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:oak_sign" + }, + { + "id": "minecraft:spruce_sign" + }, + { + "id": "minecraft:birch_sign" + }, + { + "id": "minecraft:jungle_sign" + }, + { + "id": "minecraft:acacia_sign" + }, + { + "id": "minecraft:dark_oak_sign" + }, + { + "id": "minecraft:mangrove_sign" + }, + { + "id": "minecraft:cherry_sign" + }, + { + "id": "minecraft:bamboo_sign" + }, + { + "id": "minecraft:crimson_sign" + }, + { + "id": "minecraft:warped_sign" + }, + { + "id": "minecraft:oak_hanging_sign" + }, + { + "id": "minecraft:spruce_hanging_sign" + }, + { + "id": "minecraft:birch_hanging_sign" + }, + { + "id": "minecraft:jungle_hanging_sign" + }, + { + "id": "minecraft:acacia_hanging_sign" + }, + { + "id": "minecraft:dark_oak_hanging_sign" + }, + { + "id": "minecraft:mangrove_hanging_sign" + }, + { + "id": "minecraft:cherry_hanging_sign" + }, + { + "id": "minecraft:bamboo_hanging_sign" + }, + { + "id": "minecraft:crimson_hanging_sign" + }, + { + "id": "minecraft:warped_hanging_sign" + }, + { + "id": "minecraft:painting" + }, + { + "id": "minecraft:frame" + }, + { + "id": "minecraft:glow_frame" + }, + { + "id": "minecraft:honey_bottle" + }, + { + "id": "minecraft:flower_pot" + }, + { + "id": "minecraft:bowl" + }, + { + "id": "minecraft:bucket" + }, + { + "id": "minecraft:milk_bucket" + }, + { + "id": "minecraft:water_bucket" + }, + { + "id": "minecraft:lava_bucket" + }, + { + "id": "minecraft:cod_bucket" + }, + { + "id": "minecraft:salmon_bucket" + }, + { + "id": "minecraft:tropical_fish_bucket" + }, + { + "id": "minecraft:pufferfish_bucket" + }, + { + "id": "minecraft:powder_snow_bucket" + }, + { + "id": "minecraft:axolotl_bucket" + }, + { + "id": "minecraft:tadpole_bucket" + }, + { + "id": "minecraft:skull", + "damage": 3 + }, + { + "id": "minecraft:skull", + "damage": 2 + }, + { + "id": "minecraft:skull", + "damage": 4 + }, + { + "id": "minecraft:skull", + "damage": 5 + }, + { + "id": "minecraft:skull" + }, + { + "id": "minecraft:skull", + "damage": 1 + }, + { + "id": "minecraft:skull", + "damage": 6 + }, + { + "id": "minecraft:beacon", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSKAAAACAQAbmFtZRAAbWluZWNyYWZ0OmJlYWNvbgQJAG5hbWVfaGFzaACwhhfSkdkHAwoAbmV0d29ya19pZF8jfiEKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:bell", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTNAQAACAQAbmFtZQ4AbWluZWNyYWZ0OmJlbGwECQBuYW1lX2hhc2iPqsgDXRcsxAMKAG5ldHdvcmtfaWT7zhOoCgYAc3RhdGVzCAoAYXR0YWNobWVudAgAc3RhbmRpbmcDCQBkaXJlY3Rpb24AAAAAAQoAdG9nZ2xlX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:conduit", + "block_state_b64": "CgAAAwgAYmxvY2tfaWScAQAACAQAbmFtZREAbWluZWNyYWZ0OmNvbmR1aXQECQBuYW1lX2hhc2jqxKAxq2EaWQMKAG5ldHdvcmtfaWTWcBVnCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:stonecutter_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTEAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lY3V0dGVyX2Jsb2NrBAkAbmFtZV9oYXNoQAXTbAM3MeYDCgBuZXR3b3JrX2lkWS4RjAoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAG5vcnRoAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:coal" + }, + { + "id": "minecraft:charcoal" + }, + { + "id": "minecraft:diamond" + }, + { + "id": "minecraft:iron_nugget" + }, + { + "id": "minecraft:raw_iron" + }, + { + "id": "minecraft:raw_gold" + }, + { + "id": "minecraft:raw_copper" + }, + { + "id": "minecraft:copper_ingot" + }, + { + "id": "minecraft:iron_ingot" + }, + { + "id": "minecraft:netherite_scrap" + }, + { + "id": "minecraft:netherite_ingot" + }, + { + "id": "minecraft:gold_nugget" + }, + { + "id": "minecraft:gold_ingot" + }, + { + "id": "minecraft:emerald" + }, + { + "id": "minecraft:quartz" + }, + { + "id": "minecraft:clay_ball" + }, + { + "id": "minecraft:brick" + }, + { + "id": "minecraft:netherbrick" + }, + { + "id": "minecraft:prismarine_shard" + }, + { + "id": "minecraft:amethyst_shard" + }, + { + "id": "minecraft:prismarine_crystals" + }, + { + "id": "minecraft:nautilus_shell" + }, + { + "id": "minecraft:heart_of_the_sea" + }, + { + "id": "minecraft:turtle_scute" + }, + { + "id": "minecraft:phantom_membrane" + }, + { + "id": "minecraft:string" + }, + { + "id": "minecraft:feather" + }, + { + "id": "minecraft:flint" + }, + { + "id": "minecraft:gunpowder" + }, + { + "id": "minecraft:leather" + }, + { + "id": "minecraft:rabbit_hide" + }, + { + "id": "minecraft:rabbit_foot" + }, + { + "id": "minecraft:fire_charge" + }, + { + "id": "minecraft:blaze_rod" + }, + { + "id": "minecraft:blaze_powder" + }, + { + "id": "minecraft:magma_cream" + }, + { + "id": "minecraft:fermented_spider_eye" + }, + { + "id": "minecraft:echo_shard" + }, + { + "id": "minecraft:dragon_breath" + }, + { + "id": "minecraft:shulker_shell" + }, + { + "id": "minecraft:ghast_tear" + }, + { + "id": "minecraft:slime_ball" + }, + { + "id": "minecraft:ender_pearl" + }, + { + "id": "minecraft:ender_eye" + }, + { + "id": "minecraft:nether_star" + }, + { + "id": "minecraft:end_rod", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTQAAAACAQAbmFtZREAbWluZWNyYWZ0OmVuZF9yb2QECQBuYW1lX2hhc2jx/q5cEA0hmQMKAG5ldHdvcmtfaWQ2eM8kCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:lightning_rod", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ3AgAACAQAbmFtZRcAbWluZWNyYWZ0OmxpZ2h0bmluZ19yb2QECQBuYW1lX2hhc2ioXQF1xvfHNQMKAG5ldHdvcmtfaWRLuHyACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:end_crystal" + }, + { + "id": "minecraft:paper" + }, + { + "id": "minecraft:book" + }, + { + "id": "minecraft:writable_book" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQFAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQFAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQFAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQGAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQGAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQGAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQHAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQHAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQHAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQIAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAUAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAUAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAUAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQMAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQMAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQNAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQNAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQOAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQOAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQOAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAUAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQQAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQRAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQRAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQRAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQSAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQSAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQSAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAUAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQUAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQUAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQVAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQWAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQXAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQXAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQXAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQYAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQYAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQYAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQZAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQZAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQaAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQbAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQcAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAUAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQeAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQeAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQeAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQfAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQfAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQfAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQgAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQhAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQjAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQjAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQjAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQkAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQkAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQkAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQlAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQlAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQlAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:oak_boat" + }, + { + "id": "minecraft:spruce_boat" + }, + { + "id": "minecraft:birch_boat" + }, + { + "id": "minecraft:jungle_boat" + }, + { + "id": "minecraft:acacia_boat" + }, + { + "id": "minecraft:dark_oak_boat" + }, + { + "id": "minecraft:mangrove_boat" + }, + { + "id": "minecraft:cherry_boat" + }, + { + "id": "minecraft:bamboo_raft" + }, + { + "id": "minecraft:oak_chest_boat" + }, + { + "id": "minecraft:spruce_chest_boat" + }, + { + "id": "minecraft:birch_chest_boat" + }, + { + "id": "minecraft:jungle_chest_boat" + }, + { + "id": "minecraft:acacia_chest_boat" + }, + { + "id": "minecraft:dark_oak_chest_boat" + }, + { + "id": "minecraft:mangrove_chest_boat" + }, + { + "id": "minecraft:cherry_chest_boat" + }, + { + "id": "minecraft:bamboo_chest_raft" + }, + { + "id": "minecraft:rail", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRCAAAACAQAbmFtZQ4AbWluZWNyYWZ0OnJhaWwECQBuYW1lX2hhc2hUzmhUXYJDUQMKAG5ldHdvcmtfaWR+Sp6YCgYAc3RhdGVzAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:golden_rail", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQbAAAACAQAbmFtZRUAbWluZWNyYWZ0OmdvbGRlbl9yYWlsBAkAbmFtZV9oYXNoOoV5MaKipoUDCgBuZXR3b3JrX2lkfAcxLwoGAHN0YXRlcwENAHJhaWxfZGF0YV9iaXQAAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:detector_rail", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQcAAAACAQAbmFtZRcAbWluZWNyYWZ0OmRldGVjdG9yX3JhaWwECQBuYW1lX2hhc2gVUk31qOysUQMKAG5ldHdvcmtfaWRVW/aICgYAc3RhdGVzAQ0AcmFpbF9kYXRhX2JpdAADDgByYWlsX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:activator_rail", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR+AAAACAQAbmFtZRgAbWluZWNyYWZ0OmFjdGl2YXRvcl9yYWlsBAkAbmFtZV9oYXNosIL91qriCRkDCgBuZXR3b3JrX2lkZfckmwoGAHN0YXRlcwENAHJhaWxfZGF0YV9iaXQAAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:minecart" + }, + { + "id": "minecraft:chest_minecart" + }, + { + "id": "minecraft:hopper_minecart" + }, + { + "id": "minecraft:tnt_minecart" + }, + { + "id": "minecraft:redstone" + }, + { + "id": "minecraft:redstone_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSYAAAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZHN0b25lX2Jsb2NrBAkAbmFtZV9oYXNoRhULL0r8o0sDCgBuZXR3b3JrX2lklayOHgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:redstone_torch", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRMAAAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZHN0b25lX3RvcmNoBAkAbmFtZV9oYXNoizFRjpYMIDgDCgBuZXR3b3JrX2lkuHz7yAoGAHN0YXRlcwgWAHRvcmNoX2ZhY2luZ19kaXJlY3Rpb24HAHVua25vd24AAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:lever", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRFAAAACAQAbmFtZQ8AbWluZWNyYWZ0OmxldmVyBAkAbmFtZV9oYXNoGMJeLJsUMLYDCgBuZXR3b3JrX2lkEF/GuAoGAHN0YXRlcwgPAGxldmVyX2RpcmVjdGlvbg4AZG93bl9lYXN0X3dlc3QBCABvcGVuX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:wooden_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSPAAAACAQAbmFtZRcAbWluZWNyYWZ0Ondvb2Rlbl9idXR0b24ECQBuYW1lX2hhc2hR7PgSTQt0sQMKAG5ldHdvcmtfaWSU07kYCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:spruce_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSPAQAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9idXR0b24ECQBuYW1lX2hhc2jBW9Z8aYE7YQMKAG5ldHdvcmtfaWTkUIGuCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:birch_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSMAQAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX2J1dHRvbgQJAG5hbWVfaGFzaJXYgGuSHbTwAwoAbmV0d29ya19pZGWp3yoKBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:jungle_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSOAQAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9idXR0b24ECQBuYW1lX2hhc2iCgNANcJs+BQMKAG5ldHdvcmtfaWT9fImWCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:acacia_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAQAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9idXR0b24ECQBuYW1lX2hhc2gVvmcT7LTO0wMKAG5ldHdvcmtfaWRQnxIJCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:dark_oak_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSNAQAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX2J1dHRvbgQJAG5hbWVfaGFzaIV10ZGGrCIEAwoAbmV0d29ya19pZN5vAmIKBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:mangrove_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTmAgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX2J1dHRvbgQJAG5hbWVfaGFzaNzeYYKLgOzJAwoAbmV0d29ya19pZAFEGQ0KBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:cherry_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQRAwAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9idXR0b24ECQBuYW1lX2hhc2j2/IHjeAbUcwMKAG5ldHdvcmtfaWRJ1irQCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:bamboo_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT+AgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19idXR0b24ECQBuYW1lX2hhc2j7AddMi+6nsgMKAG5ldHdvcmtfaWSa9w4/CgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:stone_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRNAAAACAQAbmFtZRYAbWluZWNyYWZ0OnN0b25lX2J1dHRvbgQJAG5hbWVfaGFzaM4ejMctmvohAwoAbmV0d29ya19pZMw+aC0KBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:crimson_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fYnV0dG9uBAkAbmFtZV9oYXNofnjYHaYIeWgDCgBuZXR3b3JrX2lk+n1vyQoGAHN0YXRlcwESAGJ1dHRvbl9wcmVzc2VkX2JpdAADEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:warped_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQEAgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9idXR0b24ECQBuYW1lX2hhc2jwkV2EU6Cn1QMKAG5ldHdvcmtfaWTnHnk1CgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:polished_blackstone_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQnAgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnV0dG9uBAkAbmFtZV9oYXNojmxzQKS0S/EDCgBuZXR3b3JrX2lkDtQ95woGAHN0YXRlcwESAGJ1dHRvbl9wcmVzc2VkX2JpdAADEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:tripwire_hook", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAAAACAQAbmFtZRcAbWluZWNyYWZ0OnRyaXB3aXJlX2hvb2sECQBuYW1lX2hhc2gQdp+oGZLNnAMKAG5ldHdvcmtfaWSy+1KJCgYAc3RhdGVzAQwAYXR0YWNoZWRfYml0AAMJAGRpcmVjdGlvbgAAAAABCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:wooden_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRIAAAACAQAbmFtZR8AbWluZWNyYWZ0Ondvb2Rlbl9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaGkGs5kCuA74AwoAbmV0d29ya19pZDRzPNwKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:spruce_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSZAQAACAQAbmFtZR8AbWluZWNyYWZ0OnNwcnVjZV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaNmwuq549fJKAwoAbmV0d29ya19pZLQMCw0KBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:birch_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSWAQAACAQAbmFtZR4AbWluZWNyYWZ0OmJpcmNoX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNorQkT9kDdlTwDCgBuZXR3b3JrX2lkH0G97AoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:jungle_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSYAQAACAQAbmFtZR8AbWluZWNyYWZ0Omp1bmdsZV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaJ7DcteCkb8/AwoAbmV0d29ya19pZLdPBSAKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:acacia_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSVAQAACAQAbmFtZR8AbWluZWNyYWZ0OmFjYWNpYV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaC2frZtfoYqCAwoAbmV0d29ya19pZIDdI18KBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:dark_oak_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSXAQAACAQAbmFtZSEAbWluZWNyYWZ0OmRhcmtfb2FrX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoHUCJsTy52pwDCgBuZXR3b3JrX2lkKpi8rAoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:mangrove_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTpAgAACAQAbmFtZSEAbWluZWNyYWZ0Om1hbmdyb3ZlX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoiDsTfJaX100DCgBuZXR3b3JrX2lkuwWDyQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:cherry_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQZAwAACAQAbmFtZR8AbWluZWNyYWZ0OmNoZXJyeV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaALMqYEZDUQHAwoAbmV0d29ya19pZPNT+r0KBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:bamboo_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQBAwAACAQAbmFtZR8AbWluZWNyYWZ0OmJhbWJvb19wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaNvxJ7NIAaqlAwoAbmV0d29ya19pZIZ8XnYKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:crimson_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQFAgAACAQAbmFtZSAAbWluZWNyYWZ0OmNyaW1zb25fcHJlc3N1cmVfcGxhdGUECQBuYW1lX2hhc2hqBDVDAd31/gMKAG5ldHdvcmtfaWRmV18LCgYAc3RhdGVzAw8AcmVkc3RvbmVfc2lnbmFsAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:warped_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAgAACAQAbmFtZR8AbWluZWNyYWZ0OndhcnBlZF9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaBxFoQksWtYUAwoAbmV0d29ya19pZJVRoIcKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:stone_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRGAAAACAQAbmFtZR4AbWluZWNyYWZ0OnN0b25lX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNounJuTBUTrU8DCgBuZXR3b3JrX2lkjDydwQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:light_weighted_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSTAAAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X3dlaWdodGVkX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoOyOJkNxLtkEDCgBuZXR3b3JrX2lkrr2AjgoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:heavy_weighted_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSUAAAACAQAbmFtZScAbWluZWNyYWZ0OmhlYXZ5X3dlaWdodGVkX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoltgDmDvTajUDCgBuZXR3b3JrX2lkFxVKuQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:polished_blackstone_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAgAACAQAbmFtZSwAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfcHJlc3N1cmVfcGxhdGUECQBuYW1lX2hhc2h65Ci6/CeGqwMKAG5ldHdvcmtfaWTaSW5xCgYAc3RhdGVzAw8AcmVkc3RvbmVfc2lnbmFsAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:observer", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT7AAAACAQAbmFtZRIAbWluZWNyYWZ0Om9ic2VydmVyBAkAbmFtZV9oYXNoYhlh1lpmHTgDCgBuZXR3b3JrX2lkQEh55goGAHN0YXRlcwgaAG1pbmVjcmFmdDpmYWNpbmdfZGlyZWN0aW9uBABkb3duAQsAcG93ZXJlZF9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:daylight_detector", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSXAAAACAQAbmFtZRsAbWluZWNyYWZ0OmRheWxpZ2h0X2RldGVjdG9yBAkAbmFtZV9oYXNoV0F0s7B7PVgDCgBuZXR3b3JrX2lkri5afQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:repeater" + }, + { + "id": "minecraft:comparator" + }, + { + "id": "minecraft:hopper" + }, + { + "id": "minecraft:dropper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR9AAAACAQAbmFtZREAbWluZWNyYWZ0OmRyb3BwZXIECQBuYW1lX2hhc2joXP7XqU0l3QMKAG5ldHdvcmtfaWQfQN6zCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgMAAAABDQB0cmlnZ2VyZWRfYml0AAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:dispenser", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQXAAAACAQAbmFtZRMAbWluZWNyYWZ0OmRpc3BlbnNlcgQJAG5hbWVfaGFzaP1RR+zAbYP2AwoAbmV0d29ya19pZGAayD0KBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAwAAAAENAHRyaWdnZXJlZF9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + }, + { + "id": "minecraft:piston", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQhAAAACAQAbmFtZRAAbWluZWNyYWZ0OnBpc3RvbgQJAG5hbWVfaGFzaDs3AFh1fL0uAwoAbmV0d29ya19pZLD/5XQKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAQAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:sticky_piston", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQdAAAACAQAbmFtZRcAbWluZWNyYWZ0OnN0aWNreV9waXN0b24ECQBuYW1lX2hhc2hPFJFJSiJ0ZQMKAG5ldHdvcmtfaWT/MzCJCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgEAAAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:tnt", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQuAAAACAQAbmFtZQ0AbWluZWNyYWZ0OnRudAQJAG5hbWVfaGFzaEYOHwCvJH29AwoAbmV0d29ya19pZCGfjU4KBgBzdGF0ZXMBFABhbGxvd191bmRlcndhdGVyX2JpdAABCwBleHBsb2RlX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:name_tag" + }, + { + "id": "minecraft:loom", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTLAQAACAQAbmFtZQ4AbWluZWNyYWZ0Omxvb20ECQBuYW1lX2hhc2i7DKjAXNq8TAMKAG5ldHdvcmtfaWR/49HXCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:banner", + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 8, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 7, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 15, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 12, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 14, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 1, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 4, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 5, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 13, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 9, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 3, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 11, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 10, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 2, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 6, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 15, + "nbt_b64": "CgAAAwQAVHlwZQEAAAAA" + }, + { + "id": "minecraft:creeper_banner_pattern" + }, + { + "id": "minecraft:skull_banner_pattern" + }, + { + "id": "minecraft:flower_banner_pattern" + }, + { + "id": "minecraft:mojang_banner_pattern" + }, + { + "id": "minecraft:field_masoned_banner_pattern" + }, + { + "id": "minecraft:bordure_indented_banner_pattern" + }, + { + "id": "minecraft:piglin_banner_pattern" + }, + { + "id": "minecraft:globe_banner_pattern" + }, + { + "id": "minecraft:angler_pottery_sherd" + }, + { + "id": "minecraft:archer_pottery_sherd" + }, + { + "id": "minecraft:arms_up_pottery_sherd" + }, + { + "id": "minecraft:blade_pottery_sherd" + }, + { + "id": "minecraft:brewer_pottery_sherd" + }, + { + "id": "minecraft:burn_pottery_sherd" + }, + { + "id": "minecraft:danger_pottery_sherd" + }, + { + "id": "minecraft:explorer_pottery_sherd" + }, + { + "id": "minecraft:friend_pottery_sherd" + }, + { + "id": "minecraft:heart_pottery_sherd" + }, + { + "id": "minecraft:heartbreak_pottery_sherd" + }, + { + "id": "minecraft:howl_pottery_sherd" + }, + { + "id": "minecraft:miner_pottery_sherd" + }, + { + "id": "minecraft:mourner_pottery_sherd" + }, + { + "id": "minecraft:plenty_pottery_sherd" + }, + { + "id": "minecraft:prize_pottery_sherd" + }, + { + "id": "minecraft:sheaf_pottery_sherd" + }, + { + "id": "minecraft:shelter_pottery_sherd" + }, + { + "id": "minecraft:skull_pottery_sherd" + }, + { + "id": "minecraft:snort_pottery_sherd" + }, + { + "id": "minecraft:netherite_upgrade_smithing_template" + }, + { + "id": "minecraft:sentry_armor_trim_smithing_template" + }, + { + "id": "minecraft:vex_armor_trim_smithing_template" + }, + { + "id": "minecraft:wild_armor_trim_smithing_template" + }, + { + "id": "minecraft:coast_armor_trim_smithing_template" + }, + { + "id": "minecraft:dune_armor_trim_smithing_template" + }, + { + "id": "minecraft:wayfinder_armor_trim_smithing_template" + }, + { + "id": "minecraft:shaper_armor_trim_smithing_template" + }, + { + "id": "minecraft:raiser_armor_trim_smithing_template" + }, + { + "id": "minecraft:host_armor_trim_smithing_template" + }, + { + "id": "minecraft:ward_armor_trim_smithing_template" + }, + { + "id": "minecraft:silence_armor_trim_smithing_template" + }, + { + "id": "minecraft:tide_armor_trim_smithing_template" + }, + { + "id": "minecraft:snout_armor_trim_smithing_template" + }, + { + "id": "minecraft:rib_armor_trim_smithing_template" + }, + { + "id": "minecraft:eye_armor_trim_smithing_template" + }, + { + "id": "minecraft:spire_armor_trim_smithing_template" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwAAAAAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAABwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAIBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAHBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAPBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAMBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAOBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAABBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAEBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAFBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAANBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAJBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAADBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAALBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAKBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAACBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAGBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_star", + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yIR0d/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 8, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yUk9H/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 7, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yl52d/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 15, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9y8PDw/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 12, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9y2rM6/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 14, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yHYD5/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 1, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yJi6w/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 4, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yqkQ8/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 5, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yuDKJ/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 13, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yvU7H/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 9, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yqovz/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 3, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yMlSD/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 11, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yPdj+/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 10, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yH8eA/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 2, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yFnxe/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 6, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9ynJwW/wA=" + }, + { + "id": "minecraft:chain" + }, + { + "id": "minecraft:target", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTuAQAACAQAbmFtZRAAbWluZWNyYWZ0OnRhcmdldAQJAG5hbWVfaGFzaJc66SVbYlaxAwoAbmV0d29ya19pZPBozs0KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + }, + { + "id": "minecraft:decorated_pot", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAwAACAQAbmFtZRcAbWluZWNyYWZ0OmRlY29yYXRlZF9wb3QECQBuYW1lX2hhc2jjQgckn8VTvwMKAG5ldHdvcmtfaWRwvkUUCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + }, + { + "id": "minecraft:lodestone_compass" + }, + { + "id": "minecraft:wither_spawn_egg" + }, + { + "id": "minecraft:ender_dragon_spawn_egg" + } + ] +} \ No newline at end of file diff --git a/core/src/main/resources/bedrock/entity_identifiers.dat b/core/src/main/resources/bedrock/entity_identifiers.dat index 4e8d836c6df13ee61cc445e7edf97d83af9a75b7..9a986cf5c435ac467cac73c25a0ba160cbfbb0be 100644 GIT binary patch delta 37 tcmX?Sd(L)4nbhPBQrwfPWb7vImNK3!&&WNwQA&UFJEp<{dI(OaL9R4YL3M diff --git a/core/src/main/resources/bedrock/runtime_item_states.1_20_70.json b/core/src/main/resources/bedrock/runtime_item_states.1_20_70.json new file mode 100644 index 000000000..887b89ba1 --- /dev/null +++ b/core/src/main/resources/bedrock/runtime_item_states.1_20_70.json @@ -0,0 +1,6126 @@ +[ + { + "name": "minecraft:acacia_boat", + "id": 383 + }, + { + "name": "minecraft:acacia_button", + "id": -140 + }, + { + "name": "minecraft:acacia_chest_boat", + "id": 653 + }, + { + "name": "minecraft:acacia_door", + "id": 567 + }, + { + "name": "minecraft:acacia_double_slab", + "id": -812 + }, + { + "name": "minecraft:acacia_fence", + "id": -575 + }, + { + "name": "minecraft:acacia_fence_gate", + "id": 187 + }, + { + "name": "minecraft:acacia_hanging_sign", + "id": -504 + }, + { + "name": "minecraft:acacia_leaves", + "id": 161 + }, + { + "name": "minecraft:acacia_log", + "id": 162 + }, + { + "name": "minecraft:acacia_planks", + "id": -742 + }, + { + "name": "minecraft:acacia_pressure_plate", + "id": -150 + }, + { + "name": "minecraft:acacia_sign", + "id": 590 + }, + { + "name": "minecraft:acacia_slab", + "id": -807 + }, + { + "name": "minecraft:acacia_stairs", + "id": 163 + }, + { + "name": "minecraft:acacia_standing_sign", + "id": -190 + }, + { + "name": "minecraft:acacia_trapdoor", + "id": -145 + }, + { + "name": "minecraft:acacia_wall_sign", + "id": -191 + }, + { + "name": "minecraft:acacia_wood", + "id": -817 + }, + { + "name": "minecraft:activator_rail", + "id": 126 + }, + { + "name": "minecraft:agent_spawn_egg", + "id": 492 + }, + { + "name": "minecraft:air", + "id": -158 + }, + { + "name": "minecraft:allay_spawn_egg", + "id": 642 + }, + { + "name": "minecraft:allow", + "id": 210 + }, + { + "name": "minecraft:amethyst_block", + "id": -327 + }, + { + "name": "minecraft:amethyst_cluster", + "id": -329 + }, + { + "name": "minecraft:amethyst_shard", + "id": 635 + }, + { + "name": "minecraft:ancient_debris", + "id": -271 + }, + { + "name": "minecraft:andesite", + "id": -594 + }, + { + "name": "minecraft:andesite_stairs", + "id": -171 + }, + { + "name": "minecraft:angler_pottery_sherd", + "id": 667 + }, + { + "name": "minecraft:anvil", + "id": 145 + }, + { + "name": "minecraft:apple", + "id": 257 + }, + { + "name": "minecraft:archer_pottery_sherd", + "id": 668 + }, + { + "name": "minecraft:armadillo_scute", + "id": 709 + }, + { + "name": "minecraft:armadillo_spawn_egg", + "id": 708 + }, + { + "name": "minecraft:armor_stand", + "id": 563 + }, + { + "name": "minecraft:arms_up_pottery_sherd", + "id": 669 + }, + { + "name": "minecraft:arrow", + "id": 304 + }, + { + "name": "minecraft:axolotl_bucket", + "id": 372 + }, + { + "name": "minecraft:axolotl_spawn_egg", + "id": 507 + }, + { + "name": "minecraft:azalea", + "id": -337 + }, + { + "name": "minecraft:azalea_leaves", + "id": -324 + }, + { + "name": "minecraft:azalea_leaves_flowered", + "id": -325 + }, + { + "name": "minecraft:baked_potato", + "id": 282 + }, + { + "name": "minecraft:balloon", + "id": 609 + }, + { + "name": "minecraft:bamboo", + "id": -163 + }, + { + "name": "minecraft:bamboo_block", + "id": -527 + }, + { + "name": "minecraft:bamboo_button", + "id": -511 + }, + { + "name": "minecraft:bamboo_chest_raft", + "id": 665 + }, + { + "name": "minecraft:bamboo_door", + "id": -517 + }, + { + "name": "minecraft:bamboo_double_slab", + "id": -521 + }, + { + "name": "minecraft:bamboo_fence", + "id": -515 + }, + { + "name": "minecraft:bamboo_fence_gate", + "id": -516 + }, + { + "name": "minecraft:bamboo_hanging_sign", + "id": -522 + }, + { + "name": "minecraft:bamboo_mosaic", + "id": -509 + }, + { + "name": "minecraft:bamboo_mosaic_double_slab", + "id": -525 + }, + { + "name": "minecraft:bamboo_mosaic_slab", + "id": -524 + }, + { + "name": "minecraft:bamboo_mosaic_stairs", + "id": -523 + }, + { + "name": "minecraft:bamboo_planks", + "id": -510 + }, + { + "name": "minecraft:bamboo_pressure_plate", + "id": -514 + }, + { + "name": "minecraft:bamboo_raft", + "id": 664 + }, + { + "name": "minecraft:bamboo_sapling", + "id": -164 + }, + { + "name": "minecraft:bamboo_sign", + "id": 663 + }, + { + "name": "minecraft:bamboo_slab", + "id": -513 + }, + { + "name": "minecraft:bamboo_stairs", + "id": -512 + }, + { + "name": "minecraft:bamboo_standing_sign", + "id": -518 + }, + { + "name": "minecraft:bamboo_trapdoor", + "id": -520 + }, + { + "name": "minecraft:bamboo_wall_sign", + "id": -519 + }, + { + "name": "minecraft:banner", + "id": 578 + }, + { + "name": "minecraft:banner_pattern", + "id": 731 + }, + { + "name": "minecraft:barrel", + "id": -203 + }, + { + "name": "minecraft:barrier", + "id": -161 + }, + { + "name": "minecraft:basalt", + "id": -234 + }, + { + "name": "minecraft:bat_spawn_egg", + "id": 457 + }, + { + "name": "minecraft:beacon", + "id": 138 + }, + { + "name": "minecraft:bed", + "id": 422 + }, + { + "name": "minecraft:bedrock", + "id": 7 + }, + { + "name": "minecraft:bee_nest", + "id": -218 + }, + { + "name": "minecraft:bee_spawn_egg", + "id": 499 + }, + { + "name": "minecraft:beef", + "id": 274 + }, + { + "name": "minecraft:beehive", + "id": -219 + }, + { + "name": "minecraft:beetroot", + "id": 286 + }, + { + "name": "minecraft:beetroot_seeds", + "id": 296 + }, + { + "name": "minecraft:beetroot_soup", + "id": 287 + }, + { + "name": "minecraft:bell", + "id": -206 + }, + { + "name": "minecraft:big_dripleaf", + "id": -323 + }, + { + "name": "minecraft:birch_boat", + "id": 380 + }, + { + "name": "minecraft:birch_button", + "id": -141 + }, + { + "name": "minecraft:birch_chest_boat", + "id": 650 + }, + { + "name": "minecraft:birch_door", + "id": 565 + }, + { + "name": "minecraft:birch_double_slab", + "id": -810 + }, + { + "name": "minecraft:birch_fence", + "id": -576 + }, + { + "name": "minecraft:birch_fence_gate", + "id": 184 + }, + { + "name": "minecraft:birch_hanging_sign", + "id": -502 + }, + { + "name": "minecraft:birch_leaves", + "id": -801 + }, + { + "name": "minecraft:birch_log", + "id": -570 + }, + { + "name": "minecraft:birch_planks", + "id": -740 + }, + { + "name": "minecraft:birch_pressure_plate", + "id": -151 + }, + { + "name": "minecraft:birch_sign", + "id": 588 + }, + { + "name": "minecraft:birch_slab", + "id": -805 + }, + { + "name": "minecraft:birch_stairs", + "id": 135 + }, + { + "name": "minecraft:birch_standing_sign", + "id": -186 + }, + { + "name": "minecraft:birch_trapdoor", + "id": -146 + }, + { + "name": "minecraft:birch_wall_sign", + "id": -187 + }, + { + "name": "minecraft:birch_wood", + "id": -815 + }, + { + "name": "minecraft:black_candle", + "id": -428 + }, + { + "name": "minecraft:black_candle_cake", + "id": -445 + }, + { + "name": "minecraft:black_carpet", + "id": -611 + }, + { + "name": "minecraft:black_concrete", + "id": -642 + }, + { + "name": "minecraft:black_concrete_powder", + "id": -723 + }, + { + "name": "minecraft:black_dye", + "id": 399 + }, + { + "name": "minecraft:black_glazed_terracotta", + "id": 235 + }, + { + "name": "minecraft:black_shulker_box", + "id": -627 + }, + { + "name": "minecraft:black_stained_glass", + "id": -687 + }, + { + "name": "minecraft:black_stained_glass_pane", + "id": -657 + }, + { + "name": "minecraft:black_terracotta", + "id": -738 + }, + { + "name": "minecraft:black_wool", + "id": -554 + }, + { + "name": "minecraft:blackstone", + "id": -273 + }, + { + "name": "minecraft:blackstone_double_slab", + "id": -283 + }, + { + "name": "minecraft:blackstone_slab", + "id": -282 + }, + { + "name": "minecraft:blackstone_stairs", + "id": -276 + }, + { + "name": "minecraft:blackstone_wall", + "id": -277 + }, + { + "name": "minecraft:blade_pottery_sherd", + "id": 670 + }, + { + "name": "minecraft:blast_furnace", + "id": -196 + }, + { + "name": "minecraft:blaze_powder", + "id": 433 + }, + { + "name": "minecraft:blaze_rod", + "id": 427 + }, + { + "name": "minecraft:blaze_spawn_egg", + "id": 460 + }, + { + "name": "minecraft:bleach", + "id": 607 + }, + { + "name": "minecraft:blue_candle", + "id": -424 + }, + { + "name": "minecraft:blue_candle_cake", + "id": -441 + }, + { + "name": "minecraft:blue_carpet", + "id": -607 + }, + { + "name": "minecraft:blue_concrete", + "id": -638 + }, + { + "name": "minecraft:blue_concrete_powder", + "id": -719 + }, + { + "name": "minecraft:blue_dye", + "id": 403 + }, + { + "name": "minecraft:blue_glazed_terracotta", + "id": 231 + }, + { + "name": "minecraft:blue_ice", + "id": -11 + }, + { + "name": "minecraft:blue_shulker_box", + "id": -623 + }, + { + "name": "minecraft:blue_stained_glass", + "id": -683 + }, + { + "name": "minecraft:blue_stained_glass_pane", + "id": -653 + }, + { + "name": "minecraft:blue_terracotta", + "id": -734 + }, + { + "name": "minecraft:blue_wool", + "id": -563 + }, + { + "name": "minecraft:boat", + "id": 729 + }, + { + "name": "minecraft:bogged_spawn_egg", + "id": 467 + }, + { + "name": "minecraft:bone", + "id": 419 + }, + { + "name": "minecraft:bone_block", + "id": 216 + }, + { + "name": "minecraft:bone_meal", + "id": 415 + }, + { + "name": "minecraft:book", + "id": 391 + }, + { + "name": "minecraft:bookshelf", + "id": 47 + }, + { + "name": "minecraft:border_block", + "id": 212 + }, + { + "name": "minecraft:bordure_indented_banner_pattern", + "id": 597 + }, + { + "name": "minecraft:bow", + "id": 303 + }, + { + "name": "minecraft:bowl", + "id": 324 + }, + { + "name": "minecraft:brain_coral", + "id": -581 + }, + { + "name": "minecraft:bread", + "id": 262 + }, + { + "name": "minecraft:breeze_spawn_egg", + "id": 506 + }, + { + "name": "minecraft:brewer_pottery_sherd", + "id": 671 + }, + { + "name": "minecraft:brewing_stand", + "id": 435 + }, + { + "name": "minecraft:brick", + "id": 387 + }, + { + "name": "minecraft:brick_block", + "id": 45 + }, + { + "name": "minecraft:brick_stairs", + "id": 108 + }, + { + "name": "minecraft:brown_candle", + "id": -425 + }, + { + "name": "minecraft:brown_candle_cake", + "id": -442 + }, + { + "name": "minecraft:brown_carpet", + "id": -608 + }, + { + "name": "minecraft:brown_concrete", + "id": -639 + }, + { + "name": "minecraft:brown_concrete_powder", + "id": -720 + }, + { + "name": "minecraft:brown_dye", + "id": 402 + }, + { + "name": "minecraft:brown_glazed_terracotta", + "id": 232 + }, + { + "name": "minecraft:brown_mushroom", + "id": 39 + }, + { + "name": "minecraft:brown_mushroom_block", + "id": 99 + }, + { + "name": "minecraft:brown_shulker_box", + "id": -624 + }, + { + "name": "minecraft:brown_stained_glass", + "id": -684 + }, + { + "name": "minecraft:brown_stained_glass_pane", + "id": -654 + }, + { + "name": "minecraft:brown_terracotta", + "id": -735 + }, + { + "name": "minecraft:brown_wool", + "id": -555 + }, + { + "name": "minecraft:brush", + "id": 687 + }, + { + "name": "minecraft:bubble_column", + "id": -160 + }, + { + "name": "minecraft:bubble_coral", + "id": -582 + }, + { + "name": "minecraft:bucket", + "id": 363 + }, + { + "name": "minecraft:budding_amethyst", + "id": -328 + }, + { + "name": "minecraft:burn_pottery_sherd", + "id": 672 + }, + { + "name": "minecraft:cactus", + "id": 81 + }, + { + "name": "minecraft:cake", + "id": 421 + }, + { + "name": "minecraft:calcite", + "id": -326 + }, + { + "name": "minecraft:calibrated_sculk_sensor", + "id": -580 + }, + { + "name": "minecraft:camel_spawn_egg", + "id": 666 + }, + { + "name": "minecraft:camera", + "id": 604 + }, + { + "name": "minecraft:campfire", + "id": 600 + }, + { + "name": "minecraft:candle", + "id": -412 + }, + { + "name": "minecraft:candle_cake", + "id": -429 + }, + { + "name": "minecraft:carpet", + "id": 712 + }, + { + "name": "minecraft:carrot", + "id": 280 + }, + { + "name": "minecraft:carrot_on_a_stick", + "id": 528 + }, + { + "name": "minecraft:carrots", + "id": 141 + }, + { + "name": "minecraft:cartography_table", + "id": -200 + }, + { + "name": "minecraft:carved_pumpkin", + "id": -155 + }, + { + "name": "minecraft:cat_spawn_egg", + "id": 493 + }, + { + "name": "minecraft:cauldron", + "id": 436 + }, + { + "name": "minecraft:cave_spider_spawn_egg", + "id": 461 + }, + { + "name": "minecraft:cave_vines", + "id": -322 + }, + { + "name": "minecraft:cave_vines_body_with_berries", + "id": -375 + }, + { + "name": "minecraft:cave_vines_head_with_berries", + "id": -376 + }, + { + "name": "minecraft:chain", + "id": 630 + }, + { + "name": "minecraft:chain_command_block", + "id": 189 + }, + { + "name": "minecraft:chainmail_boots", + "id": 345 + }, + { + "name": "minecraft:chainmail_chestplate", + "id": 343 + }, + { + "name": "minecraft:chainmail_helmet", + "id": 342 + }, + { + "name": "minecraft:chainmail_leggings", + "id": 344 + }, + { + "name": "minecraft:charcoal", + "id": 306 + }, + { + "name": "minecraft:chemical_heat", + "id": 192 + }, + { + "name": "minecraft:chemistry_table", + "id": 238 + }, + { + "name": "minecraft:cherry_boat", + "id": 660 + }, + { + "name": "minecraft:cherry_button", + "id": -530 + }, + { + "name": "minecraft:cherry_chest_boat", + "id": 661 + }, + { + "name": "minecraft:cherry_door", + "id": -531 + }, + { + "name": "minecraft:cherry_double_slab", + "id": -540 + }, + { + "name": "minecraft:cherry_fence", + "id": -532 + }, + { + "name": "minecraft:cherry_fence_gate", + "id": -533 + }, + { + "name": "minecraft:cherry_hanging_sign", + "id": -534 + }, + { + "name": "minecraft:cherry_leaves", + "id": -548 + }, + { + "name": "minecraft:cherry_log", + "id": -536 + }, + { + "name": "minecraft:cherry_planks", + "id": -537 + }, + { + "name": "minecraft:cherry_pressure_plate", + "id": -538 + }, + { + "name": "minecraft:cherry_sapling", + "id": -547 + }, + { + "name": "minecraft:cherry_sign", + "id": 662 + }, + { + "name": "minecraft:cherry_slab", + "id": -539 + }, + { + "name": "minecraft:cherry_stairs", + "id": -541 + }, + { + "name": "minecraft:cherry_standing_sign", + "id": -542 + }, + { + "name": "minecraft:cherry_trapdoor", + "id": -543 + }, + { + "name": "minecraft:cherry_wall_sign", + "id": -544 + }, + { + "name": "minecraft:cherry_wood", + "id": -546 + }, + { + "name": "minecraft:chest", + "id": 54 + }, + { + "name": "minecraft:chest_boat", + "id": 656 + }, + { + "name": "minecraft:chest_minecart", + "id": 393 + }, + { + "name": "minecraft:chicken", + "id": 276 + }, + { + "name": "minecraft:chicken_spawn_egg", + "id": 439 + }, + { + "name": "minecraft:chiseled_bookshelf", + "id": -526 + }, + { + "name": "minecraft:chiseled_copper", + "id": -760 + }, + { + "name": "minecraft:chiseled_deepslate", + "id": -395 + }, + { + "name": "minecraft:chiseled_nether_bricks", + "id": -302 + }, + { + "name": "minecraft:chiseled_polished_blackstone", + "id": -279 + }, + { + "name": "minecraft:chiseled_tuff", + "id": -753 + }, + { + "name": "minecraft:chiseled_tuff_bricks", + "id": -759 + }, + { + "name": "minecraft:chorus_flower", + "id": 200 + }, + { + "name": "minecraft:chorus_fruit", + "id": 569 + }, + { + "name": "minecraft:chorus_plant", + "id": 240 + }, + { + "name": "minecraft:clay", + "id": 82 + }, + { + "name": "minecraft:clay_ball", + "id": 388 + }, + { + "name": "minecraft:client_request_placeholder_block", + "id": -465 + }, + { + "name": "minecraft:clock", + "id": 397 + }, + { + "name": "minecraft:coal", + "id": 305 + }, + { + "name": "minecraft:coal_block", + "id": 173 + }, + { + "name": "minecraft:coal_ore", + "id": 16 + }, + { + "name": "minecraft:coast_armor_trim_smithing_template", + "id": 691 + }, + { + "name": "minecraft:cobbled_deepslate", + "id": -379 + }, + { + "name": "minecraft:cobbled_deepslate_double_slab", + "id": -396 + }, + { + "name": "minecraft:cobbled_deepslate_slab", + "id": -380 + }, + { + "name": "minecraft:cobbled_deepslate_stairs", + "id": -381 + }, + { + "name": "minecraft:cobbled_deepslate_wall", + "id": -382 + }, + { + "name": "minecraft:cobblestone", + "id": 4 + }, + { + "name": "minecraft:cobblestone_wall", + "id": 139 + }, + { + "name": "minecraft:cocoa", + "id": 127 + }, + { + "name": "minecraft:cocoa_beans", + "id": 416 + }, + { + "name": "minecraft:cod", + "id": 265 + }, + { + "name": "minecraft:cod_bucket", + "id": 367 + }, + { + "name": "minecraft:cod_spawn_egg", + "id": 485 + }, + { + "name": "minecraft:colored_torch_bp", + "id": 204 + }, + { + "name": "minecraft:colored_torch_rg", + "id": 202 + }, + { + "name": "minecraft:command_block", + "id": 137 + }, + { + "name": "minecraft:command_block_minecart", + "id": 574 + }, + { + "name": "minecraft:comparator", + "id": 533 + }, + { + "name": "minecraft:compass", + "id": 395 + }, + { + "name": "minecraft:composter", + "id": -213 + }, + { + "name": "minecraft:compound", + "id": 605 + }, + { + "name": "minecraft:concrete", + "id": 721 + }, + { + "name": "minecraft:concrete_powder", + "id": 722 + }, + { + "name": "minecraft:conduit", + "id": -157 + }, + { + "name": "minecraft:cooked_beef", + "id": 275 + }, + { + "name": "minecraft:cooked_chicken", + "id": 277 + }, + { + "name": "minecraft:cooked_cod", + "id": 269 + }, + { + "name": "minecraft:cooked_mutton", + "id": 562 + }, + { + "name": "minecraft:cooked_porkchop", + "id": 264 + }, + { + "name": "minecraft:cooked_rabbit", + "id": 290 + }, + { + "name": "minecraft:cooked_salmon", + "id": 270 + }, + { + "name": "minecraft:cookie", + "id": 272 + }, + { + "name": "minecraft:copper_block", + "id": -340 + }, + { + "name": "minecraft:copper_bulb", + "id": -776 + }, + { + "name": "minecraft:copper_door", + "id": -784 + }, + { + "name": "minecraft:copper_grate", + "id": -768 + }, + { + "name": "minecraft:copper_ingot", + "id": 515 + }, + { + "name": "minecraft:copper_ore", + "id": -311 + }, + { + "name": "minecraft:copper_trapdoor", + "id": -792 + }, + { + "name": "minecraft:coral", + "id": 719 + }, + { + "name": "minecraft:coral_block", + "id": -132 + }, + { + "name": "minecraft:coral_fan", + "id": -133 + }, + { + "name": "minecraft:coral_fan_dead", + "id": -134 + }, + { + "name": "minecraft:coral_fan_hang", + "id": -135 + }, + { + "name": "minecraft:coral_fan_hang2", + "id": -136 + }, + { + "name": "minecraft:coral_fan_hang3", + "id": -137 + }, + { + "name": "minecraft:cow_spawn_egg", + "id": 440 + }, + { + "name": "minecraft:cracked_deepslate_bricks", + "id": -410 + }, + { + "name": "minecraft:cracked_deepslate_tiles", + "id": -409 + }, + { + "name": "minecraft:cracked_nether_bricks", + "id": -303 + }, + { + "name": "minecraft:cracked_polished_blackstone_bricks", + "id": -280 + }, + { + "name": "minecraft:crafter", + "id": -313 + }, + { + "name": "minecraft:crafting_table", + "id": 58 + }, + { + "name": "minecraft:creeper_banner_pattern", + "id": 593 + }, + { + "name": "minecraft:creeper_spawn_egg", + "id": 445 + }, + { + "name": "minecraft:crimson_button", + "id": -260 + }, + { + "name": "minecraft:crimson_door", + "id": 627 + }, + { + "name": "minecraft:crimson_double_slab", + "id": -266 + }, + { + "name": "minecraft:crimson_fence", + "id": -256 + }, + { + "name": "minecraft:crimson_fence_gate", + "id": -258 + }, + { + "name": "minecraft:crimson_fungus", + "id": -228 + }, + { + "name": "minecraft:crimson_hanging_sign", + "id": -506 + }, + { + "name": "minecraft:crimson_hyphae", + "id": -299 + }, + { + "name": "minecraft:crimson_nylium", + "id": -232 + }, + { + "name": "minecraft:crimson_planks", + "id": -242 + }, + { + "name": "minecraft:crimson_pressure_plate", + "id": -262 + }, + { + "name": "minecraft:crimson_roots", + "id": -223 + }, + { + "name": "minecraft:crimson_sign", + "id": 625 + }, + { + "name": "minecraft:crimson_slab", + "id": -264 + }, + { + "name": "minecraft:crimson_stairs", + "id": -254 + }, + { + "name": "minecraft:crimson_standing_sign", + "id": -250 + }, + { + "name": "minecraft:crimson_stem", + "id": -225 + }, + { + "name": "minecraft:crimson_trapdoor", + "id": -246 + }, + { + "name": "minecraft:crimson_wall_sign", + "id": -252 + }, + { + "name": "minecraft:crossbow", + "id": 586 + }, + { + "name": "minecraft:crying_obsidian", + "id": -289 + }, + { + "name": "minecraft:cut_copper", + "id": -347 + }, + { + "name": "minecraft:cut_copper_slab", + "id": -361 + }, + { + "name": "minecraft:cut_copper_stairs", + "id": -354 + }, + { + "name": "minecraft:cyan_candle", + "id": -422 + }, + { + "name": "minecraft:cyan_candle_cake", + "id": -439 + }, + { + "name": "minecraft:cyan_carpet", + "id": -605 + }, + { + "name": "minecraft:cyan_concrete", + "id": -636 + }, + { + "name": "minecraft:cyan_concrete_powder", + "id": -717 + }, + { + "name": "minecraft:cyan_dye", + "id": 405 + }, + { + "name": "minecraft:cyan_glazed_terracotta", + "id": 229 + }, + { + "name": "minecraft:cyan_shulker_box", + "id": -621 + }, + { + "name": "minecraft:cyan_stained_glass", + "id": -681 + }, + { + "name": "minecraft:cyan_stained_glass_pane", + "id": -651 + }, + { + "name": "minecraft:cyan_terracotta", + "id": -732 + }, + { + "name": "minecraft:cyan_wool", + "id": -561 + }, + { + "name": "minecraft:danger_pottery_sherd", + "id": 673 + }, + { + "name": "minecraft:dark_oak_boat", + "id": 384 + }, + { + "name": "minecraft:dark_oak_button", + "id": -142 + }, + { + "name": "minecraft:dark_oak_chest_boat", + "id": 654 + }, + { + "name": "minecraft:dark_oak_door", + "id": 568 + }, + { + "name": "minecraft:dark_oak_double_slab", + "id": -813 + }, + { + "name": "minecraft:dark_oak_fence", + "id": -577 + }, + { + "name": "minecraft:dark_oak_fence_gate", + "id": 186 + }, + { + "name": "minecraft:dark_oak_hanging_sign", + "id": -505 + }, + { + "name": "minecraft:dark_oak_leaves", + "id": -803 + }, + { + "name": "minecraft:dark_oak_log", + "id": -572 + }, + { + "name": "minecraft:dark_oak_planks", + "id": -743 + }, + { + "name": "minecraft:dark_oak_pressure_plate", + "id": -152 + }, + { + "name": "minecraft:dark_oak_sign", + "id": 591 + }, + { + "name": "minecraft:dark_oak_slab", + "id": -808 + }, + { + "name": "minecraft:dark_oak_stairs", + "id": 164 + }, + { + "name": "minecraft:dark_oak_trapdoor", + "id": -147 + }, + { + "name": "minecraft:dark_oak_wood", + "id": -818 + }, + { + "name": "minecraft:dark_prismarine_stairs", + "id": -3 + }, + { + "name": "minecraft:darkoak_standing_sign", + "id": -192 + }, + { + "name": "minecraft:darkoak_wall_sign", + "id": -193 + }, + { + "name": "minecraft:daylight_detector", + "id": 151 + }, + { + "name": "minecraft:daylight_detector_inverted", + "id": 178 + }, + { + "name": "minecraft:dead_brain_coral", + "id": -586 + }, + { + "name": "minecraft:dead_bubble_coral", + "id": -587 + }, + { + "name": "minecraft:dead_fire_coral", + "id": -588 + }, + { + "name": "minecraft:dead_horn_coral", + "id": -589 + }, + { + "name": "minecraft:dead_tube_coral", + "id": -585 + }, + { + "name": "minecraft:deadbush", + "id": 32 + }, + { + "name": "minecraft:decorated_pot", + "id": -551 + }, + { + "name": "minecraft:deepslate", + "id": -378 + }, + { + "name": "minecraft:deepslate_brick_double_slab", + "id": -399 + }, + { + "name": "minecraft:deepslate_brick_slab", + "id": -392 + }, + { + "name": "minecraft:deepslate_brick_stairs", + "id": -393 + }, + { + "name": "minecraft:deepslate_brick_wall", + "id": -394 + }, + { + "name": "minecraft:deepslate_bricks", + "id": -391 + }, + { + "name": "minecraft:deepslate_coal_ore", + "id": -406 + }, + { + "name": "minecraft:deepslate_copper_ore", + "id": -408 + }, + { + "name": "minecraft:deepslate_diamond_ore", + "id": -405 + }, + { + "name": "minecraft:deepslate_emerald_ore", + "id": -407 + }, + { + "name": "minecraft:deepslate_gold_ore", + "id": -402 + }, + { + "name": "minecraft:deepslate_iron_ore", + "id": -401 + }, + { + "name": "minecraft:deepslate_lapis_ore", + "id": -400 + }, + { + "name": "minecraft:deepslate_redstone_ore", + "id": -403 + }, + { + "name": "minecraft:deepslate_tile_double_slab", + "id": -398 + }, + { + "name": "minecraft:deepslate_tile_slab", + "id": -388 + }, + { + "name": "minecraft:deepslate_tile_stairs", + "id": -389 + }, + { + "name": "minecraft:deepslate_tile_wall", + "id": -390 + }, + { + "name": "minecraft:deepslate_tiles", + "id": -387 + }, + { + "name": "minecraft:deny", + "id": 211 + }, + { + "name": "minecraft:detector_rail", + "id": 28 + }, + { + "name": "minecraft:diamond", + "id": 307 + }, + { + "name": "minecraft:diamond_axe", + "id": 322 + }, + { + "name": "minecraft:diamond_block", + "id": 57 + }, + { + "name": "minecraft:diamond_boots", + "id": 353 + }, + { + "name": "minecraft:diamond_chestplate", + "id": 351 + }, + { + "name": "minecraft:diamond_helmet", + "id": 350 + }, + { + "name": "minecraft:diamond_hoe", + "id": 335 + }, + { + "name": "minecraft:diamond_horse_armor", + "id": 544 + }, + { + "name": "minecraft:diamond_leggings", + "id": 352 + }, + { + "name": "minecraft:diamond_ore", + "id": 56 + }, + { + "name": "minecraft:diamond_pickaxe", + "id": 321 + }, + { + "name": "minecraft:diamond_shovel", + "id": 320 + }, + { + "name": "minecraft:diamond_sword", + "id": 319 + }, + { + "name": "minecraft:diorite", + "id": -592 + }, + { + "name": "minecraft:diorite_stairs", + "id": -170 + }, + { + "name": "minecraft:dirt", + "id": 3 + }, + { + "name": "minecraft:dirt_with_roots", + "id": -318 + }, + { + "name": "minecraft:disc_fragment_5", + "id": 648 + }, + { + "name": "minecraft:dispenser", + "id": 23 + }, + { + "name": "minecraft:dolphin_spawn_egg", + "id": 489 + }, + { + "name": "minecraft:donkey_spawn_egg", + "id": 470 + }, + { + "name": "minecraft:double_cut_copper_slab", + "id": -368 + }, + { + "name": "minecraft:double_plant", + "id": 175 + }, + { + "name": "minecraft:double_stone_block_slab", + "id": 43 + }, + { + "name": "minecraft:double_stone_block_slab2", + "id": 181 + }, + { + "name": "minecraft:double_stone_block_slab3", + "id": -167 + }, + { + "name": "minecraft:double_stone_block_slab4", + "id": -168 + }, + { + "name": "minecraft:dragon_breath", + "id": 571 + }, + { + "name": "minecraft:dragon_egg", + "id": 122 + }, + { + "name": "minecraft:dried_kelp", + "id": 271 + }, + { + "name": "minecraft:dried_kelp_block", + "id": -139 + }, + { + "name": "minecraft:dripstone_block", + "id": -317 + }, + { + "name": "minecraft:dropper", + "id": 125 + }, + { + "name": "minecraft:drowned_spawn_egg", + "id": 488 + }, + { + "name": "minecraft:dune_armor_trim_smithing_template", + "id": 690 + }, + { + "name": "minecraft:dye", + "id": 730 + }, + { + "name": "minecraft:echo_shard", + "id": 658 + }, + { + "name": "minecraft:egg", + "id": 394 + }, + { + "name": "minecraft:elder_guardian_spawn_egg", + "id": 476 + }, + { + "name": "minecraft:element_0", + "id": 36 + }, + { + "name": "minecraft:element_1", + "id": -12 + }, + { + "name": "minecraft:element_10", + "id": -21 + }, + { + "name": "minecraft:element_100", + "id": -111 + }, + { + "name": "minecraft:element_101", + "id": -112 + }, + { + "name": "minecraft:element_102", + "id": -113 + }, + { + "name": "minecraft:element_103", + "id": -114 + }, + { + "name": "minecraft:element_104", + "id": -115 + }, + { + "name": "minecraft:element_105", + "id": -116 + }, + { + "name": "minecraft:element_106", + "id": -117 + }, + { + "name": "minecraft:element_107", + "id": -118 + }, + { + "name": "minecraft:element_108", + "id": -119 + }, + { + "name": "minecraft:element_109", + "id": -120 + }, + { + "name": "minecraft:element_11", + "id": -22 + }, + { + "name": "minecraft:element_110", + "id": -121 + }, + { + "name": "minecraft:element_111", + "id": -122 + }, + { + "name": "minecraft:element_112", + "id": -123 + }, + { + "name": "minecraft:element_113", + "id": -124 + }, + { + "name": "minecraft:element_114", + "id": -125 + }, + { + "name": "minecraft:element_115", + "id": -126 + }, + { + "name": "minecraft:element_116", + "id": -127 + }, + { + "name": "minecraft:element_117", + "id": -128 + }, + { + "name": "minecraft:element_118", + "id": -129 + }, + { + "name": "minecraft:element_12", + "id": -23 + }, + { + "name": "minecraft:element_13", + "id": -24 + }, + { + "name": "minecraft:element_14", + "id": -25 + }, + { + "name": "minecraft:element_15", + "id": -26 + }, + { + "name": "minecraft:element_16", + "id": -27 + }, + { + "name": "minecraft:element_17", + "id": -28 + }, + { + "name": "minecraft:element_18", + "id": -29 + }, + { + "name": "minecraft:element_19", + "id": -30 + }, + { + "name": "minecraft:element_2", + "id": -13 + }, + { + "name": "minecraft:element_20", + "id": -31 + }, + { + "name": "minecraft:element_21", + "id": -32 + }, + { + "name": "minecraft:element_22", + "id": -33 + }, + { + "name": "minecraft:element_23", + "id": -34 + }, + { + "name": "minecraft:element_24", + "id": -35 + }, + { + "name": "minecraft:element_25", + "id": -36 + }, + { + "name": "minecraft:element_26", + "id": -37 + }, + { + "name": "minecraft:element_27", + "id": -38 + }, + { + "name": "minecraft:element_28", + "id": -39 + }, + { + "name": "minecraft:element_29", + "id": -40 + }, + { + "name": "minecraft:element_3", + "id": -14 + }, + { + "name": "minecraft:element_30", + "id": -41 + }, + { + "name": "minecraft:element_31", + "id": -42 + }, + { + "name": "minecraft:element_32", + "id": -43 + }, + { + "name": "minecraft:element_33", + "id": -44 + }, + { + "name": "minecraft:element_34", + "id": -45 + }, + { + "name": "minecraft:element_35", + "id": -46 + }, + { + "name": "minecraft:element_36", + "id": -47 + }, + { + "name": "minecraft:element_37", + "id": -48 + }, + { + "name": "minecraft:element_38", + "id": -49 + }, + { + "name": "minecraft:element_39", + "id": -50 + }, + { + "name": "minecraft:element_4", + "id": -15 + }, + { + "name": "minecraft:element_40", + "id": -51 + }, + { + "name": "minecraft:element_41", + "id": -52 + }, + { + "name": "minecraft:element_42", + "id": -53 + }, + { + "name": "minecraft:element_43", + "id": -54 + }, + { + "name": "minecraft:element_44", + "id": -55 + }, + { + "name": "minecraft:element_45", + "id": -56 + }, + { + "name": "minecraft:element_46", + "id": -57 + }, + { + "name": "minecraft:element_47", + "id": -58 + }, + { + "name": "minecraft:element_48", + "id": -59 + }, + { + "name": "minecraft:element_49", + "id": -60 + }, + { + "name": "minecraft:element_5", + "id": -16 + }, + { + "name": "minecraft:element_50", + "id": -61 + }, + { + "name": "minecraft:element_51", + "id": -62 + }, + { + "name": "minecraft:element_52", + "id": -63 + }, + { + "name": "minecraft:element_53", + "id": -64 + }, + { + "name": "minecraft:element_54", + "id": -65 + }, + { + "name": "minecraft:element_55", + "id": -66 + }, + { + "name": "minecraft:element_56", + "id": -67 + }, + { + "name": "minecraft:element_57", + "id": -68 + }, + { + "name": "minecraft:element_58", + "id": -69 + }, + { + "name": "minecraft:element_59", + "id": -70 + }, + { + "name": "minecraft:element_6", + "id": -17 + }, + { + "name": "minecraft:element_60", + "id": -71 + }, + { + "name": "minecraft:element_61", + "id": -72 + }, + { + "name": "minecraft:element_62", + "id": -73 + }, + { + "name": "minecraft:element_63", + "id": -74 + }, + { + "name": "minecraft:element_64", + "id": -75 + }, + { + "name": "minecraft:element_65", + "id": -76 + }, + { + "name": "minecraft:element_66", + "id": -77 + }, + { + "name": "minecraft:element_67", + "id": -78 + }, + { + "name": "minecraft:element_68", + "id": -79 + }, + { + "name": "minecraft:element_69", + "id": -80 + }, + { + "name": "minecraft:element_7", + "id": -18 + }, + { + "name": "minecraft:element_70", + "id": -81 + }, + { + "name": "minecraft:element_71", + "id": -82 + }, + { + "name": "minecraft:element_72", + "id": -83 + }, + { + "name": "minecraft:element_73", + "id": -84 + }, + { + "name": "minecraft:element_74", + "id": -85 + }, + { + "name": "minecraft:element_75", + "id": -86 + }, + { + "name": "minecraft:element_76", + "id": -87 + }, + { + "name": "minecraft:element_77", + "id": -88 + }, + { + "name": "minecraft:element_78", + "id": -89 + }, + { + "name": "minecraft:element_79", + "id": -90 + }, + { + "name": "minecraft:element_8", + "id": -19 + }, + { + "name": "minecraft:element_80", + "id": -91 + }, + { + "name": "minecraft:element_81", + "id": -92 + }, + { + "name": "minecraft:element_82", + "id": -93 + }, + { + "name": "minecraft:element_83", + "id": -94 + }, + { + "name": "minecraft:element_84", + "id": -95 + }, + { + "name": "minecraft:element_85", + "id": -96 + }, + { + "name": "minecraft:element_86", + "id": -97 + }, + { + "name": "minecraft:element_87", + "id": -98 + }, + { + "name": "minecraft:element_88", + "id": -99 + }, + { + "name": "minecraft:element_89", + "id": -100 + }, + { + "name": "minecraft:element_9", + "id": -20 + }, + { + "name": "minecraft:element_90", + "id": -101 + }, + { + "name": "minecraft:element_91", + "id": -102 + }, + { + "name": "minecraft:element_92", + "id": -103 + }, + { + "name": "minecraft:element_93", + "id": -104 + }, + { + "name": "minecraft:element_94", + "id": -105 + }, + { + "name": "minecraft:element_95", + "id": -106 + }, + { + "name": "minecraft:element_96", + "id": -107 + }, + { + "name": "minecraft:element_97", + "id": -108 + }, + { + "name": "minecraft:element_98", + "id": -109 + }, + { + "name": "minecraft:element_99", + "id": -110 + }, + { + "name": "minecraft:elytra", + "id": 575 + }, + { + "name": "minecraft:emerald", + "id": 523 + }, + { + "name": "minecraft:emerald_block", + "id": 133 + }, + { + "name": "minecraft:emerald_ore", + "id": 129 + }, + { + "name": "minecraft:empty_map", + "id": 526 + }, + { + "name": "minecraft:enchanted_book", + "id": 532 + }, + { + "name": "minecraft:enchanted_golden_apple", + "id": 260 + }, + { + "name": "minecraft:enchanting_table", + "id": 116 + }, + { + "name": "minecraft:end_brick_stairs", + "id": -178 + }, + { + "name": "minecraft:end_bricks", + "id": 206 + }, + { + "name": "minecraft:end_crystal", + "id": 733 + }, + { + "name": "minecraft:end_gateway", + "id": 209 + }, + { + "name": "minecraft:end_portal", + "id": 119 + }, + { + "name": "minecraft:end_portal_frame", + "id": 120 + }, + { + "name": "minecraft:end_rod", + "id": 208 + }, + { + "name": "minecraft:end_stone", + "id": 121 + }, + { + "name": "minecraft:ender_chest", + "id": 130 + }, + { + "name": "minecraft:ender_dragon_spawn_egg", + "id": 512 + }, + { + "name": "minecraft:ender_eye", + "id": 437 + }, + { + "name": "minecraft:ender_pearl", + "id": 426 + }, + { + "name": "minecraft:enderman_spawn_egg", + "id": 446 + }, + { + "name": "minecraft:endermite_spawn_egg", + "id": 464 + }, + { + "name": "minecraft:evoker_spawn_egg", + "id": 480 + }, + { + "name": "minecraft:experience_bottle", + "id": 519 + }, + { + "name": "minecraft:explorer_pottery_sherd", + "id": 674 + }, + { + "name": "minecraft:exposed_chiseled_copper", + "id": -761 + }, + { + "name": "minecraft:exposed_copper", + "id": -341 + }, + { + "name": "minecraft:exposed_copper_bulb", + "id": -777 + }, + { + "name": "minecraft:exposed_copper_door", + "id": -785 + }, + { + "name": "minecraft:exposed_copper_grate", + "id": -769 + }, + { + "name": "minecraft:exposed_copper_trapdoor", + "id": -793 + }, + { + "name": "minecraft:exposed_cut_copper", + "id": -348 + }, + { + "name": "minecraft:exposed_cut_copper_slab", + "id": -362 + }, + { + "name": "minecraft:exposed_cut_copper_stairs", + "id": -355 + }, + { + "name": "minecraft:exposed_double_cut_copper_slab", + "id": -369 + }, + { + "name": "minecraft:eye_armor_trim_smithing_template", + "id": 694 + }, + { + "name": "minecraft:farmland", + "id": 60 + }, + { + "name": "minecraft:feather", + "id": 330 + }, + { + "name": "minecraft:fence", + "id": 714 + }, + { + "name": "minecraft:fence_gate", + "id": 107 + }, + { + "name": "minecraft:fermented_spider_eye", + "id": 432 + }, + { + "name": "minecraft:field_masoned_banner_pattern", + "id": 596 + }, + { + "name": "minecraft:filled_map", + "id": 424 + }, + { + "name": "minecraft:fire", + "id": 51 + }, + { + "name": "minecraft:fire_charge", + "id": 520 + }, + { + "name": "minecraft:fire_coral", + "id": -583 + }, + { + "name": "minecraft:firework_rocket", + "id": 530 + }, + { + "name": "minecraft:firework_star", + "id": 531 + }, + { + "name": "minecraft:fishing_rod", + "id": 396 + }, + { + "name": "minecraft:fletching_table", + "id": -201 + }, + { + "name": "minecraft:flint", + "id": 359 + }, + { + "name": "minecraft:flint_and_steel", + "id": 302 + }, + { + "name": "minecraft:flower_banner_pattern", + "id": 592 + }, + { + "name": "minecraft:flower_pot", + "id": 525 + }, + { + "name": "minecraft:flowering_azalea", + "id": -338 + }, + { + "name": "minecraft:flowing_lava", + "id": 10 + }, + { + "name": "minecraft:flowing_water", + "id": 8 + }, + { + "name": "minecraft:fox_spawn_egg", + "id": 495 + }, + { + "name": "minecraft:frame", + "id": 524 + }, + { + "name": "minecraft:friend_pottery_sherd", + "id": 675 + }, + { + "name": "minecraft:frog_spawn", + "id": -468 + }, + { + "name": "minecraft:frog_spawn_egg", + "id": 639 + }, + { + "name": "minecraft:frosted_ice", + "id": 207 + }, + { + "name": "minecraft:furnace", + "id": 61 + }, + { + "name": "minecraft:ghast_spawn_egg", + "id": 458 + }, + { + "name": "minecraft:ghast_tear", + "id": 428 + }, + { + "name": "minecraft:gilded_blackstone", + "id": -281 + }, + { + "name": "minecraft:glass", + "id": 20 + }, + { + "name": "minecraft:glass_bottle", + "id": 431 + }, + { + "name": "minecraft:glass_pane", + "id": 102 + }, + { + "name": "minecraft:glistering_melon_slice", + "id": 438 + }, + { + "name": "minecraft:globe_banner_pattern", + "id": 599 + }, + { + "name": "minecraft:glow_berries", + "id": 734 + }, + { + "name": "minecraft:glow_frame", + "id": 634 + }, + { + "name": "minecraft:glow_ink_sac", + "id": 514 + }, + { + "name": "minecraft:glow_lichen", + "id": -411 + }, + { + "name": "minecraft:glow_squid_spawn_egg", + "id": 509 + }, + { + "name": "minecraft:glow_stick", + "id": 612 + }, + { + "name": "minecraft:glowingobsidian", + "id": 246 + }, + { + "name": "minecraft:glowstone", + "id": 89 + }, + { + "name": "minecraft:glowstone_dust", + "id": 398 + }, + { + "name": "minecraft:goat_horn", + "id": 638 + }, + { + "name": "minecraft:goat_spawn_egg", + "id": 508 + }, + { + "name": "minecraft:gold_block", + "id": 41 + }, + { + "name": "minecraft:gold_ingot", + "id": 309 + }, + { + "name": "minecraft:gold_nugget", + "id": 429 + }, + { + "name": "minecraft:gold_ore", + "id": 14 + }, + { + "name": "minecraft:golden_apple", + "id": 259 + }, + { + "name": "minecraft:golden_axe", + "id": 328 + }, + { + "name": "minecraft:golden_boots", + "id": 357 + }, + { + "name": "minecraft:golden_carrot", + "id": 284 + }, + { + "name": "minecraft:golden_chestplate", + "id": 355 + }, + { + "name": "minecraft:golden_helmet", + "id": 354 + }, + { + "name": "minecraft:golden_hoe", + "id": 336 + }, + { + "name": "minecraft:golden_horse_armor", + "id": 543 + }, + { + "name": "minecraft:golden_leggings", + "id": 356 + }, + { + "name": "minecraft:golden_pickaxe", + "id": 327 + }, + { + "name": "minecraft:golden_rail", + "id": 27 + }, + { + "name": "minecraft:golden_shovel", + "id": 326 + }, + { + "name": "minecraft:golden_sword", + "id": 325 + }, + { + "name": "minecraft:granite", + "id": -590 + }, + { + "name": "minecraft:granite_stairs", + "id": -169 + }, + { + "name": "minecraft:grass_block", + "id": 2 + }, + { + "name": "minecraft:grass_path", + "id": 198 + }, + { + "name": "minecraft:gravel", + "id": 13 + }, + { + "name": "minecraft:gray_candle", + "id": -420 + }, + { + "name": "minecraft:gray_candle_cake", + "id": -437 + }, + { + "name": "minecraft:gray_carpet", + "id": -603 + }, + { + "name": "minecraft:gray_concrete", + "id": -634 + }, + { + "name": "minecraft:gray_concrete_powder", + "id": -715 + }, + { + "name": "minecraft:gray_dye", + "id": 407 + }, + { + "name": "minecraft:gray_glazed_terracotta", + "id": 227 + }, + { + "name": "minecraft:gray_shulker_box", + "id": -619 + }, + { + "name": "minecraft:gray_stained_glass", + "id": -679 + }, + { + "name": "minecraft:gray_stained_glass_pane", + "id": -649 + }, + { + "name": "minecraft:gray_terracotta", + "id": -730 + }, + { + "name": "minecraft:gray_wool", + "id": -553 + }, + { + "name": "minecraft:green_candle", + "id": -426 + }, + { + "name": "minecraft:green_candle_cake", + "id": -443 + }, + { + "name": "minecraft:green_carpet", + "id": -609 + }, + { + "name": "minecraft:green_concrete", + "id": -640 + }, + { + "name": "minecraft:green_concrete_powder", + "id": -721 + }, + { + "name": "minecraft:green_dye", + "id": 401 + }, + { + "name": "minecraft:green_glazed_terracotta", + "id": 233 + }, + { + "name": "minecraft:green_shulker_box", + "id": -625 + }, + { + "name": "minecraft:green_stained_glass", + "id": -685 + }, + { + "name": "minecraft:green_stained_glass_pane", + "id": -655 + }, + { + "name": "minecraft:green_terracotta", + "id": -736 + }, + { + "name": "minecraft:green_wool", + "id": -560 + }, + { + "name": "minecraft:grindstone", + "id": -195 + }, + { + "name": "minecraft:guardian_spawn_egg", + "id": 465 + }, + { + "name": "minecraft:gunpowder", + "id": 331 + }, + { + "name": "minecraft:hanging_roots", + "id": -319 + }, + { + "name": "minecraft:hard_black_stained_glass", + "id": -702 + }, + { + "name": "minecraft:hard_black_stained_glass_pane", + "id": -672 + }, + { + "name": "minecraft:hard_blue_stained_glass", + "id": -698 + }, + { + "name": "minecraft:hard_blue_stained_glass_pane", + "id": -668 + }, + { + "name": "minecraft:hard_brown_stained_glass", + "id": -699 + }, + { + "name": "minecraft:hard_brown_stained_glass_pane", + "id": -669 + }, + { + "name": "minecraft:hard_cyan_stained_glass", + "id": -696 + }, + { + "name": "minecraft:hard_cyan_stained_glass_pane", + "id": -666 + }, + { + "name": "minecraft:hard_glass", + "id": 253 + }, + { + "name": "minecraft:hard_glass_pane", + "id": 190 + }, + { + "name": "minecraft:hard_gray_stained_glass", + "id": -694 + }, + { + "name": "minecraft:hard_gray_stained_glass_pane", + "id": -664 + }, + { + "name": "minecraft:hard_green_stained_glass", + "id": -700 + }, + { + "name": "minecraft:hard_green_stained_glass_pane", + "id": -670 + }, + { + "name": "minecraft:hard_light_blue_stained_glass", + "id": -690 + }, + { + "name": "minecraft:hard_light_blue_stained_glass_pane", + "id": -660 + }, + { + "name": "minecraft:hard_light_gray_stained_glass", + "id": -695 + }, + { + "name": "minecraft:hard_light_gray_stained_glass_pane", + "id": -665 + }, + { + "name": "minecraft:hard_lime_stained_glass", + "id": -692 + }, + { + "name": "minecraft:hard_lime_stained_glass_pane", + "id": -662 + }, + { + "name": "minecraft:hard_magenta_stained_glass", + "id": -689 + }, + { + "name": "minecraft:hard_magenta_stained_glass_pane", + "id": -659 + }, + { + "name": "minecraft:hard_orange_stained_glass", + "id": -688 + }, + { + "name": "minecraft:hard_orange_stained_glass_pane", + "id": -658 + }, + { + "name": "minecraft:hard_pink_stained_glass", + "id": -693 + }, + { + "name": "minecraft:hard_pink_stained_glass_pane", + "id": -663 + }, + { + "name": "minecraft:hard_purple_stained_glass", + "id": -697 + }, + { + "name": "minecraft:hard_purple_stained_glass_pane", + "id": -667 + }, + { + "name": "minecraft:hard_red_stained_glass", + "id": -701 + }, + { + "name": "minecraft:hard_red_stained_glass_pane", + "id": -671 + }, + { + "name": "minecraft:hard_stained_glass", + "id": 727 + }, + { + "name": "minecraft:hard_stained_glass_pane", + "id": 728 + }, + { + "name": "minecraft:hard_white_stained_glass", + "id": 254 + }, + { + "name": "minecraft:hard_white_stained_glass_pane", + "id": 191 + }, + { + "name": "minecraft:hard_yellow_stained_glass", + "id": -691 + }, + { + "name": "minecraft:hard_yellow_stained_glass_pane", + "id": -661 + }, + { + "name": "minecraft:hardened_clay", + "id": 172 + }, + { + "name": "minecraft:hay_block", + "id": 170 + }, + { + "name": "minecraft:heart_of_the_sea", + "id": 582 + }, + { + "name": "minecraft:heart_pottery_sherd", + "id": 676 + }, + { + "name": "minecraft:heartbreak_pottery_sherd", + "id": 677 + }, + { + "name": "minecraft:heavy_weighted_pressure_plate", + "id": 148 + }, + { + "name": "minecraft:hoglin_spawn_egg", + "id": 501 + }, + { + "name": "minecraft:honey_block", + "id": -220 + }, + { + "name": "minecraft:honey_bottle", + "id": 603 + }, + { + "name": "minecraft:honeycomb", + "id": 602 + }, + { + "name": "minecraft:honeycomb_block", + "id": -221 + }, + { + "name": "minecraft:hopper", + "id": 538 + }, + { + "name": "minecraft:hopper_minecart", + "id": 537 + }, + { + "name": "minecraft:horn_coral", + "id": -584 + }, + { + "name": "minecraft:horse_spawn_egg", + "id": 462 + }, + { + "name": "minecraft:host_armor_trim_smithing_template", + "id": 704 + }, + { + "name": "minecraft:howl_pottery_sherd", + "id": 678 + }, + { + "name": "minecraft:husk_spawn_egg", + "id": 468 + }, + { + "name": "minecraft:ice", + "id": 79 + }, + { + "name": "minecraft:ice_bomb", + "id": 606 + }, + { + "name": "minecraft:infested_deepslate", + "id": -454 + }, + { + "name": "minecraft:info_update", + "id": 248 + }, + { + "name": "minecraft:info_update2", + "id": 249 + }, + { + "name": "minecraft:ink_sac", + "id": 417 + }, + { + "name": "minecraft:invisible_bedrock", + "id": 95 + }, + { + "name": "minecraft:iron_axe", + "id": 301 + }, + { + "name": "minecraft:iron_bars", + "id": 101 + }, + { + "name": "minecraft:iron_block", + "id": 42 + }, + { + "name": "minecraft:iron_boots", + "id": 349 + }, + { + "name": "minecraft:iron_chestplate", + "id": 347 + }, + { + "name": "minecraft:iron_door", + "id": 375 + }, + { + "name": "minecraft:iron_golem_spawn_egg", + "id": 510 + }, + { + "name": "minecraft:iron_helmet", + "id": 346 + }, + { + "name": "minecraft:iron_hoe", + "id": 334 + }, + { + "name": "minecraft:iron_horse_armor", + "id": 542 + }, + { + "name": "minecraft:iron_ingot", + "id": 308 + }, + { + "name": "minecraft:iron_leggings", + "id": 348 + }, + { + "name": "minecraft:iron_nugget", + "id": 580 + }, + { + "name": "minecraft:iron_ore", + "id": 15 + }, + { + "name": "minecraft:iron_pickaxe", + "id": 300 + }, + { + "name": "minecraft:iron_shovel", + "id": 299 + }, + { + "name": "minecraft:iron_sword", + "id": 310 + }, + { + "name": "minecraft:iron_trapdoor", + "id": 167 + }, + { + "name": "minecraft:item.acacia_door", + "id": 196 + }, + { + "name": "minecraft:item.bed", + "id": 26 + }, + { + "name": "minecraft:item.beetroot", + "id": 244 + }, + { + "name": "minecraft:item.birch_door", + "id": 194 + }, + { + "name": "minecraft:item.brewing_stand", + "id": 117 + }, + { + "name": "minecraft:item.cake", + "id": 92 + }, + { + "name": "minecraft:item.camera", + "id": 242 + }, + { + "name": "minecraft:item.campfire", + "id": -209 + }, + { + "name": "minecraft:item.cauldron", + "id": 118 + }, + { + "name": "minecraft:item.chain", + "id": -286 + }, + { + "name": "minecraft:item.crimson_door", + "id": -244 + }, + { + "name": "minecraft:item.dark_oak_door", + "id": 197 + }, + { + "name": "minecraft:item.flower_pot", + "id": 140 + }, + { + "name": "minecraft:item.frame", + "id": 199 + }, + { + "name": "minecraft:item.glow_frame", + "id": -339 + }, + { + "name": "minecraft:item.hopper", + "id": 154 + }, + { + "name": "minecraft:item.iron_door", + "id": 71 + }, + { + "name": "minecraft:item.jungle_door", + "id": 195 + }, + { + "name": "minecraft:item.kelp", + "id": -138 + }, + { + "name": "minecraft:item.mangrove_door", + "id": -493 + }, + { + "name": "minecraft:item.nether_sprouts", + "id": -238 + }, + { + "name": "minecraft:item.nether_wart", + "id": 115 + }, + { + "name": "minecraft:item.reeds", + "id": 83 + }, + { + "name": "minecraft:item.skull", + "id": 144 + }, + { + "name": "minecraft:item.soul_campfire", + "id": -290 + }, + { + "name": "minecraft:item.spruce_door", + "id": 193 + }, + { + "name": "minecraft:item.warped_door", + "id": -245 + }, + { + "name": "minecraft:item.wheat", + "id": 59 + }, + { + "name": "minecraft:item.wooden_door", + "id": 64 + }, + { + "name": "minecraft:jigsaw", + "id": -211 + }, + { + "name": "minecraft:jukebox", + "id": 84 + }, + { + "name": "minecraft:jungle_boat", + "id": 381 + }, + { + "name": "minecraft:jungle_button", + "id": -143 + }, + { + "name": "minecraft:jungle_chest_boat", + "id": 651 + }, + { + "name": "minecraft:jungle_door", + "id": 566 + }, + { + "name": "minecraft:jungle_double_slab", + "id": -811 + }, + { + "name": "minecraft:jungle_fence", + "id": -578 + }, + { + "name": "minecraft:jungle_fence_gate", + "id": 185 + }, + { + "name": "minecraft:jungle_hanging_sign", + "id": -503 + }, + { + "name": "minecraft:jungle_leaves", + "id": -802 + }, + { + "name": "minecraft:jungle_log", + "id": -571 + }, + { + "name": "minecraft:jungle_planks", + "id": -741 + }, + { + "name": "minecraft:jungle_pressure_plate", + "id": -153 + }, + { + "name": "minecraft:jungle_sign", + "id": 589 + }, + { + "name": "minecraft:jungle_slab", + "id": -806 + }, + { + "name": "minecraft:jungle_stairs", + "id": 136 + }, + { + "name": "minecraft:jungle_standing_sign", + "id": -188 + }, + { + "name": "minecraft:jungle_trapdoor", + "id": -148 + }, + { + "name": "minecraft:jungle_wall_sign", + "id": -189 + }, + { + "name": "minecraft:jungle_wood", + "id": -816 + }, + { + "name": "minecraft:kelp", + "id": 386 + }, + { + "name": "minecraft:ladder", + "id": 65 + }, + { + "name": "minecraft:lantern", + "id": -208 + }, + { + "name": "minecraft:lapis_block", + "id": 22 + }, + { + "name": "minecraft:lapis_lazuli", + "id": 418 + }, + { + "name": "minecraft:lapis_ore", + "id": 21 + }, + { + "name": "minecraft:large_amethyst_bud", + "id": -330 + }, + { + "name": "minecraft:lava", + "id": 11 + }, + { + "name": "minecraft:lava_bucket", + "id": 366 + }, + { + "name": "minecraft:lead", + "id": 558 + }, + { + "name": "minecraft:leather", + "id": 385 + }, + { + "name": "minecraft:leather_boots", + "id": 341 + }, + { + "name": "minecraft:leather_chestplate", + "id": 339 + }, + { + "name": "minecraft:leather_helmet", + "id": 338 + }, + { + "name": "minecraft:leather_horse_armor", + "id": 541 + }, + { + "name": "minecraft:leather_leggings", + "id": 340 + }, + { + "name": "minecraft:leaves", + "id": 715 + }, + { + "name": "minecraft:leaves2", + "id": 716 + }, + { + "name": "minecraft:lectern", + "id": -194 + }, + { + "name": "minecraft:lever", + "id": 69 + }, + { + "name": "minecraft:light_block", + "id": -215 + }, + { + "name": "minecraft:light_blue_candle", + "id": -416 + }, + { + "name": "minecraft:light_blue_candle_cake", + "id": -433 + }, + { + "name": "minecraft:light_blue_carpet", + "id": -599 + }, + { + "name": "minecraft:light_blue_concrete", + "id": -630 + }, + { + "name": "minecraft:light_blue_concrete_powder", + "id": -711 + }, + { + "name": "minecraft:light_blue_dye", + "id": 411 + }, + { + "name": "minecraft:light_blue_glazed_terracotta", + "id": 223 + }, + { + "name": "minecraft:light_blue_shulker_box", + "id": -615 + }, + { + "name": "minecraft:light_blue_stained_glass", + "id": -675 + }, + { + "name": "minecraft:light_blue_stained_glass_pane", + "id": -645 + }, + { + "name": "minecraft:light_blue_terracotta", + "id": -726 + }, + { + "name": "minecraft:light_blue_wool", + "id": -562 + }, + { + "name": "minecraft:light_gray_candle", + "id": -421 + }, + { + "name": "minecraft:light_gray_candle_cake", + "id": -438 + }, + { + "name": "minecraft:light_gray_carpet", + "id": -604 + }, + { + "name": "minecraft:light_gray_concrete", + "id": -635 + }, + { + "name": "minecraft:light_gray_concrete_powder", + "id": -716 + }, + { + "name": "minecraft:light_gray_dye", + "id": 406 + }, + { + "name": "minecraft:light_gray_shulker_box", + "id": -620 + }, + { + "name": "minecraft:light_gray_stained_glass", + "id": -680 + }, + { + "name": "minecraft:light_gray_stained_glass_pane", + "id": -650 + }, + { + "name": "minecraft:light_gray_terracotta", + "id": -731 + }, + { + "name": "minecraft:light_gray_wool", + "id": -552 + }, + { + "name": "minecraft:light_weighted_pressure_plate", + "id": 147 + }, + { + "name": "minecraft:lightning_rod", + "id": -312 + }, + { + "name": "minecraft:lime_candle", + "id": -418 + }, + { + "name": "minecraft:lime_candle_cake", + "id": -435 + }, + { + "name": "minecraft:lime_carpet", + "id": -601 + }, + { + "name": "minecraft:lime_concrete", + "id": -632 + }, + { + "name": "minecraft:lime_concrete_powder", + "id": -713 + }, + { + "name": "minecraft:lime_dye", + "id": 409 + }, + { + "name": "minecraft:lime_glazed_terracotta", + "id": 225 + }, + { + "name": "minecraft:lime_shulker_box", + "id": -617 + }, + { + "name": "minecraft:lime_stained_glass", + "id": -677 + }, + { + "name": "minecraft:lime_stained_glass_pane", + "id": -647 + }, + { + "name": "minecraft:lime_terracotta", + "id": -728 + }, + { + "name": "minecraft:lime_wool", + "id": -559 + }, + { + "name": "minecraft:lingering_potion", + "id": 573 + }, + { + "name": "minecraft:lit_blast_furnace", + "id": -214 + }, + { + "name": "minecraft:lit_deepslate_redstone_ore", + "id": -404 + }, + { + "name": "minecraft:lit_furnace", + "id": 62 + }, + { + "name": "minecraft:lit_pumpkin", + "id": 91 + }, + { + "name": "minecraft:lit_redstone_lamp", + "id": 124 + }, + { + "name": "minecraft:lit_redstone_ore", + "id": 74 + }, + { + "name": "minecraft:lit_smoker", + "id": -199 + }, + { + "name": "minecraft:llama_spawn_egg", + "id": 478 + }, + { + "name": "minecraft:lodestone", + "id": -222 + }, + { + "name": "minecraft:lodestone_compass", + "id": 613 + }, + { + "name": "minecraft:log", + "id": 713 + }, + { + "name": "minecraft:log2", + "id": 720 + }, + { + "name": "minecraft:loom", + "id": -204 + }, + { + "name": "minecraft:magenta_candle", + "id": -415 + }, + { + "name": "minecraft:magenta_candle_cake", + "id": -432 + }, + { + "name": "minecraft:magenta_carpet", + "id": -598 + }, + { + "name": "minecraft:magenta_concrete", + "id": -629 + }, + { + "name": "minecraft:magenta_concrete_powder", + "id": -710 + }, + { + "name": "minecraft:magenta_dye", + "id": 412 + }, + { + "name": "minecraft:magenta_glazed_terracotta", + "id": 222 + }, + { + "name": "minecraft:magenta_shulker_box", + "id": -614 + }, + { + "name": "minecraft:magenta_stained_glass", + "id": -674 + }, + { + "name": "minecraft:magenta_stained_glass_pane", + "id": -644 + }, + { + "name": "minecraft:magenta_terracotta", + "id": -725 + }, + { + "name": "minecraft:magenta_wool", + "id": -565 + }, + { + "name": "minecraft:magma", + "id": 213 + }, + { + "name": "minecraft:magma_cream", + "id": 434 + }, + { + "name": "minecraft:magma_cube_spawn_egg", + "id": 459 + }, + { + "name": "minecraft:mangrove_boat", + "id": 646 + }, + { + "name": "minecraft:mangrove_button", + "id": -487 + }, + { + "name": "minecraft:mangrove_chest_boat", + "id": 655 + }, + { + "name": "minecraft:mangrove_door", + "id": 644 + }, + { + "name": "minecraft:mangrove_double_slab", + "id": -499 + }, + { + "name": "minecraft:mangrove_fence", + "id": -491 + }, + { + "name": "minecraft:mangrove_fence_gate", + "id": -492 + }, + { + "name": "minecraft:mangrove_hanging_sign", + "id": -508 + }, + { + "name": "minecraft:mangrove_leaves", + "id": -472 + }, + { + "name": "minecraft:mangrove_log", + "id": -484 + }, + { + "name": "minecraft:mangrove_planks", + "id": -486 + }, + { + "name": "minecraft:mangrove_pressure_plate", + "id": -490 + }, + { + "name": "minecraft:mangrove_propagule", + "id": -474 + }, + { + "name": "minecraft:mangrove_roots", + "id": -482 + }, + { + "name": "minecraft:mangrove_sign", + "id": 645 + }, + { + "name": "minecraft:mangrove_slab", + "id": -489 + }, + { + "name": "minecraft:mangrove_stairs", + "id": -488 + }, + { + "name": "minecraft:mangrove_standing_sign", + "id": -494 + }, + { + "name": "minecraft:mangrove_trapdoor", + "id": -496 + }, + { + "name": "minecraft:mangrove_wall_sign", + "id": -495 + }, + { + "name": "minecraft:mangrove_wood", + "id": -497 + }, + { + "name": "minecraft:medicine", + "id": 610 + }, + { + "name": "minecraft:medium_amethyst_bud", + "id": -331 + }, + { + "name": "minecraft:melon_block", + "id": 103 + }, + { + "name": "minecraft:melon_seeds", + "id": 294 + }, + { + "name": "minecraft:melon_slice", + "id": 273 + }, + { + "name": "minecraft:melon_stem", + "id": 105 + }, + { + "name": "minecraft:milk_bucket", + "id": 364 + }, + { + "name": "minecraft:minecart", + "id": 373 + }, + { + "name": "minecraft:miner_pottery_sherd", + "id": 679 + }, + { + "name": "minecraft:mob_spawner", + "id": 52 + }, + { + "name": "minecraft:mojang_banner_pattern", + "id": 595 + }, + { + "name": "minecraft:monster_egg", + "id": 97 + }, + { + "name": "minecraft:mooshroom_spawn_egg", + "id": 444 + }, + { + "name": "minecraft:moss_block", + "id": -320 + }, + { + "name": "minecraft:moss_carpet", + "id": -335 + }, + { + "name": "minecraft:mossy_cobblestone", + "id": 48 + }, + { + "name": "minecraft:mossy_cobblestone_stairs", + "id": -179 + }, + { + "name": "minecraft:mossy_stone_brick_stairs", + "id": -175 + }, + { + "name": "minecraft:mourner_pottery_sherd", + "id": 680 + }, + { + "name": "minecraft:moving_block", + "id": 250 + }, + { + "name": "minecraft:mud", + "id": -473 + }, + { + "name": "minecraft:mud_brick_double_slab", + "id": -479 + }, + { + "name": "minecraft:mud_brick_slab", + "id": -478 + }, + { + "name": "minecraft:mud_brick_stairs", + "id": -480 + }, + { + "name": "minecraft:mud_brick_wall", + "id": -481 + }, + { + "name": "minecraft:mud_bricks", + "id": -475 + }, + { + "name": "minecraft:muddy_mangrove_roots", + "id": -483 + }, + { + "name": "minecraft:mule_spawn_egg", + "id": 471 + }, + { + "name": "minecraft:mushroom_stew", + "id": 261 + }, + { + "name": "minecraft:music_disc_11", + "id": 555 + }, + { + "name": "minecraft:music_disc_13", + "id": 545 + }, + { + "name": "minecraft:music_disc_5", + "id": 647 + }, + { + "name": "minecraft:music_disc_blocks", + "id": 547 + }, + { + "name": "minecraft:music_disc_cat", + "id": 546 + }, + { + "name": "minecraft:music_disc_chirp", + "id": 548 + }, + { + "name": "minecraft:music_disc_far", + "id": 549 + }, + { + "name": "minecraft:music_disc_mall", + "id": 550 + }, + { + "name": "minecraft:music_disc_mellohi", + "id": 551 + }, + { + "name": "minecraft:music_disc_otherside", + "id": 637 + }, + { + "name": "minecraft:music_disc_pigstep", + "id": 631 + }, + { + "name": "minecraft:music_disc_relic", + "id": 705 + }, + { + "name": "minecraft:music_disc_stal", + "id": 552 + }, + { + "name": "minecraft:music_disc_strad", + "id": 553 + }, + { + "name": "minecraft:music_disc_wait", + "id": 556 + }, + { + "name": "minecraft:music_disc_ward", + "id": 554 + }, + { + "name": "minecraft:mutton", + "id": 561 + }, + { + "name": "minecraft:mycelium", + "id": 110 + }, + { + "name": "minecraft:name_tag", + "id": 559 + }, + { + "name": "minecraft:nautilus_shell", + "id": 581 + }, + { + "name": "minecraft:nether_brick", + "id": 112 + }, + { + "name": "minecraft:nether_brick_fence", + "id": 113 + }, + { + "name": "minecraft:nether_brick_stairs", + "id": 114 + }, + { + "name": "minecraft:nether_gold_ore", + "id": -288 + }, + { + "name": "minecraft:nether_sprouts", + "id": 632 + }, + { + "name": "minecraft:nether_star", + "id": 529 + }, + { + "name": "minecraft:nether_wart", + "id": 295 + }, + { + "name": "minecraft:nether_wart_block", + "id": 214 + }, + { + "name": "minecraft:netherbrick", + "id": 534 + }, + { + "name": "minecraft:netherite_axe", + "id": 617 + }, + { + "name": "minecraft:netherite_block", + "id": -270 + }, + { + "name": "minecraft:netherite_boots", + "id": 623 + }, + { + "name": "minecraft:netherite_chestplate", + "id": 621 + }, + { + "name": "minecraft:netherite_helmet", + "id": 620 + }, + { + "name": "minecraft:netherite_hoe", + "id": 618 + }, + { + "name": "minecraft:netherite_ingot", + "id": 619 + }, + { + "name": "minecraft:netherite_leggings", + "id": 622 + }, + { + "name": "minecraft:netherite_pickaxe", + "id": 616 + }, + { + "name": "minecraft:netherite_scrap", + "id": 624 + }, + { + "name": "minecraft:netherite_shovel", + "id": 615 + }, + { + "name": "minecraft:netherite_sword", + "id": 614 + }, + { + "name": "minecraft:netherite_upgrade_smithing_template", + "id": 688 + }, + { + "name": "minecraft:netherrack", + "id": 87 + }, + { + "name": "minecraft:netherreactor", + "id": 247 + }, + { + "name": "minecraft:normal_stone_stairs", + "id": -180 + }, + { + "name": "minecraft:noteblock", + "id": 25 + }, + { + "name": "minecraft:npc_spawn_egg", + "id": 475 + }, + { + "name": "minecraft:oak_boat", + "id": 379 + }, + { + "name": "minecraft:oak_chest_boat", + "id": 649 + }, + { + "name": "minecraft:oak_double_slab", + "id": 157 + }, + { + "name": "minecraft:oak_fence", + "id": 85 + }, + { + "name": "minecraft:oak_hanging_sign", + "id": -500 + }, + { + "name": "minecraft:oak_leaves", + "id": 18 + }, + { + "name": "minecraft:oak_log", + "id": 17 + }, + { + "name": "minecraft:oak_planks", + "id": 5 + }, + { + "name": "minecraft:oak_sign", + "id": 361 + }, + { + "name": "minecraft:oak_slab", + "id": 158 + }, + { + "name": "minecraft:oak_stairs", + "id": 53 + }, + { + "name": "minecraft:oak_wood", + "id": -212 + }, + { + "name": "minecraft:observer", + "id": 251 + }, + { + "name": "minecraft:obsidian", + "id": 49 + }, + { + "name": "minecraft:ocelot_spawn_egg", + "id": 455 + }, + { + "name": "minecraft:ochre_froglight", + "id": -471 + }, + { + "name": "minecraft:orange_candle", + "id": -414 + }, + { + "name": "minecraft:orange_candle_cake", + "id": -431 + }, + { + "name": "minecraft:orange_carpet", + "id": -597 + }, + { + "name": "minecraft:orange_concrete", + "id": -628 + }, + { + "name": "minecraft:orange_concrete_powder", + "id": -709 + }, + { + "name": "minecraft:orange_dye", + "id": 413 + }, + { + "name": "minecraft:orange_glazed_terracotta", + "id": 221 + }, + { + "name": "minecraft:orange_shulker_box", + "id": -613 + }, + { + "name": "minecraft:orange_stained_glass", + "id": -673 + }, + { + "name": "minecraft:orange_stained_glass_pane", + "id": -643 + }, + { + "name": "minecraft:orange_terracotta", + "id": -724 + }, + { + "name": "minecraft:orange_wool", + "id": -557 + }, + { + "name": "minecraft:oxidized_chiseled_copper", + "id": -763 + }, + { + "name": "minecraft:oxidized_copper", + "id": -343 + }, + { + "name": "minecraft:oxidized_copper_bulb", + "id": -779 + }, + { + "name": "minecraft:oxidized_copper_door", + "id": -787 + }, + { + "name": "minecraft:oxidized_copper_grate", + "id": -771 + }, + { + "name": "minecraft:oxidized_copper_trapdoor", + "id": -795 + }, + { + "name": "minecraft:oxidized_cut_copper", + "id": -350 + }, + { + "name": "minecraft:oxidized_cut_copper_slab", + "id": -364 + }, + { + "name": "minecraft:oxidized_cut_copper_stairs", + "id": -357 + }, + { + "name": "minecraft:oxidized_double_cut_copper_slab", + "id": -371 + }, + { + "name": "minecraft:packed_ice", + "id": 174 + }, + { + "name": "minecraft:packed_mud", + "id": -477 + }, + { + "name": "minecraft:painting", + "id": 360 + }, + { + "name": "minecraft:panda_spawn_egg", + "id": 494 + }, + { + "name": "minecraft:paper", + "id": 390 + }, + { + "name": "minecraft:parrot_spawn_egg", + "id": 483 + }, + { + "name": "minecraft:pearlescent_froglight", + "id": -469 + }, + { + "name": "minecraft:phantom_membrane", + "id": 585 + }, + { + "name": "minecraft:phantom_spawn_egg", + "id": 491 + }, + { + "name": "minecraft:pig_spawn_egg", + "id": 441 + }, + { + "name": "minecraft:piglin_banner_pattern", + "id": 598 + }, + { + "name": "minecraft:piglin_brute_spawn_egg", + "id": 504 + }, + { + "name": "minecraft:piglin_spawn_egg", + "id": 502 + }, + { + "name": "minecraft:pillager_spawn_egg", + "id": 496 + }, + { + "name": "minecraft:pink_candle", + "id": -419 + }, + { + "name": "minecraft:pink_candle_cake", + "id": -436 + }, + { + "name": "minecraft:pink_carpet", + "id": -602 + }, + { + "name": "minecraft:pink_concrete", + "id": -633 + }, + { + "name": "minecraft:pink_concrete_powder", + "id": -714 + }, + { + "name": "minecraft:pink_dye", + "id": 408 + }, + { + "name": "minecraft:pink_glazed_terracotta", + "id": 226 + }, + { + "name": "minecraft:pink_petals", + "id": -549 + }, + { + "name": "minecraft:pink_shulker_box", + "id": -618 + }, + { + "name": "minecraft:pink_stained_glass", + "id": -678 + }, + { + "name": "minecraft:pink_stained_glass_pane", + "id": -648 + }, + { + "name": "minecraft:pink_terracotta", + "id": -729 + }, + { + "name": "minecraft:pink_wool", + "id": -566 + }, + { + "name": "minecraft:piston", + "id": 33 + }, + { + "name": "minecraft:piston_arm_collision", + "id": 34 + }, + { + "name": "minecraft:pitcher_crop", + "id": -574 + }, + { + "name": "minecraft:pitcher_plant", + "id": -612 + }, + { + "name": "minecraft:pitcher_pod", + "id": 298 + }, + { + "name": "minecraft:planks", + "id": 718 + }, + { + "name": "minecraft:plenty_pottery_sherd", + "id": 681 + }, + { + "name": "minecraft:podzol", + "id": 243 + }, + { + "name": "minecraft:pointed_dripstone", + "id": -308 + }, + { + "name": "minecraft:poisonous_potato", + "id": 283 + }, + { + "name": "minecraft:polar_bear_spawn_egg", + "id": 477 + }, + { + "name": "minecraft:polished_andesite", + "id": -595 + }, + { + "name": "minecraft:polished_andesite_stairs", + "id": -174 + }, + { + "name": "minecraft:polished_basalt", + "id": -235 + }, + { + "name": "minecraft:polished_blackstone", + "id": -291 + }, + { + "name": "minecraft:polished_blackstone_brick_double_slab", + "id": -285 + }, + { + "name": "minecraft:polished_blackstone_brick_slab", + "id": -284 + }, + { + "name": "minecraft:polished_blackstone_brick_stairs", + "id": -275 + }, + { + "name": "minecraft:polished_blackstone_brick_wall", + "id": -278 + }, + { + "name": "minecraft:polished_blackstone_bricks", + "id": -274 + }, + { + "name": "minecraft:polished_blackstone_button", + "id": -296 + }, + { + "name": "minecraft:polished_blackstone_double_slab", + "id": -294 + }, + { + "name": "minecraft:polished_blackstone_pressure_plate", + "id": -295 + }, + { + "name": "minecraft:polished_blackstone_slab", + "id": -293 + }, + { + "name": "minecraft:polished_blackstone_stairs", + "id": -292 + }, + { + "name": "minecraft:polished_blackstone_wall", + "id": -297 + }, + { + "name": "minecraft:polished_deepslate", + "id": -383 + }, + { + "name": "minecraft:polished_deepslate_double_slab", + "id": -397 + }, + { + "name": "minecraft:polished_deepslate_slab", + "id": -384 + }, + { + "name": "minecraft:polished_deepslate_stairs", + "id": -385 + }, + { + "name": "minecraft:polished_deepslate_wall", + "id": -386 + }, + { + "name": "minecraft:polished_diorite", + "id": -593 + }, + { + "name": "minecraft:polished_diorite_stairs", + "id": -173 + }, + { + "name": "minecraft:polished_granite", + "id": -591 + }, + { + "name": "minecraft:polished_granite_stairs", + "id": -172 + }, + { + "name": "minecraft:polished_tuff", + "id": -748 + }, + { + "name": "minecraft:polished_tuff_double_slab", + "id": -750 + }, + { + "name": "minecraft:polished_tuff_slab", + "id": -749 + }, + { + "name": "minecraft:polished_tuff_stairs", + "id": -751 + }, + { + "name": "minecraft:polished_tuff_wall", + "id": -752 + }, + { + "name": "minecraft:popped_chorus_fruit", + "id": 570 + }, + { + "name": "minecraft:porkchop", + "id": 263 + }, + { + "name": "minecraft:portal", + "id": 90 + }, + { + "name": "minecraft:potato", + "id": 281 + }, + { + "name": "minecraft:potatoes", + "id": 142 + }, + { + "name": "minecraft:potion", + "id": 430 + }, + { + "name": "minecraft:powder_snow", + "id": -306 + }, + { + "name": "minecraft:powder_snow_bucket", + "id": 371 + }, + { + "name": "minecraft:powered_comparator", + "id": 150 + }, + { + "name": "minecraft:powered_repeater", + "id": 94 + }, + { + "name": "minecraft:prismarine", + "id": 168 + }, + { + "name": "minecraft:prismarine_bricks_stairs", + "id": -4 + }, + { + "name": "minecraft:prismarine_crystals", + "id": 560 + }, + { + "name": "minecraft:prismarine_shard", + "id": 576 + }, + { + "name": "minecraft:prismarine_stairs", + "id": -2 + }, + { + "name": "minecraft:prize_pottery_sherd", + "id": 682 + }, + { + "name": "minecraft:pufferfish", + "id": 268 + }, + { + "name": "minecraft:pufferfish_bucket", + "id": 370 + }, + { + "name": "minecraft:pufferfish_spawn_egg", + "id": 486 + }, + { + "name": "minecraft:pumpkin", + "id": 86 + }, + { + "name": "minecraft:pumpkin_pie", + "id": 285 + }, + { + "name": "minecraft:pumpkin_seeds", + "id": 293 + }, + { + "name": "minecraft:pumpkin_stem", + "id": 104 + }, + { + "name": "minecraft:purple_candle", + "id": -423 + }, + { + "name": "minecraft:purple_candle_cake", + "id": -440 + }, + { + "name": "minecraft:purple_carpet", + "id": -606 + }, + { + "name": "minecraft:purple_concrete", + "id": -637 + }, + { + "name": "minecraft:purple_concrete_powder", + "id": -718 + }, + { + "name": "minecraft:purple_dye", + "id": 404 + }, + { + "name": "minecraft:purple_glazed_terracotta", + "id": 219 + }, + { + "name": "minecraft:purple_shulker_box", + "id": -622 + }, + { + "name": "minecraft:purple_stained_glass", + "id": -682 + }, + { + "name": "minecraft:purple_stained_glass_pane", + "id": -652 + }, + { + "name": "minecraft:purple_terracotta", + "id": -733 + }, + { + "name": "minecraft:purple_wool", + "id": -564 + }, + { + "name": "minecraft:purpur_block", + "id": 201 + }, + { + "name": "minecraft:purpur_stairs", + "id": 203 + }, + { + "name": "minecraft:quartz", + "id": 535 + }, + { + "name": "minecraft:quartz_block", + "id": 155 + }, + { + "name": "minecraft:quartz_bricks", + "id": -304 + }, + { + "name": "minecraft:quartz_ore", + "id": 153 + }, + { + "name": "minecraft:quartz_stairs", + "id": 156 + }, + { + "name": "minecraft:rabbit", + "id": 289 + }, + { + "name": "minecraft:rabbit_foot", + "id": 539 + }, + { + "name": "minecraft:rabbit_hide", + "id": 540 + }, + { + "name": "minecraft:rabbit_spawn_egg", + "id": 463 + }, + { + "name": "minecraft:rabbit_stew", + "id": 291 + }, + { + "name": "minecraft:rail", + "id": 66 + }, + { + "name": "minecraft:raiser_armor_trim_smithing_template", + "id": 702 + }, + { + "name": "minecraft:rapid_fertilizer", + "id": 608 + }, + { + "name": "minecraft:ravager_spawn_egg", + "id": 498 + }, + { + "name": "minecraft:raw_copper", + "id": 518 + }, + { + "name": "minecraft:raw_copper_block", + "id": -452 + }, + { + "name": "minecraft:raw_gold", + "id": 517 + }, + { + "name": "minecraft:raw_gold_block", + "id": -453 + }, + { + "name": "minecraft:raw_iron", + "id": 516 + }, + { + "name": "minecraft:raw_iron_block", + "id": -451 + }, + { + "name": "minecraft:recovery_compass", + "id": 657 + }, + { + "name": "minecraft:red_candle", + "id": -427 + }, + { + "name": "minecraft:red_candle_cake", + "id": -444 + }, + { + "name": "minecraft:red_carpet", + "id": -610 + }, + { + "name": "minecraft:red_concrete", + "id": -641 + }, + { + "name": "minecraft:red_concrete_powder", + "id": -722 + }, + { + "name": "minecraft:red_dye", + "id": 400 + }, + { + "name": "minecraft:red_flower", + "id": 38 + }, + { + "name": "minecraft:red_glazed_terracotta", + "id": 234 + }, + { + "name": "minecraft:red_mushroom", + "id": 40 + }, + { + "name": "minecraft:red_mushroom_block", + "id": 100 + }, + { + "name": "minecraft:red_nether_brick", + "id": 215 + }, + { + "name": "minecraft:red_nether_brick_stairs", + "id": -184 + }, + { + "name": "minecraft:red_sandstone", + "id": 179 + }, + { + "name": "minecraft:red_sandstone_stairs", + "id": 180 + }, + { + "name": "minecraft:red_shulker_box", + "id": -626 + }, + { + "name": "minecraft:red_stained_glass", + "id": -686 + }, + { + "name": "minecraft:red_stained_glass_pane", + "id": -656 + }, + { + "name": "minecraft:red_terracotta", + "id": -737 + }, + { + "name": "minecraft:red_wool", + "id": -556 + }, + { + "name": "minecraft:redstone", + "id": 376 + }, + { + "name": "minecraft:redstone_block", + "id": 152 + }, + { + "name": "minecraft:redstone_lamp", + "id": 123 + }, + { + "name": "minecraft:redstone_ore", + "id": 73 + }, + { + "name": "minecraft:redstone_torch", + "id": 76 + }, + { + "name": "minecraft:redstone_wire", + "id": 55 + }, + { + "name": "minecraft:reinforced_deepslate", + "id": -466 + }, + { + "name": "minecraft:repeater", + "id": 423 + }, + { + "name": "minecraft:repeating_command_block", + "id": 188 + }, + { + "name": "minecraft:reserved6", + "id": 255 + }, + { + "name": "minecraft:respawn_anchor", + "id": -272 + }, + { + "name": "minecraft:rib_armor_trim_smithing_template", + "id": 698 + }, + { + "name": "minecraft:rotten_flesh", + "id": 278 + }, + { + "name": "minecraft:saddle", + "id": 374 + }, + { + "name": "minecraft:salmon", + "id": 266 + }, + { + "name": "minecraft:salmon_bucket", + "id": 368 + }, + { + "name": "minecraft:salmon_spawn_egg", + "id": 487 + }, + { + "name": "minecraft:sand", + "id": 12 + }, + { + "name": "minecraft:sandstone", + "id": 24 + }, + { + "name": "minecraft:sandstone_stairs", + "id": 128 + }, + { + "name": "minecraft:sapling", + "id": 6 + }, + { + "name": "minecraft:scaffolding", + "id": -165 + }, + { + "name": "minecraft:sculk", + "id": -458 + }, + { + "name": "minecraft:sculk_catalyst", + "id": -460 + }, + { + "name": "minecraft:sculk_sensor", + "id": -307 + }, + { + "name": "minecraft:sculk_shrieker", + "id": -461 + }, + { + "name": "minecraft:sculk_vein", + "id": -459 + }, + { + "name": "minecraft:sea_lantern", + "id": 169 + }, + { + "name": "minecraft:sea_pickle", + "id": -156 + }, + { + "name": "minecraft:seagrass", + "id": -130 + }, + { + "name": "minecraft:sentry_armor_trim_smithing_template", + "id": 689 + }, + { + "name": "minecraft:shaper_armor_trim_smithing_template", + "id": 703 + }, + { + "name": "minecraft:sheaf_pottery_sherd", + "id": 683 + }, + { + "name": "minecraft:shears", + "id": 425 + }, + { + "name": "minecraft:sheep_spawn_egg", + "id": 442 + }, + { + "name": "minecraft:shelter_pottery_sherd", + "id": 684 + }, + { + "name": "minecraft:shield", + "id": 358 + }, + { + "name": "minecraft:shroomlight", + "id": -230 + }, + { + "name": "minecraft:shulker_box", + "id": 725 + }, + { + "name": "minecraft:shulker_shell", + "id": 577 + }, + { + "name": "minecraft:shulker_spawn_egg", + "id": 474 + }, + { + "name": "minecraft:silence_armor_trim_smithing_template", + "id": 700 + }, + { + "name": "minecraft:silver_glazed_terracotta", + "id": 228 + }, + { + "name": "minecraft:silverfish_spawn_egg", + "id": 447 + }, + { + "name": "minecraft:skeleton_horse_spawn_egg", + "id": 472 + }, + { + "name": "minecraft:skeleton_spawn_egg", + "id": 448 + }, + { + "name": "minecraft:skull", + "id": 527 + }, + { + "name": "minecraft:skull_banner_pattern", + "id": 594 + }, + { + "name": "minecraft:skull_pottery_sherd", + "id": 685 + }, + { + "name": "minecraft:slime", + "id": 165 + }, + { + "name": "minecraft:slime_ball", + "id": 392 + }, + { + "name": "minecraft:slime_spawn_egg", + "id": 449 + }, + { + "name": "minecraft:small_amethyst_bud", + "id": -332 + }, + { + "name": "minecraft:small_dripleaf_block", + "id": -336 + }, + { + "name": "minecraft:smithing_table", + "id": -202 + }, + { + "name": "minecraft:smoker", + "id": -198 + }, + { + "name": "minecraft:smooth_basalt", + "id": -377 + }, + { + "name": "minecraft:smooth_quartz_stairs", + "id": -185 + }, + { + "name": "minecraft:smooth_red_sandstone_stairs", + "id": -176 + }, + { + "name": "minecraft:smooth_sandstone_stairs", + "id": -177 + }, + { + "name": "minecraft:smooth_stone", + "id": -183 + }, + { + "name": "minecraft:sniffer_egg", + "id": -596 + }, + { + "name": "minecraft:sniffer_spawn_egg", + "id": 505 + }, + { + "name": "minecraft:snort_pottery_sherd", + "id": 686 + }, + { + "name": "minecraft:snout_armor_trim_smithing_template", + "id": 697 + }, + { + "name": "minecraft:snow", + "id": 80 + }, + { + "name": "minecraft:snow_golem_spawn_egg", + "id": 511 + }, + { + "name": "minecraft:snow_layer", + "id": 78 + }, + { + "name": "minecraft:snowball", + "id": 377 + }, + { + "name": "minecraft:soul_campfire", + "id": 633 + }, + { + "name": "minecraft:soul_fire", + "id": -237 + }, + { + "name": "minecraft:soul_lantern", + "id": -269 + }, + { + "name": "minecraft:soul_sand", + "id": 88 + }, + { + "name": "minecraft:soul_soil", + "id": -236 + }, + { + "name": "minecraft:soul_torch", + "id": -268 + }, + { + "name": "minecraft:sparkler", + "id": 611 + }, + { + "name": "minecraft:spawn_egg", + "id": 732 + }, + { + "name": "minecraft:spider_eye", + "id": 279 + }, + { + "name": "minecraft:spider_spawn_egg", + "id": 450 + }, + { + "name": "minecraft:spire_armor_trim_smithing_template", + "id": 699 + }, + { + "name": "minecraft:splash_potion", + "id": 572 + }, + { + "name": "minecraft:sponge", + "id": 19 + }, + { + "name": "minecraft:spore_blossom", + "id": -321 + }, + { + "name": "minecraft:spruce_boat", + "id": 382 + }, + { + "name": "minecraft:spruce_button", + "id": -144 + }, + { + "name": "minecraft:spruce_chest_boat", + "id": 652 + }, + { + "name": "minecraft:spruce_door", + "id": 564 + }, + { + "name": "minecraft:spruce_double_slab", + "id": -809 + }, + { + "name": "minecraft:spruce_fence", + "id": -579 + }, + { + "name": "minecraft:spruce_fence_gate", + "id": 183 + }, + { + "name": "minecraft:spruce_hanging_sign", + "id": -501 + }, + { + "name": "minecraft:spruce_leaves", + "id": -800 + }, + { + "name": "minecraft:spruce_log", + "id": -569 + }, + { + "name": "minecraft:spruce_planks", + "id": -739 + }, + { + "name": "minecraft:spruce_pressure_plate", + "id": -154 + }, + { + "name": "minecraft:spruce_sign", + "id": 587 + }, + { + "name": "minecraft:spruce_slab", + "id": -804 + }, + { + "name": "minecraft:spruce_stairs", + "id": 134 + }, + { + "name": "minecraft:spruce_standing_sign", + "id": -181 + }, + { + "name": "minecraft:spruce_trapdoor", + "id": -149 + }, + { + "name": "minecraft:spruce_wall_sign", + "id": -182 + }, + { + "name": "minecraft:spruce_wood", + "id": -814 + }, + { + "name": "minecraft:spyglass", + "id": 636 + }, + { + "name": "minecraft:squid_spawn_egg", + "id": 454 + }, + { + "name": "minecraft:stained_glass", + "id": 723 + }, + { + "name": "minecraft:stained_glass_pane", + "id": 724 + }, + { + "name": "minecraft:stained_hardened_clay", + "id": 706 + }, + { + "name": "minecraft:standing_banner", + "id": 176 + }, + { + "name": "minecraft:standing_sign", + "id": 63 + }, + { + "name": "minecraft:stick", + "id": 323 + }, + { + "name": "minecraft:sticky_piston", + "id": 29 + }, + { + "name": "minecraft:sticky_piston_arm_collision", + "id": -217 + }, + { + "name": "minecraft:stone", + "id": 1 + }, + { + "name": "minecraft:stone_axe", + "id": 318 + }, + { + "name": "minecraft:stone_block_slab", + "id": 44 + }, + { + "name": "minecraft:stone_block_slab2", + "id": 182 + }, + { + "name": "minecraft:stone_block_slab3", + "id": -162 + }, + { + "name": "minecraft:stone_block_slab4", + "id": -166 + }, + { + "name": "minecraft:stone_brick_stairs", + "id": 109 + }, + { + "name": "minecraft:stone_button", + "id": 77 + }, + { + "name": "minecraft:stone_hoe", + "id": 333 + }, + { + "name": "minecraft:stone_pickaxe", + "id": 317 + }, + { + "name": "minecraft:stone_pressure_plate", + "id": 70 + }, + { + "name": "minecraft:stone_shovel", + "id": 316 + }, + { + "name": "minecraft:stone_stairs", + "id": 67 + }, + { + "name": "minecraft:stone_sword", + "id": 315 + }, + { + "name": "minecraft:stonebrick", + "id": 98 + }, + { + "name": "minecraft:stonecutter", + "id": 245 + }, + { + "name": "minecraft:stonecutter_block", + "id": -197 + }, + { + "name": "minecraft:stray_spawn_egg", + "id": 466 + }, + { + "name": "minecraft:strider_spawn_egg", + "id": 500 + }, + { + "name": "minecraft:string", + "id": 329 + }, + { + "name": "minecraft:stripped_acacia_log", + "id": -8 + }, + { + "name": "minecraft:stripped_acacia_wood", + "id": -823 + }, + { + "name": "minecraft:stripped_bamboo_block", + "id": -528 + }, + { + "name": "minecraft:stripped_birch_log", + "id": -6 + }, + { + "name": "minecraft:stripped_birch_wood", + "id": -821 + }, + { + "name": "minecraft:stripped_cherry_log", + "id": -535 + }, + { + "name": "minecraft:stripped_cherry_wood", + "id": -545 + }, + { + "name": "minecraft:stripped_crimson_hyphae", + "id": -300 + }, + { + "name": "minecraft:stripped_crimson_stem", + "id": -240 + }, + { + "name": "minecraft:stripped_dark_oak_log", + "id": -9 + }, + { + "name": "minecraft:stripped_dark_oak_wood", + "id": -824 + }, + { + "name": "minecraft:stripped_jungle_log", + "id": -7 + }, + { + "name": "minecraft:stripped_jungle_wood", + "id": -822 + }, + { + "name": "minecraft:stripped_mangrove_log", + "id": -485 + }, + { + "name": "minecraft:stripped_mangrove_wood", + "id": -498 + }, + { + "name": "minecraft:stripped_oak_log", + "id": -10 + }, + { + "name": "minecraft:stripped_oak_wood", + "id": -819 + }, + { + "name": "minecraft:stripped_spruce_log", + "id": -5 + }, + { + "name": "minecraft:stripped_spruce_wood", + "id": -820 + }, + { + "name": "minecraft:stripped_warped_hyphae", + "id": -301 + }, + { + "name": "minecraft:stripped_warped_stem", + "id": -241 + }, + { + "name": "minecraft:structure_block", + "id": 252 + }, + { + "name": "minecraft:structure_void", + "id": 217 + }, + { + "name": "minecraft:sugar", + "id": 420 + }, + { + "name": "minecraft:sugar_cane", + "id": 389 + }, + { + "name": "minecraft:suspicious_gravel", + "id": -573 + }, + { + "name": "minecraft:suspicious_sand", + "id": -529 + }, + { + "name": "minecraft:suspicious_stew", + "id": 601 + }, + { + "name": "minecraft:sweet_berries", + "id": 288 + }, + { + "name": "minecraft:sweet_berry_bush", + "id": -207 + }, + { + "name": "minecraft:tadpole_bucket", + "id": 641 + }, + { + "name": "minecraft:tadpole_spawn_egg", + "id": 640 + }, + { + "name": "minecraft:tallgrass", + "id": 31 + }, + { + "name": "minecraft:target", + "id": -239 + }, + { + "name": "minecraft:tide_armor_trim_smithing_template", + "id": 696 + }, + { + "name": "minecraft:tinted_glass", + "id": -334 + }, + { + "name": "minecraft:tnt", + "id": 46 + }, + { + "name": "minecraft:tnt_minecart", + "id": 536 + }, + { + "name": "minecraft:torch", + "id": 50 + }, + { + "name": "minecraft:torchflower", + "id": -568 + }, + { + "name": "minecraft:torchflower_crop", + "id": -567 + }, + { + "name": "minecraft:torchflower_seeds", + "id": 297 + }, + { + "name": "minecraft:totem_of_undying", + "id": 579 + }, + { + "name": "minecraft:trader_llama_spawn_egg", + "id": 659 + }, + { + "name": "minecraft:trapdoor", + "id": 96 + }, + { + "name": "minecraft:trapped_chest", + "id": 146 + }, + { + "name": "minecraft:trial_key", + "id": 707 + }, + { + "name": "minecraft:trial_spawner", + "id": -315 + }, + { + "name": "minecraft:trident", + "id": 557 + }, + { + "name": "minecraft:trip_wire", + "id": 132 + }, + { + "name": "minecraft:tripwire_hook", + "id": 131 + }, + { + "name": "minecraft:tropical_fish", + "id": 267 + }, + { + "name": "minecraft:tropical_fish_bucket", + "id": 369 + }, + { + "name": "minecraft:tropical_fish_spawn_egg", + "id": 484 + }, + { + "name": "minecraft:tube_coral", + "id": -131 + }, + { + "name": "minecraft:tuff", + "id": -333 + }, + { + "name": "minecraft:tuff_brick_double_slab", + "id": -756 + }, + { + "name": "minecraft:tuff_brick_slab", + "id": -755 + }, + { + "name": "minecraft:tuff_brick_stairs", + "id": -757 + }, + { + "name": "minecraft:tuff_brick_wall", + "id": -758 + }, + { + "name": "minecraft:tuff_bricks", + "id": -754 + }, + { + "name": "minecraft:tuff_double_slab", + "id": -745 + }, + { + "name": "minecraft:tuff_slab", + "id": -744 + }, + { + "name": "minecraft:tuff_stairs", + "id": -746 + }, + { + "name": "minecraft:tuff_wall", + "id": -747 + }, + { + "name": "minecraft:turtle_egg", + "id": -159 + }, + { + "name": "minecraft:turtle_helmet", + "id": 584 + }, + { + "name": "minecraft:turtle_scute", + "id": 583 + }, + { + "name": "minecraft:turtle_spawn_egg", + "id": 490 + }, + { + "name": "minecraft:twisting_vines", + "id": -287 + }, + { + "name": "minecraft:underwater_torch", + "id": 239 + }, + { + "name": "minecraft:undyed_shulker_box", + "id": 205 + }, + { + "name": "minecraft:unknown", + "id": -305 + }, + { + "name": "minecraft:unlit_redstone_torch", + "id": 75 + }, + { + "name": "minecraft:unpowered_comparator", + "id": 149 + }, + { + "name": "minecraft:unpowered_repeater", + "id": 93 + }, + { + "name": "minecraft:vault", + "id": -314 + }, + { + "name": "minecraft:verdant_froglight", + "id": -470 + }, + { + "name": "minecraft:vex_armor_trim_smithing_template", + "id": 695 + }, + { + "name": "minecraft:vex_spawn_egg", + "id": 481 + }, + { + "name": "minecraft:villager_spawn_egg", + "id": 453 + }, + { + "name": "minecraft:vindicator_spawn_egg", + "id": 479 + }, + { + "name": "minecraft:vine", + "id": 106 + }, + { + "name": "minecraft:wall_banner", + "id": 177 + }, + { + "name": "minecraft:wall_sign", + "id": 68 + }, + { + "name": "minecraft:wandering_trader_spawn_egg", + "id": 497 + }, + { + "name": "minecraft:ward_armor_trim_smithing_template", + "id": 693 + }, + { + "name": "minecraft:warden_spawn_egg", + "id": 643 + }, + { + "name": "minecraft:warped_button", + "id": -261 + }, + { + "name": "minecraft:warped_door", + "id": 628 + }, + { + "name": "minecraft:warped_double_slab", + "id": -267 + }, + { + "name": "minecraft:warped_fence", + "id": -257 + }, + { + "name": "minecraft:warped_fence_gate", + "id": -259 + }, + { + "name": "minecraft:warped_fungus", + "id": -229 + }, + { + "name": "minecraft:warped_fungus_on_a_stick", + "id": 629 + }, + { + "name": "minecraft:warped_hanging_sign", + "id": -507 + }, + { + "name": "minecraft:warped_hyphae", + "id": -298 + }, + { + "name": "minecraft:warped_nylium", + "id": -233 + }, + { + "name": "minecraft:warped_planks", + "id": -243 + }, + { + "name": "minecraft:warped_pressure_plate", + "id": -263 + }, + { + "name": "minecraft:warped_roots", + "id": -224 + }, + { + "name": "minecraft:warped_sign", + "id": 626 + }, + { + "name": "minecraft:warped_slab", + "id": -265 + }, + { + "name": "minecraft:warped_stairs", + "id": -255 + }, + { + "name": "minecraft:warped_standing_sign", + "id": -251 + }, + { + "name": "minecraft:warped_stem", + "id": -226 + }, + { + "name": "minecraft:warped_trapdoor", + "id": -247 + }, + { + "name": "minecraft:warped_wall_sign", + "id": -253 + }, + { + "name": "minecraft:warped_wart_block", + "id": -227 + }, + { + "name": "minecraft:water", + "id": 9 + }, + { + "name": "minecraft:water_bucket", + "id": 365 + }, + { + "name": "minecraft:waterlily", + "id": 111 + }, + { + "name": "minecraft:waxed_chiseled_copper", + "id": -764 + }, + { + "name": "minecraft:waxed_copper", + "id": -344 + }, + { + "name": "minecraft:waxed_copper_bulb", + "id": -780 + }, + { + "name": "minecraft:waxed_copper_door", + "id": -788 + }, + { + "name": "minecraft:waxed_copper_grate", + "id": -772 + }, + { + "name": "minecraft:waxed_copper_trapdoor", + "id": -796 + }, + { + "name": "minecraft:waxed_cut_copper", + "id": -351 + }, + { + "name": "minecraft:waxed_cut_copper_slab", + "id": -365 + }, + { + "name": "minecraft:waxed_cut_copper_stairs", + "id": -358 + }, + { + "name": "minecraft:waxed_double_cut_copper_slab", + "id": -372 + }, + { + "name": "minecraft:waxed_exposed_chiseled_copper", + "id": -765 + }, + { + "name": "minecraft:waxed_exposed_copper", + "id": -345 + }, + { + "name": "minecraft:waxed_exposed_copper_bulb", + "id": -781 + }, + { + "name": "minecraft:waxed_exposed_copper_door", + "id": -789 + }, + { + "name": "minecraft:waxed_exposed_copper_grate", + "id": -773 + }, + { + "name": "minecraft:waxed_exposed_copper_trapdoor", + "id": -797 + }, + { + "name": "minecraft:waxed_exposed_cut_copper", + "id": -352 + }, + { + "name": "minecraft:waxed_exposed_cut_copper_slab", + "id": -366 + }, + { + "name": "minecraft:waxed_exposed_cut_copper_stairs", + "id": -359 + }, + { + "name": "minecraft:waxed_exposed_double_cut_copper_slab", + "id": -373 + }, + { + "name": "minecraft:waxed_oxidized_chiseled_copper", + "id": -766 + }, + { + "name": "minecraft:waxed_oxidized_copper", + "id": -446 + }, + { + "name": "minecraft:waxed_oxidized_copper_bulb", + "id": -783 + }, + { + "name": "minecraft:waxed_oxidized_copper_door", + "id": -791 + }, + { + "name": "minecraft:waxed_oxidized_copper_grate", + "id": -775 + }, + { + "name": "minecraft:waxed_oxidized_copper_trapdoor", + "id": -799 + }, + { + "name": "minecraft:waxed_oxidized_cut_copper", + "id": -447 + }, + { + "name": "minecraft:waxed_oxidized_cut_copper_slab", + "id": -449 + }, + { + "name": "minecraft:waxed_oxidized_cut_copper_stairs", + "id": -448 + }, + { + "name": "minecraft:waxed_oxidized_double_cut_copper_slab", + "id": -450 + }, + { + "name": "minecraft:waxed_weathered_chiseled_copper", + "id": -767 + }, + { + "name": "minecraft:waxed_weathered_copper", + "id": -346 + }, + { + "name": "minecraft:waxed_weathered_copper_bulb", + "id": -782 + }, + { + "name": "minecraft:waxed_weathered_copper_door", + "id": -790 + }, + { + "name": "minecraft:waxed_weathered_copper_grate", + "id": -774 + }, + { + "name": "minecraft:waxed_weathered_copper_trapdoor", + "id": -798 + }, + { + "name": "minecraft:waxed_weathered_cut_copper", + "id": -353 + }, + { + "name": "minecraft:waxed_weathered_cut_copper_slab", + "id": -367 + }, + { + "name": "minecraft:waxed_weathered_cut_copper_stairs", + "id": -360 + }, + { + "name": "minecraft:waxed_weathered_double_cut_copper_slab", + "id": -374 + }, + { + "name": "minecraft:wayfinder_armor_trim_smithing_template", + "id": 701 + }, + { + "name": "minecraft:weathered_chiseled_copper", + "id": -762 + }, + { + "name": "minecraft:weathered_copper", + "id": -342 + }, + { + "name": "minecraft:weathered_copper_bulb", + "id": -778 + }, + { + "name": "minecraft:weathered_copper_door", + "id": -786 + }, + { + "name": "minecraft:weathered_copper_grate", + "id": -770 + }, + { + "name": "minecraft:weathered_copper_trapdoor", + "id": -794 + }, + { + "name": "minecraft:weathered_cut_copper", + "id": -349 + }, + { + "name": "minecraft:weathered_cut_copper_slab", + "id": -363 + }, + { + "name": "minecraft:weathered_cut_copper_stairs", + "id": -356 + }, + { + "name": "minecraft:weathered_double_cut_copper_slab", + "id": -370 + }, + { + "name": "minecraft:web", + "id": 30 + }, + { + "name": "minecraft:weeping_vines", + "id": -231 + }, + { + "name": "minecraft:wheat", + "id": 337 + }, + { + "name": "minecraft:wheat_seeds", + "id": 292 + }, + { + "name": "minecraft:white_candle", + "id": -413 + }, + { + "name": "minecraft:white_candle_cake", + "id": -430 + }, + { + "name": "minecraft:white_carpet", + "id": 171 + }, + { + "name": "minecraft:white_concrete", + "id": 236 + }, + { + "name": "minecraft:white_concrete_powder", + "id": 237 + }, + { + "name": "minecraft:white_dye", + "id": 414 + }, + { + "name": "minecraft:white_glazed_terracotta", + "id": 220 + }, + { + "name": "minecraft:white_shulker_box", + "id": 218 + }, + { + "name": "minecraft:white_stained_glass", + "id": 241 + }, + { + "name": "minecraft:white_stained_glass_pane", + "id": 160 + }, + { + "name": "minecraft:white_terracotta", + "id": 159 + }, + { + "name": "minecraft:white_wool", + "id": 35 + }, + { + "name": "minecraft:wild_armor_trim_smithing_template", + "id": 692 + }, + { + "name": "minecraft:wind_charge", + "id": 378 + }, + { + "name": "minecraft:witch_spawn_egg", + "id": 456 + }, + { + "name": "minecraft:wither_rose", + "id": -216 + }, + { + "name": "minecraft:wither_skeleton_spawn_egg", + "id": 469 + }, + { + "name": "minecraft:wither_spawn_egg", + "id": 513 + }, + { + "name": "minecraft:wolf_armor", + "id": 710 + }, + { + "name": "minecraft:wolf_spawn_egg", + "id": 443 + }, + { + "name": "minecraft:wood", + "id": 726 + }, + { + "name": "minecraft:wooden_axe", + "id": 314 + }, + { + "name": "minecraft:wooden_button", + "id": 143 + }, + { + "name": "minecraft:wooden_door", + "id": 362 + }, + { + "name": "minecraft:wooden_hoe", + "id": 332 + }, + { + "name": "minecraft:wooden_pickaxe", + "id": 313 + }, + { + "name": "minecraft:wooden_pressure_plate", + "id": 72 + }, + { + "name": "minecraft:wooden_shovel", + "id": 312 + }, + { + "name": "minecraft:wooden_slab", + "id": 717 + }, + { + "name": "minecraft:wooden_sword", + "id": 311 + }, + { + "name": "minecraft:wool", + "id": 711 + }, + { + "name": "minecraft:writable_book", + "id": 521 + }, + { + "name": "minecraft:written_book", + "id": 522 + }, + { + "name": "minecraft:yellow_candle", + "id": -417 + }, + { + "name": "minecraft:yellow_candle_cake", + "id": -434 + }, + { + "name": "minecraft:yellow_carpet", + "id": -600 + }, + { + "name": "minecraft:yellow_concrete", + "id": -631 + }, + { + "name": "minecraft:yellow_concrete_powder", + "id": -712 + }, + { + "name": "minecraft:yellow_dye", + "id": 410 + }, + { + "name": "minecraft:yellow_flower", + "id": 37 + }, + { + "name": "minecraft:yellow_glazed_terracotta", + "id": 224 + }, + { + "name": "minecraft:yellow_shulker_box", + "id": -616 + }, + { + "name": "minecraft:yellow_stained_glass", + "id": -676 + }, + { + "name": "minecraft:yellow_stained_glass_pane", + "id": -646 + }, + { + "name": "minecraft:yellow_terracotta", + "id": -727 + }, + { + "name": "minecraft:yellow_wool", + "id": -558 + }, + { + "name": "minecraft:zoglin_spawn_egg", + "id": 503 + }, + { + "name": "minecraft:zombie_horse_spawn_egg", + "id": 473 + }, + { + "name": "minecraft:zombie_pigman_spawn_egg", + "id": 452 + }, + { + "name": "minecraft:zombie_spawn_egg", + "id": 451 + }, + { + "name": "minecraft:zombie_villager_spawn_egg", + "id": 482 + } +] \ No newline at end of file diff --git a/core/src/main/resources/mappings b/core/src/main/resources/mappings index 522967d6e..c96c53850 160000 --- a/core/src/main/resources/mappings +++ b/core/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit 522967d6ee76972994ad05a992dc9d7bb4e889ba +Subproject commit c96c53850b720a0238e1a398a49b24b0a0887da7 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4ce5dda1a..41e1ebaec 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,10 +9,10 @@ netty = "4.1.103.Final" guava = "29.0-jre" gson = "2.3.1" # Provided by Spigot 1.8.8 websocket = "1.5.1" -protocol = "3.0.0.Beta1-20240204.134050-120" -protocol-connection = "3.0.0.Beta1-20240204.134050-119" +protocol = "3.0.0.Beta1-20240226.201527-125" +protocol-connection = "3.0.0.Beta1-20240226.201527-124" raknet = "1.0.0.CR1-20231206.145325-12" -blockstateupdater="1.20.60-20240129.140535-1" +blockstateupdater="1.20.70-20240303.125052-2" mcauthlib = "d9d773e" mcprotocollib = "1.20.4-2-20240116.220521-7" adventure = "4.14.0" From 7e4d97f6e135d3c80b26f7f17248b90ec6e83266 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Wed, 13 Mar 2024 02:05:41 -0700 Subject: [PATCH 204/344] Fix wooden slabs (#4489) * Fix wooden slabs Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Update submodule Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Also indicate 1.20.71 support Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --------- Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- README.md | 2 +- .../org/geysermc/geyser/network/GameProtocol.java | 2 +- .../geyser/registry/populator/Conversion662_649.java | 11 +++++++++++ core/src/main/resources/mappings | 2 +- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c6445155f..76a62a462 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,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.20.40 - 1.20.70 and Minecraft Java 1.20.4 +### Currently supporting Minecraft Bedrock 1.20.40 - 1.20.71 and Minecraft Java 1.20.4 ## 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/GameProtocol.java b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java index 3ead79d9e..80d2038d9 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java @@ -72,7 +72,7 @@ public final class GameProtocol { .minecraftVersion("1.20.60/1.20.62") .build()); SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC.toBuilder() - .minecraftVersion("1.20.70") + .minecraftVersion("1.20.70/1.20.71") .build()); } diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion662_649.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion662_649.java index 6dc6b01a0..cddeae7bf 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion662_649.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion662_649.java @@ -67,6 +67,17 @@ public class Conversion662_649 { } } + if (NEW_SLABS.contains(identifer)) { + switch (identifer) { + case "minecraft:oak_slab" -> { return mapping.withBedrockIdentifier("minecraft:wooden_slab").withBedrockData(0); } + case "minecraft:spruce_slab" -> { return mapping.withBedrockIdentifier("minecraft:wooden_slab").withBedrockData(1); } + case "minecraft:birch_slab" -> { return mapping.withBedrockIdentifier("minecraft:wooden_slab").withBedrockData(2); } + case "minecraft:jungle_slab" -> { return mapping.withBedrockIdentifier("minecraft:wooden_slab").withBedrockData(3); } + case "minecraft:acacia_slab" -> { return mapping.withBedrockIdentifier("minecraft:wooden_slab").withBedrockData(4); } + case "minecraft:dark_oak_slab" -> { return mapping.withBedrockIdentifier("minecraft:wooden_slab").withBedrockData(5); } + } + } + if (NEW_LEAVES.contains(identifer) || NEW_LEAVES2.contains(identifer)) { switch (identifer) { case "minecraft:oak_leaves" -> { return mapping.withBedrockIdentifier("minecraft:leaves").withBedrockData(0); } diff --git a/core/src/main/resources/mappings b/core/src/main/resources/mappings index c96c53850..b1883ca53 160000 --- a/core/src/main/resources/mappings +++ b/core/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit c96c53850b720a0238e1a398a49b24b0a0887da7 +Subproject commit b1883ca53afc082de98aeb062ba2fad00e069617 From a9467cf150bf2f0af36849b6a47abd23db8be83b Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Wed, 13 Mar 2024 02:54:39 -0700 Subject: [PATCH 205/344] Temporary bad fix for command crashing (#4490) Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .../java/org/geysermc/geyser/session/GeyserSession.java | 7 +++++++ .../translator/protocol/java/JavaCommandsTranslator.java | 8 ++++++++ 2 files changed, 15 insertions(+) diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 7a4a8ff6f..b95b5af8d 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -602,6 +602,13 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { @Setter private @Nullable ItemData currentBook = null; + /** + * Stores if we've sent AvailibleCommandsPacket to the client due to it crashing if sent twice on 1.20.70/71 + * Hopefully bedrock will have a hotfix so we can remove this + */ + @Setter + private boolean sentAvailibleCommands = false; + private final GeyserCameraData cameraData; private final GeyserEntityData entityData; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCommandsTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCommandsTranslator.java index 0d7f45c7d..7ded656dd 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCommandsTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCommandsTranslator.java @@ -46,6 +46,7 @@ import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.event.java.ServerDefineCommandsEvent; import org.geysermc.geyser.command.GeyserCommandManager; import org.geysermc.geyser.inventory.item.Enchantment; +import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.session.GeyserSession; @@ -115,6 +116,12 @@ public class JavaCommandsTranslator extends PacketTranslator commandData = new ArrayList<>(); @@ -191,6 +198,7 @@ public class JavaCommandsTranslator extends PacketTranslator Date: Wed, 13 Mar 2024 20:25:30 +0100 Subject: [PATCH 206/344] update protocol lib to resolve command crashing (#4493) --- .../java/org/geysermc/geyser/session/GeyserSession.java | 7 ------- .../translator/protocol/java/JavaCommandsTranslator.java | 8 -------- gradle/libs.versions.toml | 4 ++-- 3 files changed, 2 insertions(+), 17 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index b95b5af8d..7a4a8ff6f 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -602,13 +602,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { @Setter private @Nullable ItemData currentBook = null; - /** - * Stores if we've sent AvailibleCommandsPacket to the client due to it crashing if sent twice on 1.20.70/71 - * Hopefully bedrock will have a hotfix so we can remove this - */ - @Setter - private boolean sentAvailibleCommands = false; - private final GeyserCameraData cameraData; private final GeyserEntityData entityData; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCommandsTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCommandsTranslator.java index 7ded656dd..0d7f45c7d 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCommandsTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCommandsTranslator.java @@ -46,7 +46,6 @@ import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.event.java.ServerDefineCommandsEvent; import org.geysermc.geyser.command.GeyserCommandManager; import org.geysermc.geyser.inventory.item.Enchantment; -import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.session.GeyserSession; @@ -116,12 +115,6 @@ public class JavaCommandsTranslator extends PacketTranslator commandData = new ArrayList<>(); @@ -198,7 +191,6 @@ public class JavaCommandsTranslator extends PacketTranslator Date: Thu, 14 Mar 2024 10:27:49 +0100 Subject: [PATCH 207/344] Fix virtual lecterns - again (#4494) --- .../geyser/inventory/LecternContainer.java | 32 ++++++++++++++++++- .../inventory/LecternInventoryTranslator.java | 5 +++ .../inventory/JavaOpenBookTranslator.java | 5 +-- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/inventory/LecternContainer.java b/core/src/main/java/org/geysermc/geyser/inventory/LecternContainer.java index f5aa7b0d6..7ac2fed99 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/LecternContainer.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/LecternContainer.java @@ -26,10 +26,13 @@ package org.geysermc.geyser.inventory; import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; -import org.cloudburstmc.math.vector.Vector3i; import lombok.Getter; import lombok.Setter; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.protocol.java.inventory.JavaOpenBookTranslator; public class LecternContainer extends Container { @Getter @Setter @@ -39,7 +42,34 @@ public class LecternContainer extends Container { @Getter @Setter private Vector3i position; + // Sigh. When the lectern container is created, we don't know (yet) if it's fake or not. + // So... time for a manual check :/ + @Getter + private boolean isFakeLectern = false; + public LecternContainer(String title, int id, int size, ContainerType containerType, PlayerInventory playerInventory) { super(title, id, size, containerType, playerInventory); } + + /** + * When we are using a fake lectern, the Java server expects us to still be in a player inventory. + * We can't use {@link #isUsingRealBlock()} as that may not be determined yet. + */ + @Override + public void setItem(int slot, @NonNull GeyserItemStack newItem, GeyserSession session) { + if (isFakeLectern) { + session.getPlayerInventory().setItem(slot, newItem, session); + } else { + super.setItem(slot, newItem, session); + } + } + + /** + * This is used ONLY once to set the book of a fake lectern in {@link JavaOpenBookTranslator}. + * See {@link LecternContainer#setItem(int, GeyserItemStack, GeyserSession)} as for why this is separate. + */ + public void setFakeLecternBook(GeyserItemStack book, GeyserSession session) { + this.isFakeLectern = true; + super.setItem(0, book, session); + } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java index 7a1ec7573..9d0661b08 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java @@ -129,6 +129,11 @@ public class LecternInventoryTranslator extends AbstractBlockInventoryTranslator @Override public void updateSlot(GeyserSession session, Inventory inventory, int slot) { + // If we're not in a real lectern, the Java server thinks we are still in the player inventory. + if (((LecternContainer) inventory).isFakeLectern()) { + InventoryTranslator.PLAYER_INVENTORY_TRANSLATOR.updateSlot(session, session.getPlayerInventory(), slot); + return; + } super.updateSlot(session, inventory, slot); if (slot == 0) { updateBook(session, inventory, inventory.getItem(0)); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaOpenBookTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaOpenBookTranslator.java index f9cf4ee28..24b964b7c 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaOpenBookTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaOpenBookTranslator.java @@ -30,6 +30,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.clientbound.inventory.Cli import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClosePacket; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.Inventory; +import org.geysermc.geyser.inventory.LecternContainer; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.session.GeyserSession; @@ -79,8 +80,8 @@ public class JavaOpenBookTranslator extends PacketTranslator Date: Fri, 15 Mar 2024 13:52:34 +0100 Subject: [PATCH 208/344] More error-robust kernel version parsing (#4496) * should resolve https://github.com/GeyserMC/Geyser/issues/4492 * Use regex to parse version * yeet debug * Only log the throwable message --- .../geyser/network/netty/Bootstraps.java | 50 ++++++++----------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/Bootstraps.java b/core/src/main/java/org/geysermc/geyser/network/netty/Bootstraps.java index 9ffc45650..9f889a6e7 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/Bootstraps.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/Bootstraps.java @@ -31,18 +31,18 @@ import io.netty.channel.ChannelFuture; import io.netty.channel.epoll.Native; import io.netty.channel.unix.UnixChannelOption; import lombok.experimental.UtilityClass; +import org.geysermc.geyser.GeyserImpl; -import java.util.Optional; import java.util.concurrent.CompletableFuture; +import java.util.regex.Matcher; +import java.util.regex.Pattern; -@SuppressWarnings("OptionalUsedAsFieldOrParameterType") @UtilityClass public final class Bootstraps { - private static final Optional KERNEL_VERSION; // The REUSEPORT_AVAILABLE socket option is available starting from kernel version 3.9. // This option allows multiple sockets to listen on the same IP address and port without conflict. - private static final int[] REUSEPORT_VERSION = new int[]{3, 9, 0}; + private static final int[] REUSEPORT_VERSION = new int[]{3, 9}; private static final boolean REUSEPORT_AVAILABLE; static { @@ -50,24 +50,16 @@ public final class Bootstraps { try { kernelVersion = Native.KERNEL_VERSION; } catch (Throwable e) { + GeyserImpl.getInstance().getLogger().debug("Could not determine kernel version! " + e.getMessage()); kernelVersion = null; } - if (kernelVersion != null && kernelVersion.contains("-")) { - int index = kernelVersion.indexOf('-'); - if (index > -1) { - kernelVersion = kernelVersion.substring(0, index); - } - int[] kernelVer = fromString(kernelVersion); - KERNEL_VERSION = Optional.of(kernelVer); - REUSEPORT_AVAILABLE = checkVersion(kernelVer, 0); - } else { - KERNEL_VERSION = Optional.empty(); - REUSEPORT_AVAILABLE = false; - } - } - public static Optional getKernelVersion() { - return KERNEL_VERSION; + if (kernelVersion == null) { + REUSEPORT_AVAILABLE = false; + } else { + int[] kernelVer = fromString(kernelVersion); + REUSEPORT_AVAILABLE = checkVersion(kernelVer, 0); + } } public static boolean isReusePortAvailable() { @@ -81,17 +73,19 @@ public final class Bootstraps { } } - private static int[] fromString(String ver) { - String[] parts = ver.split("\\."); - if (parts.length < 2) { - throw new IllegalArgumentException("At least 2 version numbers required"); + private static int[] fromString(String input) { + // Match only beginning of string for at least two digits separated by dot + Pattern pattern = Pattern.compile("^(\\d+)\\.(\\d+)"); + Matcher matcher = pattern.matcher(input); + + int[] version = {0, 0}; + + if (matcher.find()) { + version[0] = Integer.parseInt(matcher.group(1)); + version[1] = Integer.parseInt(matcher.group(2)); } - return new int[]{ - Integer.parseInt(parts[0]), - Integer.parseInt(parts[1]), - parts.length == 2 ? 0 : Integer.parseInt(parts[2]) - }; + return version; } private static boolean checkVersion(int[] ver, int i) { From 112f4ddb8d8ef6d2518f6adde57300f31c6c5be1 Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 15 Mar 2024 17:33:48 +0100 Subject: [PATCH 209/344] Fix: Inventory handling when client tries to open the player inventory when it shouldn't (#4499) * attempt at fixing * Fix wrong handling of OPEN_INVENTORY case in BedrockInteractTranslator --- .../bedrock/entity/player/BedrockInteractTranslator.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockInteractTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockInteractTranslator.java index 80141f849..07e192bb7 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockInteractTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockInteractTranslator.java @@ -127,9 +127,9 @@ public class BedrockInteractTranslator extends PacketTranslator InventoryUtils.openInventory(session, session.getPlayerInventory()); } } else { - // Case: Player opens a player inventory, while we think it shouldn't have! - // Close all inventories, reset to player inventory. - InventoryUtils.closeInventory(session, session.getOpenInventory().getJavaId(), false); + // Case: Player tries to open a player inventory, while we think it should be in a different inventory + // Now: Open the inventory that we're supposed to be in. + InventoryUtils.openInventory(session, session.getOpenInventory()); } break; } From e1e09a6ccbb517bddfd4f93b6881743a760fd941 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Sat, 16 Mar 2024 08:19:09 -0700 Subject: [PATCH 210/344] Fix KQueue loading crashing macOS; Closes #4474 (#4506) --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c7138e2d8..73417f23a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -5,7 +5,7 @@ erosion = "1.0-20230406.174837-8" events = "1.1-SNAPSHOT" jackson = { strictly = "2.14.0" } # Don't let other dependencies override fastutil = "8.5.2" -netty = "4.1.103.Final" +netty = "4.1.107.Final" guava = "29.0-jre" gson = "2.3.1" # Provided by Spigot 1.8.8 websocket = "1.5.1" From b03818a0c44da311c5d163a106ce7747899df1f7 Mon Sep 17 00:00:00 2001 From: chris Date: Mon, 18 Mar 2024 19:41:36 +0100 Subject: [PATCH 211/344] Add attack damage indicator to custom items (#4495) --- .../item/custom/NonVanillaCustomItemData.java | 10 +++ .../item/GeyserNonVanillaCustomItemData.java | 15 +++++ .../java/org/geysermc/geyser/item/Items.java | 62 +++++++++---------- .../geyser/item/components/ToolTier.java | 4 -- .../org/geysermc/geyser/item/type/Item.java | 15 +++-- .../CustomItemRegistryPopulator.java | 17 ++--- 6 files changed, 76 insertions(+), 47 deletions(-) diff --git a/api/src/main/java/org/geysermc/geyser/api/item/custom/NonVanillaCustomItemData.java b/api/src/main/java/org/geysermc/geyser/api/item/custom/NonVanillaCustomItemData.java index 37a4247d1..59e2faad8 100644 --- a/api/src/main/java/org/geysermc/geyser/api/item/custom/NonVanillaCustomItemData.java +++ b/api/src/main/java/org/geysermc/geyser/api/item/custom/NonVanillaCustomItemData.java @@ -64,6 +64,14 @@ public interface NonVanillaCustomItemData extends CustomItemData { */ int maxDamage(); + /** + * Gets the attack damage of the item. + * This is purely visual, and only applied to tools + * + * @return the attack damage of the item + */ + int attackDamage(); + /** * Gets the tool type of the item. * @@ -169,6 +177,8 @@ public interface NonVanillaCustomItemData extends CustomItemData { Builder maxDamage(int maxDamage); + Builder attackDamage(int attackDamage); + Builder toolType(@Nullable String toolType); Builder toolTier(@Nullable String toolTier); diff --git a/core/src/main/java/org/geysermc/geyser/item/GeyserNonVanillaCustomItemData.java b/core/src/main/java/org/geysermc/geyser/item/GeyserNonVanillaCustomItemData.java index 14f8c3a39..9d86bfa96 100644 --- a/core/src/main/java/org/geysermc/geyser/item/GeyserNonVanillaCustomItemData.java +++ b/core/src/main/java/org/geysermc/geyser/item/GeyserNonVanillaCustomItemData.java @@ -42,6 +42,7 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i private final int javaId; private final int stackSize; private final int maxDamage; + private final int attackDamage; private final String toolType; private final String toolTier; private final String armorType; @@ -64,6 +65,7 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i this.javaId = builder.javaId; this.stackSize = builder.stackSize; this.maxDamage = builder.maxDamage; + this.attackDamage = builder.attackDamage; this.toolType = builder.toolType; this.toolTier = builder.toolTier; this.armorType = builder.armorType; @@ -98,6 +100,11 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i return maxDamage; } + @Override + public int attackDamage() { + return attackDamage; + } + @Override public String toolType() { return toolType; @@ -161,6 +168,8 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i private int maxDamage = 0; + private int attackDamage = 0; + private String toolType = null; private String toolTier = null; @@ -248,6 +257,12 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i return this; } + @Override + public NonVanillaCustomItemData.Builder attackDamage(int attackDamage) { + this.attackDamage = attackDamage; + return this; + } + @Override public Builder toolType(@Nullable String toolType) { this.toolType = toolType; diff --git a/core/src/main/java/org/geysermc/geyser/item/Items.java b/core/src/main/java/org/geysermc/geyser/item/Items.java index e84315fd8..2147ebb2c 100644 --- a/core/src/main/java/org/geysermc/geyser/item/Items.java +++ b/core/src/main/java/org/geysermc/geyser/item/Items.java @@ -852,36 +852,36 @@ public final class Items { public static final Item GOLD_INGOT = register(new Item("gold_ingot", builder())); public static final Item NETHERITE_INGOT = register(new Item("netherite_ingot", builder())); public static final Item NETHERITE_SCRAP = register(new Item("netherite_scrap", builder())); - public static final Item WOODEN_SWORD = register(new TieredItem("wooden_sword", ToolTier.WOODEN, builder().stackSize(1).maxDamage(59))); - public static final Item WOODEN_SHOVEL = register(new TieredItem("wooden_shovel", ToolTier.WOODEN, builder().stackSize(1).maxDamage(59))); - public static final Item WOODEN_PICKAXE = register(new TieredItem("wooden_pickaxe", ToolTier.WOODEN, builder().stackSize(1).maxDamage(59))); - public static final Item WOODEN_AXE = register(new TieredItem("wooden_axe", ToolTier.WOODEN, builder().stackSize(1).maxDamage(59))); - public static final Item WOODEN_HOE = register(new TieredItem("wooden_hoe", ToolTier.WOODEN, builder().stackSize(1).maxDamage(59))); - public static final Item STONE_SWORD = register(new TieredItem("stone_sword", ToolTier.STONE, builder().stackSize(1).maxDamage(131))); - public static final Item STONE_SHOVEL = register(new TieredItem("stone_shovel", ToolTier.STONE, builder().stackSize(1).maxDamage(131))); - public static final Item STONE_PICKAXE = register(new TieredItem("stone_pickaxe", ToolTier.STONE, builder().stackSize(1).maxDamage(131))); - public static final Item STONE_AXE = register(new TieredItem("stone_axe", ToolTier.STONE, builder().stackSize(1).maxDamage(131))); - public static final Item STONE_HOE = register(new TieredItem("stone_hoe", ToolTier.STONE, builder().stackSize(1).maxDamage(131))); - public static final Item GOLDEN_SWORD = register(new TieredItem("golden_sword", ToolTier.GOLDEN, builder().stackSize(1).maxDamage(32))); - public static final Item GOLDEN_SHOVEL = register(new TieredItem("golden_shovel", ToolTier.GOLDEN, builder().stackSize(1).maxDamage(32))); - public static final Item GOLDEN_PICKAXE = register(new TieredItem("golden_pickaxe", ToolTier.GOLDEN, builder().stackSize(1).maxDamage(32))); - public static final Item GOLDEN_AXE = register(new TieredItem("golden_axe", ToolTier.GOLDEN, builder().stackSize(1).maxDamage(32))); - public static final Item GOLDEN_HOE = register(new TieredItem("golden_hoe", ToolTier.GOLDEN, builder().stackSize(1).maxDamage(32))); - public static final Item IRON_SWORD = register(new TieredItem("iron_sword", ToolTier.IRON, builder().stackSize(1).maxDamage(250))); - public static final Item IRON_SHOVEL = register(new TieredItem("iron_shovel", ToolTier.IRON, builder().stackSize(1).maxDamage(250))); - public static final Item IRON_PICKAXE = register(new TieredItem("iron_pickaxe", ToolTier.IRON, builder().stackSize(1).maxDamage(250))); - public static final Item IRON_AXE = register(new TieredItem("iron_axe", ToolTier.IRON, builder().stackSize(1).maxDamage(250))); - public static final Item IRON_HOE = register(new TieredItem("iron_hoe", ToolTier.IRON, builder().stackSize(1).maxDamage(250))); - public static final Item DIAMOND_SWORD = register(new TieredItem("diamond_sword", ToolTier.DIAMOND, builder().stackSize(1).maxDamage(1561))); - public static final Item DIAMOND_SHOVEL = register(new TieredItem("diamond_shovel", ToolTier.DIAMOND, builder().stackSize(1).maxDamage(1561))); - public static final Item DIAMOND_PICKAXE = register(new TieredItem("diamond_pickaxe", ToolTier.DIAMOND, builder().stackSize(1).maxDamage(1561))); - public static final Item DIAMOND_AXE = register(new TieredItem("diamond_axe", ToolTier.DIAMOND, builder().stackSize(1).maxDamage(1561))); - public static final Item DIAMOND_HOE = register(new TieredItem("diamond_hoe", ToolTier.DIAMOND, builder().stackSize(1).maxDamage(1561))); - public static final Item NETHERITE_SWORD = register(new TieredItem("netherite_sword", ToolTier.NETHERITE, builder().stackSize(1).maxDamage(2031))); - public static final Item NETHERITE_SHOVEL = register(new TieredItem("netherite_shovel", ToolTier.NETHERITE, builder().stackSize(1).maxDamage(2031))); - public static final Item NETHERITE_PICKAXE = register(new TieredItem("netherite_pickaxe", ToolTier.NETHERITE, builder().stackSize(1).maxDamage(2031))); - public static final Item NETHERITE_AXE = register(new TieredItem("netherite_axe", ToolTier.NETHERITE, builder().stackSize(1).maxDamage(2031))); - public static final Item NETHERITE_HOE = register(new TieredItem("netherite_hoe", ToolTier.NETHERITE, builder().stackSize(1).maxDamage(2031))); + public static final Item WOODEN_SWORD = register(new TieredItem("wooden_sword", ToolTier.WOODEN, builder().stackSize(1).attackDamage(4).maxDamage(59))); + public static final Item WOODEN_SHOVEL = register(new TieredItem("wooden_shovel", ToolTier.WOODEN, builder().stackSize(1).attackDamage(2.5).maxDamage(59))); + public static final Item WOODEN_PICKAXE = register(new TieredItem("wooden_pickaxe", ToolTier.WOODEN, builder().stackSize(1).attackDamage(2).maxDamage(59))); + public static final Item WOODEN_AXE = register(new TieredItem("wooden_axe", ToolTier.WOODEN, builder().stackSize(1).attackDamage(7).maxDamage(59))); + public static final Item WOODEN_HOE = register(new TieredItem("wooden_hoe", ToolTier.WOODEN, builder().stackSize(1).attackDamage(1).maxDamage(59))); + public static final Item STONE_SWORD = register(new TieredItem("stone_sword", ToolTier.STONE, builder().stackSize(1).attackDamage(5).maxDamage(131))); + public static final Item STONE_SHOVEL = register(new TieredItem("stone_shovel", ToolTier.STONE, builder().stackSize(1).attackDamage(3.5).maxDamage(131))); + public static final Item STONE_PICKAXE = register(new TieredItem("stone_pickaxe", ToolTier.STONE, builder().stackSize(1).attackDamage(3).maxDamage(131))); + public static final Item STONE_AXE = register(new TieredItem("stone_axe", ToolTier.STONE, builder().stackSize(1).attackDamage(9).maxDamage(131))); + public static final Item STONE_HOE = register(new TieredItem("stone_hoe", ToolTier.STONE, builder().stackSize(1).attackDamage(1).maxDamage(131))); + public static final Item GOLDEN_SWORD = register(new TieredItem("golden_sword", ToolTier.GOLDEN, builder().stackSize(1).attackDamage(4).maxDamage(32))); + public static final Item GOLDEN_SHOVEL = register(new TieredItem("golden_shovel", ToolTier.GOLDEN, builder().stackSize(1).attackDamage(2.5).maxDamage(32))); + public static final Item GOLDEN_PICKAXE = register(new TieredItem("golden_pickaxe", ToolTier.GOLDEN, builder().stackSize(1).attackDamage(2).maxDamage(32))); + public static final Item GOLDEN_AXE = register(new TieredItem("golden_axe", ToolTier.GOLDEN, builder().stackSize(1).attackDamage(7).maxDamage(32))); + public static final Item GOLDEN_HOE = register(new TieredItem("golden_hoe", ToolTier.GOLDEN, builder().stackSize(1).attackDamage(1).maxDamage(32))); + public static final Item IRON_SWORD = register(new TieredItem("iron_sword", ToolTier.IRON, builder().stackSize(1).attackDamage(6).maxDamage(250))); + public static final Item IRON_SHOVEL = register(new TieredItem("iron_shovel", ToolTier.IRON, builder().stackSize(1).attackDamage(4.5).maxDamage(250))); + public static final Item IRON_PICKAXE = register(new TieredItem("iron_pickaxe", ToolTier.IRON, builder().stackSize(1).attackDamage(4).maxDamage(250))); + public static final Item IRON_AXE = register(new TieredItem("iron_axe", ToolTier.IRON, builder().stackSize(1).attackDamage(9).maxDamage(250))); + public static final Item IRON_HOE = register(new TieredItem("iron_hoe", ToolTier.IRON, builder().stackSize(1).attackDamage(1).maxDamage(250))); + public static final Item DIAMOND_SWORD = register(new TieredItem("diamond_sword", ToolTier.DIAMOND, builder().stackSize(1).attackDamage(7).maxDamage(1561))); + public static final Item DIAMOND_SHOVEL = register(new TieredItem("diamond_shovel", ToolTier.DIAMOND, builder().stackSize(1).attackDamage(5.5).maxDamage(1561))); + public static final Item DIAMOND_PICKAXE = register(new TieredItem("diamond_pickaxe", ToolTier.DIAMOND, builder().stackSize(1).attackDamage(5).maxDamage(1561))); + public static final Item DIAMOND_AXE = register(new TieredItem("diamond_axe", ToolTier.DIAMOND, builder().stackSize(1).attackDamage(9).maxDamage(1561))); + public static final Item DIAMOND_HOE = register(new TieredItem("diamond_hoe", ToolTier.DIAMOND, builder().stackSize(1).attackDamage(1).maxDamage(1561))); + public static final Item NETHERITE_SWORD = register(new TieredItem("netherite_sword", ToolTier.NETHERITE, builder().stackSize(1).attackDamage(8).maxDamage(2031))); + public static final Item NETHERITE_SHOVEL = register(new TieredItem("netherite_shovel", ToolTier.NETHERITE, builder().stackSize(1).attackDamage(6.5).maxDamage(2031))); + public static final Item NETHERITE_PICKAXE = register(new TieredItem("netherite_pickaxe", ToolTier.NETHERITE, builder().stackSize(1).attackDamage(6).maxDamage(2031))); + public static final Item NETHERITE_AXE = register(new TieredItem("netherite_axe", ToolTier.NETHERITE, builder().stackSize(1).attackDamage(10).maxDamage(2031))); + public static final Item NETHERITE_HOE = register(new TieredItem("netherite_hoe", ToolTier.NETHERITE, builder().stackSize(1).attackDamage(1).maxDamage(2031))); public static final Item STICK = register(new Item("stick", builder())); public static final Item BOWL = register(new Item("bowl", builder())); public static final Item MUSHROOM_STEW = register(new Item("mushroom_stew", builder().stackSize(1))); @@ -1216,7 +1216,7 @@ public final class Items { public static final Item MUSIC_DISC_5 = register(new Item("music_disc_5", builder().stackSize(1))); public static final Item MUSIC_DISC_PIGSTEP = register(new Item("music_disc_pigstep", builder().stackSize(1))); public static final Item DISC_FRAGMENT_5 = register(new Item("disc_fragment_5", builder())); - public static final Item TRIDENT = register(new Item("trident", builder().stackSize(1).maxDamage(250))); + public static final Item TRIDENT = register(new Item("trident", builder().stackSize(1).attackDamage(9).maxDamage(250))); public static final Item PHANTOM_MEMBRANE = register(new Item("phantom_membrane", builder())); public static final Item NAUTILUS_SHELL = register(new Item("nautilus_shell", builder())); public static final Item HEART_OF_THE_SEA = register(new Item("heart_of_the_sea", builder())); diff --git a/core/src/main/java/org/geysermc/geyser/item/components/ToolTier.java b/core/src/main/java/org/geysermc/geyser/item/components/ToolTier.java index 8484eb185..a8832df1e 100644 --- a/core/src/main/java/org/geysermc/geyser/item/components/ToolTier.java +++ b/core/src/main/java/org/geysermc/geyser/item/components/ToolTier.java @@ -53,10 +53,6 @@ public enum ToolTier { this.repairIngredients = Suppliers.memoize(repairIngredients::get); } - public int getSpeed() { - return speed; - } - public Set getRepairIngredients() { return repairIngredients.get(); } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/Item.java b/core/src/main/java/org/geysermc/geyser/item/type/Item.java index 94bb3324e..3701b5189 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/Item.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/Item.java @@ -50,14 +50,14 @@ public class Item { private final String javaIdentifier; private int javaId = -1; private final int stackSize; - private final String toolType; + private final int attackDamage; private final int maxDamage; public Item(String javaIdentifier, Builder builder) { this.javaIdentifier = Identifier.formalize(javaIdentifier).intern(); this.stackSize = builder.stackSize; - this.toolType = builder.toolType; this.maxDamage = builder.maxDamage; + this.attackDamage = builder.attackDamage; } public String javaIdentifier() { @@ -72,6 +72,10 @@ public class Item { return maxDamage; } + public int attackDamage() { + return attackDamage; + } + public int maxStackSize() { return stackSize; } @@ -279,16 +283,17 @@ public class Item { public static final class Builder { private int stackSize = 64; - private String toolType; private int maxDamage; + private int attackDamage; public Builder stackSize(int stackSize) { this.stackSize = stackSize; return this; } - public Builder setToolType(String toolType) { - this.toolType = toolType; + public Builder attackDamage(double attackDamage) { + // TODO properly store/send a double value once Bedrock supports it.. pls + this.attackDamage = (int) attackDamage; return this; } 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 2e00bd4ad..baaa61204 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 @@ -153,7 +153,7 @@ public class CustomItemRegistryPopulator { .build(); NbtMapBuilder builder = createComponentNbt(customItemData, customItemData.identifier(), customItemId, - customItemData.creativeCategory(), customItemData.creativeGroup(), customItemData.isHat(), customItemData.displayHandheld(), protocolVersion); + customItemData.isHat(), customItemData.displayHandheld(), protocolVersion); ComponentItemData componentItemData = new ComponentItemData(customIdentifier, builder.build()); return new NonVanillaItemRegistration(componentItemData, item, customItemMapping); @@ -172,7 +172,7 @@ public class CustomItemRegistryPopulator { boolean canDestroyInCreative = true; if (mapping.getToolType() != null) { // This is not using the isTool boolean because it is not just a render type here. - canDestroyInCreative = computeToolProperties(mapping.getToolType(), itemProperties, componentBuilder); + canDestroyInCreative = computeToolProperties(mapping.getToolType(), itemProperties, componentBuilder, javaItem.attackDamage()); } itemProperties.putBoolean("can_destroy_in_creative", canDestroyInCreative); @@ -208,10 +208,8 @@ public class CustomItemRegistryPopulator { return builder; } - @SuppressWarnings("OptionalUsedAsFieldOrParameterType") private static NbtMapBuilder createComponentNbt(NonVanillaCustomItemData customItemData, String customItemName, - int customItemId, OptionalInt creativeCategory, - String creativeGroup, boolean isHat, boolean displayHandheld, int protocolVersion) { + int customItemId, boolean isHat, boolean displayHandheld, int protocolVersion) { NbtMapBuilder builder = NbtMap.builder(); builder.putString("name", customItemName) .putInt("id", customItemId); @@ -223,7 +221,7 @@ public class CustomItemRegistryPopulator { boolean canDestroyInCreative = true; if (customItemData.toolType() != null) { // This is not using the isTool boolean because it is not just a render type here. - canDestroyInCreative = computeToolProperties(Objects.requireNonNull(customItemData.toolType()), itemProperties, componentBuilder); + canDestroyInCreative = computeToolProperties(Objects.requireNonNull(customItemData.toolType()), itemProperties, componentBuilder, customItemData.attackDamage()); } itemProperties.putBoolean("can_destroy_in_creative", canDestroyInCreative); @@ -311,7 +309,7 @@ public class CustomItemRegistryPopulator { /** * @return can destroy in creative */ - private static boolean computeToolProperties(String toolType, NbtMapBuilder itemProperties, NbtMapBuilder componentBuilder) { + private static boolean computeToolProperties(String toolType, NbtMapBuilder itemProperties, NbtMapBuilder componentBuilder, int attackDamage) { boolean canDestroyInCreative = true; float miningSpeed = 1.0f; @@ -362,6 +360,11 @@ public class CustomItemRegistryPopulator { itemProperties.putInt("enchantable_value", 1); itemProperties.putString("enchantable_slot", toolType); + // Adds a "attack damage" indicator. Purely visual! + if (attackDamage > 0) { + itemProperties.putInt("damage", attackDamage); + } + return canDestroyInCreative; } From 867cf6da05c56ea5ead21533a6bfdebc601e60bf Mon Sep 17 00:00:00 2001 From: chris Date: Tue, 19 Mar 2024 23:05:30 +0100 Subject: [PATCH 212/344] Feature: JiJ dependencies on modded platforms (#4502) * Use JiJ inclusion for Fabric/NeoForge to prevent mod conflicts. Further: Don't publish shadow jars to maven. * Shade and relocate dependencies that don't conform to SemVer on Fabric * Shade/Relocate dependencies on Fabric to avoid version warnings * Use relocate function from the build-logic plugin --- bootstrap/bungeecord/build.gradle.kts | 2 +- bootstrap/mod/fabric/build.gradle.kts | 41 +++++++++-- bootstrap/mod/neoforge/build.gradle.kts | 19 +++-- bootstrap/spigot/build.gradle.kts | 17 ++--- bootstrap/velocity/build.gradle.kts | 2 + bootstrap/viaproxy/build.gradle.kts | 2 + build-logic/src/main/kotlin/extensions.kt | 15 ++-- .../geyser.modded-conventions.gradle.kts | 72 +++++++++++++------ .../geyser.publish-conventions.gradle.kts | 6 ++ .../geyser.shadow-conventions.gradle.kts | 1 - 10 files changed, 117 insertions(+), 60 deletions(-) diff --git a/bootstrap/bungeecord/build.gradle.kts b/bootstrap/bungeecord/build.gradle.kts index 4025569dd..1b57ffa5a 100644 --- a/bootstrap/bungeecord/build.gradle.kts +++ b/bootstrap/bungeecord/build.gradle.kts @@ -1,7 +1,7 @@ dependencies { api(projects.core) - implementation(libs.adventure.text.serializer.bungeecord) + compileOnlyApi(libs.bungeecord.proxy) } platformRelocate("net.md_5.bungee.jni") diff --git a/bootstrap/mod/fabric/build.gradle.kts b/bootstrap/mod/fabric/build.gradle.kts index dac042ad7..eb28e0e93 100644 --- a/bootstrap/mod/fabric/build.gradle.kts +++ b/bootstrap/mod/fabric/build.gradle.kts @@ -7,6 +7,8 @@ architectury { fabric() } +val includeTransitive: Configuration = configurations.getByName("includeTransitive") + dependencies { modImplementation(libs.fabric.loader) modApi(libs.fabric.api) @@ -15,14 +17,29 @@ dependencies { shadow(project(path = ":mod", configuration = "transformProductionFabric")) { isTransitive = false } - shadow(projects.core) { - exclude(group = "com.google.guava", module = "guava") - exclude(group = "com.google.code.gson", module = "gson") - exclude(group = "org.slf4j") - exclude(group = "com.nukkitx.fastutil") - exclude(group = "io.netty.incubator") - } + shadow(projects.core) { isTransitive = false } + includeTransitive(projects.core) + // These are NOT transitively included, and instead shadowed + relocated. + // Avoids fabric complaining about non-SemVer versioning + // TODO: re-evaluate after loom 1.6 (https://github.com/FabricMC/fabric-loom/pull/1075) + shadow(libs.protocol.connection) { isTransitive = false } + shadow(libs.protocol.common) { isTransitive = false } + shadow(libs.protocol.codec) { isTransitive = false } + shadow(libs.mcauthlib) { isTransitive = false } + shadow(libs.raknet) { isTransitive = false } + shadow(libs.netty.codec.haproxy) { isTransitive = false } + shadow("org.cloudburstmc:nbt:3.0.2.Final") { isTransitive = false } + shadow("io.netty:netty-codec-dns:4.1.103.Final") { isTransitive = false } + shadow("io.netty:netty-resolver-dns-classes-macos:4.1.103.Final") { isTransitive = false } + + // Consequences of shading + relocating mcauthlib: shadow/relocate mcpl! + shadow(libs.mcprotocollib) { isTransitive = false } + + // Since we also relocate cloudburst protocol: shade erosion common + shadow(libs.erosion.common) { isTransitive = false } + + // Permissions modImplementation(libs.fabric.permissions) include(libs.fabric.permissions) } @@ -31,6 +48,16 @@ application { mainClass.set("org.geysermc.geyser.platform.fabric.GeyserFabricMain") } +relocate("org.cloudburstmc.nbt") +relocate("org.cloudburstmc.netty") +relocate("org.cloudburstmc.protocol") +relocate("io.netty.handler.codec.dns") +relocate("io.netty.handler.codec.haproxy") +relocate("io.netty.resolver.dns.macos") +relocate("com.github.steveice10.mc.protocol") +relocate("com.github.steveice10.mc.auth") +relocate("com.github.steveice10.packetlib") + tasks { remapJar { archiveBaseName.set("Geyser-Fabric") diff --git a/bootstrap/mod/neoforge/build.gradle.kts b/bootstrap/mod/neoforge/build.gradle.kts index d85087542..2a414e6dd 100644 --- a/bootstrap/mod/neoforge/build.gradle.kts +++ b/bootstrap/mod/neoforge/build.gradle.kts @@ -2,11 +2,17 @@ plugins { application } +// This is provided by "org.cloudburstmc.math.mutable" too, so yeet. +// NeoForge's class loader is *really* annoying. +provided("org.cloudburstmc.math", "api") + architectury { platformSetupLoomIde() neoForge() } +val includeTransitive: Configuration = configurations.getByName("includeTransitive") + dependencies { // See https://github.com/google/guava/issues/6618 modules { @@ -21,12 +27,9 @@ dependencies { shadow(project(path = ":mod", configuration = "transformProductionNeoForge")) { isTransitive = false } - shadow(projects.core) { - exclude(group = "com.google.guava", module = "guava") - exclude(group = "com.google.code.gson", module = "gson") - exclude(group = "org.slf4j") - exclude(group = "io.netty.incubator") - } + shadow(project(path = ":core")) { isTransitive = false } + + includeTransitive(projects.core) } application { @@ -34,10 +37,6 @@ application { } tasks { - shadowJar { - relocate("it.unimi.dsi.fastutil", "org.geysermc.relocate.fastutil") - } - remapJar { archiveBaseName.set("Geyser-NeoForge") } diff --git a/bootstrap/spigot/build.gradle.kts b/bootstrap/spigot/build.gradle.kts index 129064cd4..41da1a0de 100644 --- a/bootstrap/spigot/build.gradle.kts +++ b/bootstrap/spigot/build.gradle.kts @@ -11,18 +11,11 @@ dependencies { implementation(libs.commodore) implementation(libs.adventure.text.serializer.bungeecord) - - // Both folia-api and paper-mojangapi only provide Java 17 versions for 1.19 - compileOnly(libs.folia.api) { - attributes { - attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17) - } - } - compileOnly(libs.paper.mojangapi) { - attributes { - attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17) - } - } + + compileOnly(libs.folia.api) + compileOnly(libs.paper.mojangapi) + + compileOnlyApi(libs.viaversion) } platformRelocate("it.unimi.dsi.fastutil") diff --git a/bootstrap/velocity/build.gradle.kts b/bootstrap/velocity/build.gradle.kts index 8908b2afd..a21fb2349 100644 --- a/bootstrap/velocity/build.gradle.kts +++ b/bootstrap/velocity/build.gradle.kts @@ -1,6 +1,8 @@ dependencies { annotationProcessor(libs.velocity.api) api(projects.core) + + compileOnlyApi(libs.velocity.api) } platformRelocate("com.fasterxml.jackson") diff --git a/bootstrap/viaproxy/build.gradle.kts b/bootstrap/viaproxy/build.gradle.kts index 4d5d4f949..01c5b5b34 100644 --- a/bootstrap/viaproxy/build.gradle.kts +++ b/bootstrap/viaproxy/build.gradle.kts @@ -1,5 +1,7 @@ dependencies { api(projects.core) + + compileOnlyApi(libs.viaproxy) } platformRelocate("net.kyori") diff --git a/build-logic/src/main/kotlin/extensions.kt b/build-logic/src/main/kotlin/extensions.kt index b4a14f678..41e11344b 100644 --- a/build-logic/src/main/kotlin/extensions.kt +++ b/build-logic/src/main/kotlin/extensions.kt @@ -58,19 +58,20 @@ fun Project.platformRelocate(pattern: String, exclusion: String = "") { val providedDependencies = mutableMapOf>() -fun Project.provided(pattern: String, name: String, version: String, excludedOn: Int = 0b110) { +fun getProvidedDependenciesForProject(projectName: String): MutableSet { + return providedDependencies.getOrDefault(projectName, emptySet()).toMutableSet() +} + +fun Project.provided(pattern: String, name: String, excludedOn: Int = 0b110) { providedDependencies.getOrPut(project.name) { mutableSetOf() } - .add("${calcExclusion(pattern, 0b100, excludedOn)}:" + - "${calcExclusion(name, 0b10, excludedOn)}:" + - calcExclusion(version, 0b1, excludedOn)) - dependencies.add("compileOnlyApi", "$pattern:$name:$version") + .add("${calcExclusion(pattern, 0b100, excludedOn)}:${calcExclusion(name, 0b10, excludedOn)}") } fun Project.provided(dependency: ProjectDependency) = - provided(dependency.group!!, dependency.name, dependency.version!!) + provided(dependency.group!!, dependency.name) fun Project.provided(dependency: MinimalExternalModuleDependency) = - provided(dependency.module.group, dependency.module.name, dependency.versionConstraint.requiredVersion) + provided(dependency.module.group, dependency.module.name) fun Project.provided(provider: Provider) = provided(provider.get()) diff --git a/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts b/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts index 0842eae84..91bde525e 100644 --- a/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts @@ -11,6 +11,31 @@ plugins { id("com.modrinth.minotaur") } +// These are provided by Minecraft/modded platforms already, no need to include them +provided("com.google.code.gson", "gson") +provided("com.google.guava", ".*") +provided("org.slf4j", "slf4j-api") +provided("com.nukkitx.fastutil", ".*") +provided("org.cloudburstmc.fastutil.maps", ".*") +provided("org.cloudburstmc.fastutil.sets", ".*") +provided("org.cloudburstmc.fastutil.commons", ".*") +provided("org.cloudburstmc.fastutil", ".*") +provided("org.checkerframework", "checker-qual") +provided("io.netty", "netty-transport-classes-epoll") +provided("io.netty", "netty-transport-native-epoll") +provided("io.netty", "netty-transport-native-unix-common") +provided("io.netty", "netty-transport-classes-kqueue") +provided("io.netty", "netty-transport-native-kqueue") +provided("io.netty", "netty-handler") +provided("io.netty", "netty-common") +provided("io.netty", "netty-buffer") +provided("io.netty", "netty-resolver") +provided("io.netty", "netty-transport") +provided("io.netty", "netty-codec") +provided("io.netty", "netty-resolver-dns") +provided("io.netty", "netty-resolver-dns-native-macos") +provided("org.ow2.asm", "asm") + architectury { minecraft = "1.20.4" } @@ -19,6 +44,10 @@ loom { silentMojangMappingsLicense() } +configurations { + create("includeTransitive").isTransitive = true +} + tasks { // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task // if it is present. @@ -34,28 +63,6 @@ tasks { // The remapped shadowJar is the final desired mod jar archiveVersion.set(project.version.toString()) archiveClassifier.set("shaded") - - relocate("org.objectweb.asm", "org.geysermc.relocate.asm") - relocate("org.yaml", "org.geysermc.relocate.yaml") // https://github.com/CardboardPowered/cardboard/issues/139 - relocate("com.fasterxml.jackson", "org.geysermc.relocate.jackson") - relocate("net.kyori", "org.geysermc.relocate.kyori") - - dependencies { - // Exclude everything EXCEPT some DNS stuff required for HAProxy - exclude(dependency("io.netty:netty-transport-classes-epoll:.*")) - exclude(dependency("io.netty:netty-transport-native-epoll:.*")) - exclude(dependency("io.netty:netty-transport-native-unix-common:.*")) - exclude(dependency("io.netty:netty-transport-classes-kqueue:.*")) - exclude(dependency("io.netty:netty-transport-native-kqueue:.*")) - exclude(dependency("io.netty:netty-handler:.*")) - exclude(dependency("io.netty:netty-common:.*")) - exclude(dependency("io.netty:netty-buffer:.*")) - exclude(dependency("io.netty:netty-resolver:.*")) - exclude(dependency("io.netty:netty-transport:.*")) - exclude(dependency("io.netty:netty-codec:.*")) - exclude(dependency("io.netty:netty-resolver-dns:.*")) - exclude(dependency("io.netty:netty-resolver-dns-native-macos:.*")) - } } remapJar { @@ -73,6 +80,27 @@ tasks { } } +afterEvaluate { + val providedDependencies = getProvidedDependenciesForProject(project.name) + + // These are shaded, no need to JiJ them + configurations["shadow"].dependencies.forEach {shadowed -> + println("Not including shadowed dependency: ${shadowed.group}:${shadowed.name}") + providedDependencies.add("${shadowed.group}:${shadowed.name}") + } + + // Now: Include all transitive dependencies that aren't excluded + configurations["includeTransitive"].resolvedConfiguration.resolvedArtifacts.forEach { dep -> + if (!providedDependencies.contains("${dep.moduleVersion.id.group}:${dep.moduleVersion.id.name}") + and !providedDependencies.contains("${dep.moduleVersion.id.group}:.*")) { + println("Including dependency via JiJ: ${dep.id}") + dependencies.add("include", dep.moduleVersion.id.toString()) + } else { + println("Not including ${dep.id} for ${project.name}!") + } + } +} + dependencies { minecraft("com.mojang:minecraft:1.20.4") mappings(loom.officialMojangMappings()) diff --git a/build-logic/src/main/kotlin/geyser.publish-conventions.gradle.kts b/build-logic/src/main/kotlin/geyser.publish-conventions.gradle.kts index 036ee803c..eca587721 100644 --- a/build-logic/src/main/kotlin/geyser.publish-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.publish-conventions.gradle.kts @@ -7,3 +7,9 @@ indra { publishSnapshotsTo("geysermc", "https://repo.opencollab.dev/maven-snapshots") publishReleasesTo("geysermc", "https://repo.opencollab.dev/maven-releases") } + +publishing { + // skip shadow jar from publishing. Workaround for https://github.com/johnrengelman/shadow/issues/651 + val javaComponent = project.components["java"] as AdhocComponentWithVariants + javaComponent.withVariantsFromConfiguration(configurations["shadowRuntimeElements"]) { skip() } +} \ No newline at end of file diff --git a/build-logic/src/main/kotlin/geyser.shadow-conventions.gradle.kts b/build-logic/src/main/kotlin/geyser.shadow-conventions.gradle.kts index dde85c33a..c160e5ec6 100644 --- a/build-logic/src/main/kotlin/geyser.shadow-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.shadow-conventions.gradle.kts @@ -7,7 +7,6 @@ plugins { tasks { named("jar") { - archiveClassifier.set("unshaded") from(project.rootProject.file("LICENSE")) } val shadowJar = named("shadowJar") { From 4fa0bcd01b9ca897bf33f4e6d2187997caadb22b Mon Sep 17 00:00:00 2001 From: chris Date: Thu, 21 Mar 2024 19:05:41 +0100 Subject: [PATCH 213/344] Update Jackson (#4512) * Update jackson * relocate yaml on velocity --- bootstrap/velocity/build.gradle.kts | 1 + .../geysermc/geyser/extension/GeyserExtensionDescription.java | 3 ++- gradle/libs.versions.toml | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/bootstrap/velocity/build.gradle.kts b/bootstrap/velocity/build.gradle.kts index a21fb2349..97e9d1f57 100644 --- a/bootstrap/velocity/build.gradle.kts +++ b/bootstrap/velocity/build.gradle.kts @@ -8,6 +8,7 @@ dependencies { platformRelocate("com.fasterxml.jackson") platformRelocate("it.unimi.dsi.fastutil") platformRelocate("net.kyori.adventure.text.serializer.gson.legacyimpl") +platformRelocate("org.yaml") exclude("com.google.*:*") diff --git a/core/src/main/java/org/geysermc/geyser/extension/GeyserExtensionDescription.java b/core/src/main/java/org/geysermc/geyser/extension/GeyserExtensionDescription.java index 716b763f5..239ffc450 100644 --- a/core/src/main/java/org/geysermc/geyser/extension/GeyserExtensionDescription.java +++ b/core/src/main/java/org/geysermc/geyser/extension/GeyserExtensionDescription.java @@ -31,6 +31,7 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.api.extension.ExtensionDescription; import org.geysermc.geyser.api.extension.exception.InvalidDescriptionException; import org.geysermc.geyser.text.GeyserLocale; +import org.yaml.snakeyaml.LoaderOptions; import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.constructor.CustomClassLoaderConstructor; @@ -48,7 +49,7 @@ public record GeyserExtensionDescription(@NonNull String id, @NonNull String version, @NonNull List authors) implements ExtensionDescription { - private static final Yaml YAML = new Yaml(new CustomClassLoaderConstructor(Source.class.getClassLoader())); + private static final Yaml YAML = new Yaml(new CustomClassLoaderConstructor(Source.class.getClassLoader(), new LoaderOptions())); public static final Pattern ID_PATTERN = Pattern.compile("[a-z][a-z0-9-_]{0,63}"); public static final Pattern NAME_PATTERN = Pattern.compile("^[A-Za-z_.-]+$"); diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 73417f23a..377172346 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,7 +3,7 @@ base-api = "1.0.0-SNAPSHOT" cumulus = "1.1.2" erosion = "1.0-20230406.174837-8" events = "1.1-SNAPSHOT" -jackson = { strictly = "2.14.0" } # Don't let other dependencies override +jackson = "2.17.0" fastutil = "8.5.2" netty = "4.1.107.Final" guava = "29.0-jre" @@ -38,7 +38,7 @@ mixin = "0.8.5" # plugin versions indra = "3.1.3" -shadow = "7.1.3-SNAPSHOT" +shadow = "8.1.1" architectury-plugin = "3.4-SNAPSHOT" architectury-loom = "1.4-SNAPSHOT" minotaur = "2.8.7" From c64e8afccebebd8cf23f0c3562dba7bd1350b2c5 Mon Sep 17 00:00:00 2001 From: CloudyOrk <120650272+CloudyOrk@users.noreply.github.com> Date: Sat, 23 Mar 2024 00:33:17 +0530 Subject: [PATCH 214/344] Indicate existing 1.20.72 support (#4515) * update supported version * Update GameProtocol.java * Update GameProtocol.java --------- Co-authored-by: Kas-tle <26531652+Kas-tle@users.noreply.github.com> --- README.md | 2 +- .../src/main/java/org/geysermc/geyser/network/GameProtocol.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 76a62a462..8a28e7177 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,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.20.40 - 1.20.71 and Minecraft Java 1.20.4 +### Currently supporting Minecraft Bedrock 1.20.40 - 1.20.72 and Minecraft Java 1.20.4 ## 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/GameProtocol.java b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java index 80d2038d9..900463c5c 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java @@ -72,7 +72,7 @@ public final class GameProtocol { .minecraftVersion("1.20.60/1.20.62") .build()); SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC.toBuilder() - .minecraftVersion("1.20.70/1.20.71") + .minecraftVersion("1.20.70/1.20.72") .build()); } From d24a4766b4e332f5964165f66f57ae7d0f7d0f83 Mon Sep 17 00:00:00 2001 From: chris Date: Sun, 24 Mar 2024 17:12:40 +0100 Subject: [PATCH 215/344] Shade the Geyser api on modded platforms (#4520) --- bootstrap/mod/fabric/build.gradle.kts | 3 +++ bootstrap/mod/neoforge/build.gradle.kts | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/bootstrap/mod/fabric/build.gradle.kts b/bootstrap/mod/fabric/build.gradle.kts index eb28e0e93..538147b15 100644 --- a/bootstrap/mod/fabric/build.gradle.kts +++ b/bootstrap/mod/fabric/build.gradle.kts @@ -39,6 +39,9 @@ dependencies { // Since we also relocate cloudburst protocol: shade erosion common shadow(libs.erosion.common) { isTransitive = false } + // Let's shade in our own api + shadow(projects.api) { isTransitive = false } + // Permissions modImplementation(libs.fabric.permissions) include(libs.fabric.permissions) diff --git a/bootstrap/mod/neoforge/build.gradle.kts b/bootstrap/mod/neoforge/build.gradle.kts index 2a414e6dd..f7204332b 100644 --- a/bootstrap/mod/neoforge/build.gradle.kts +++ b/bootstrap/mod/neoforge/build.gradle.kts @@ -27,8 +27,12 @@ dependencies { shadow(project(path = ":mod", configuration = "transformProductionNeoForge")) { isTransitive = false } - shadow(project(path = ":core")) { isTransitive = false } + shadow(projects.core) { isTransitive = false } + // Let's shade in our own api + shadow(projects.api) { isTransitive = false } + + // Include all transitive deps of core via JiJ includeTransitive(projects.core) } From 4ea94f89a2a54775330fdca3096cbad6d89255d3 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Sun, 24 Mar 2024 21:30:00 +0000 Subject: [PATCH 216/344] Fix entity pick request for cherry and bamboo boats (#4522) --- .../bedrock/BedrockEntityPickRequestTranslator.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockEntityPickRequestTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockEntityPickRequestTranslator.java index f64ddeac6..e85456c33 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockEntityPickRequestTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockEntityPickRequestTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2024 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 @@ -62,13 +62,17 @@ public class BedrockEntityPickRequestTranslator extends PacketTranslator "birch"; case 3 -> "jungle"; case 4 -> "acacia"; - //case 5 -> "cherry"; TODO + case 5 -> "cherry"; case 6 -> "dark_oak"; case 7 -> "mangrove"; - //case 8 -> "bamboo"; + case 8 -> "bamboo"; default -> "oak"; }; itemName = typeOfBoat + "_" + entity.getDefinition().entityType().name().toLowerCase(Locale.ROOT); + // Bamboo boat is a raft + if (variant == 8) { + itemName = itemName.replace("boat", "raft"); + } } case LEASH_KNOT -> itemName = "lead"; case CHEST_MINECART, COMMAND_BLOCK_MINECART, FURNACE_MINECART, HOPPER_MINECART, TNT_MINECART -> From 85908690a340120f3cafe45eb2d286b15a1f83c2 Mon Sep 17 00:00:00 2001 From: chris Date: Wed, 27 Mar 2024 01:47:21 +0100 Subject: [PATCH 217/344] Revert inventory "fix" that's causing issues with quickly opening & closing inventories (#4523) --- .../bedrock/entity/player/BedrockInteractTranslator.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockInteractTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockInteractTranslator.java index 07e192bb7..a45690ab1 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockInteractTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockInteractTranslator.java @@ -126,12 +126,7 @@ public class BedrockInteractTranslator extends PacketTranslator } else { InventoryUtils.openInventory(session, session.getPlayerInventory()); } - } else { - // Case: Player tries to open a player inventory, while we think it should be in a different inventory - // Now: Open the inventory that we're supposed to be in. - InventoryUtils.openInventory(session, session.getOpenInventory()); } - break; } } } From f1828419d631c43ef27b06d62a646229d2482236 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Thu, 28 Mar 2024 17:28:49 -0700 Subject: [PATCH 218/344] Update raknet (#4528) --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 377172346..b34f37d76 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ gson = "2.3.1" # Provided by Spigot 1.8.8 websocket = "1.5.1" protocol = "3.0.0.Beta1-20240313.120922-126" protocol-connection = "3.0.0.Beta1-20240313.120922-125" -raknet = "1.0.0.CR1-20231206.145325-12" +raknet = "1.0.0.CR1-20240328.213920-13" blockstateupdater="1.20.70-20240303.125052-2" mcauthlib = "d9d773e" mcprotocollib = "1.20.4-2-20240116.220521-7" From 7da3afef603dad61b3504ab5486bf577c0d7d336 Mon Sep 17 00:00:00 2001 From: Redned Date: Fri, 29 Mar 2024 12:25:57 +0000 Subject: [PATCH 219/344] Update RakNet --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b34f37d76..35ba90597 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ gson = "2.3.1" # Provided by Spigot 1.8.8 websocket = "1.5.1" protocol = "3.0.0.Beta1-20240313.120922-126" protocol-connection = "3.0.0.Beta1-20240313.120922-125" -raknet = "1.0.0.CR1-20240328.213920-13" +raknet = "1.0.0.CR1-20240329.101527-14" blockstateupdater="1.20.70-20240303.125052-2" mcauthlib = "d9d773e" mcprotocollib = "1.20.4-2-20240116.220521-7" From b469904951bfa38ad5e950d58bb3e0dcbe2b9d73 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Sat, 30 Mar 2024 03:27:55 -0700 Subject: [PATCH 220/344] Update Raknet (#4529) --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 35ba90597..0e446a48f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ gson = "2.3.1" # Provided by Spigot 1.8.8 websocket = "1.5.1" protocol = "3.0.0.Beta1-20240313.120922-126" protocol-connection = "3.0.0.Beta1-20240313.120922-125" -raknet = "1.0.0.CR1-20240329.101527-14" +raknet = "1.0.0.CR1-20240330.101522-15" blockstateupdater="1.20.70-20240303.125052-2" mcauthlib = "d9d773e" mcprotocollib = "1.20.4-2-20240116.220521-7" From fbafdbb2a708971917cb51e0d088e247370d601f Mon Sep 17 00:00:00 2001 From: rtm516 Date: Sun, 31 Mar 2024 12:01:59 +0100 Subject: [PATCH 221/344] Allow NonVanillaCustomItemData to have a block assigned (#4530) --- .../item/custom/NonVanillaCustomItemData.java | 11 ++++++++++- .../item/GeyserNonVanillaCustomItemData.java | 16 +++++++++++++++- .../populator/CustomItemRegistryPopulator.java | 7 ++++++- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/api/src/main/java/org/geysermc/geyser/api/item/custom/NonVanillaCustomItemData.java b/api/src/main/java/org/geysermc/geyser/api/item/custom/NonVanillaCustomItemData.java index 59e2faad8..2c283780c 100644 --- a/api/src/main/java/org/geysermc/geyser/api/item/custom/NonVanillaCustomItemData.java +++ b/api/src/main/java/org/geysermc/geyser/api/item/custom/NonVanillaCustomItemData.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2024 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 @@ -161,6 +161,13 @@ public interface NonVanillaCustomItemData extends CustomItemData { return displayHandheld(); } + /** + * Gets the block the item places. + * + * @return the block the item places + */ + String block(); + static NonVanillaCustomItemData.Builder builder() { return GeyserApi.api().provider(NonVanillaCustomItemData.Builder.class); } @@ -201,6 +208,8 @@ public interface NonVanillaCustomItemData extends CustomItemData { Builder chargeable(boolean isChargeable); + Builder block(String block); + /** * @deprecated Use {@link #displayHandheld(boolean)} instead. */ diff --git a/core/src/main/java/org/geysermc/geyser/item/GeyserNonVanillaCustomItemData.java b/core/src/main/java/org/geysermc/geyser/item/GeyserNonVanillaCustomItemData.java index 9d86bfa96..9c9269df3 100644 --- a/core/src/main/java/org/geysermc/geyser/item/GeyserNonVanillaCustomItemData.java +++ b/core/src/main/java/org/geysermc/geyser/item/GeyserNonVanillaCustomItemData.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2024 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 @@ -55,6 +55,7 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i private final boolean isEdible; private final boolean canAlwaysEat; private final boolean isChargeable; + private final String block; public GeyserNonVanillaCustomItemData(Builder builder) { super(builder.name, builder.customItemOptions, builder.displayName, builder.icon, builder.allowOffhand, @@ -78,6 +79,7 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i this.isEdible = builder.edible; this.canAlwaysEat = builder.canAlwaysEat; this.isChargeable = builder.chargeable; + this.block = builder.block; } @Override @@ -160,6 +162,11 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i return isChargeable; } + @Override + public String block() { + return block; + } + public static class Builder extends GeyserCustomItemData.Builder implements NonVanillaCustomItemData.Builder { private String identifier = null; private int javaId = -1; @@ -186,6 +193,7 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i private boolean edible = false; private boolean canAlwaysEat = false; private boolean chargeable = false; + private String block = null; @Override public Builder name(@NonNull String name) { @@ -339,6 +347,12 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i return this; } + @Override + public Builder block(String block) { + this.block = block; + return this; + } + @Override public NonVanillaCustomItemData build() { if (identifier == null || javaId == -1) { 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 baaa61204..10d87a8a9 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2024 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 @@ -248,6 +248,11 @@ public class CustomItemRegistryPopulator { itemProperties.putBoolean("foil", true); } + String block = customItemData.block(); + if (block != null) { + computeBlockItemProperties(block, componentBuilder); + } + componentBuilder.putCompound("item_properties", itemProperties.build()); builder.putCompound("components", componentBuilder.build()); From c9ca4c82f73f6ac0d8d5028753f73e4d7db3cdba Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Sun, 31 Mar 2024 21:42:31 -0700 Subject: [PATCH 222/344] Allow configuration of RakNet limits (#4532) * Allow configuration of RakNet limits Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Validate packet limiter system properties Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --------- Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .../GeyserJacksonConfiguration.java | 15 ++++- .../geyser/network/netty/GeyserServer.java | 55 ++++++++++++++++++- .../org/geysermc/geyser/util/FileUtils.java | 3 + .../org/geysermc/geyser/util/WebUtils.java | 30 ++++++++++ core/src/main/resources/config.yml | 4 +- gradle/libs.versions.toml | 2 +- 6 files changed, 102 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java b/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java index b3b7e8cd4..a55e4af8f 100644 --- a/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java +++ b/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java @@ -40,9 +40,11 @@ import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.network.CIDRMatcher; import org.geysermc.geyser.text.AsteriskSerializer; import org.geysermc.geyser.text.GeyserLocale; +import org.geysermc.geyser.util.WebUtils; import java.io.IOException; import java.nio.file.Path; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.UUID; @@ -233,7 +235,18 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration List matchers = this.whitelistedIPsMatchers; if (matchers == null) { synchronized (this) { - this.whitelistedIPsMatchers = matchers = proxyProtocolWhitelistedIPs.stream() + // Check if proxyProtocolWhitelistedIPs contains URLs we need to fetch and parse by line + List whitelistedCIDRs = new ArrayList<>(); + for (String ip: proxyProtocolWhitelistedIPs) { + if (!ip.startsWith("http")) { + whitelistedCIDRs.add(ip); + continue; + } + + WebUtils.getLineStream(ip).forEach(whitelistedCIDRs::add); + } + + this.whitelistedIPsMatchers = matchers = whitelistedCIDRs.stream() .map(CIDRMatcher::new) .collect(Collectors.toList()); } diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java b/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java index ea1dcb509..ce904d465 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java @@ -46,6 +46,7 @@ import net.jodah.expiringmap.ExpiringMap; import org.cloudburstmc.netty.channel.raknet.RakChannelFactory; import org.cloudburstmc.netty.channel.raknet.config.RakChannelOption; import org.cloudburstmc.netty.handler.codec.raknet.server.RakServerOfflineHandler; +import org.cloudburstmc.netty.handler.codec.raknet.server.RakServerRateLimiter; import org.cloudburstmc.protocol.bedrock.BedrockPong; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.command.defaults.ConnectionTestCommand; @@ -71,6 +72,10 @@ import java.util.concurrent.TimeUnit; import java.util.function.IntFunction; import java.util.function.Supplier; +import static org.cloudburstmc.netty.channel.raknet.RakConstants.DEFAULT_GLOBAL_PACKET_LIMIT; +import static org.cloudburstmc.netty.channel.raknet.RakConstants.DEFAULT_OFFLINE_PACKET_LIMIT; +import static org.cloudburstmc.netty.channel.raknet.RakConstants.DEFAULT_PACKET_LIMIT; + public final class GeyserServer { private static final boolean PRINT_DEBUG_PINGS = Boolean.parseBoolean(System.getProperty("Geyser.PrintPingsInDebugMode", "true")); @@ -141,23 +146,31 @@ public final class GeyserServer { bootstrapFutures = new ChannelFuture[listenCount]; for (int i = 0; i < listenCount; i++) { ChannelFuture future = bootstrap.bind(address); - addHandlers(future); + modifyHandlers(future); bootstrapFutures[i] = future; } return Bootstraps.allOf(bootstrapFutures); } - private void addHandlers(ChannelFuture future) { + private void modifyHandlers(ChannelFuture future) { Channel channel = future.channel(); // Add our ping handler channel.pipeline() .addFirst(RakConnectionRequestHandler.NAME, new RakConnectionRequestHandler(this)) .addAfter(RakServerOfflineHandler.NAME, RakPingHandler.NAME, new RakPingHandler(this)); + // Add proxy handler - if (this.geyser.getConfig().getBedrock().isEnableProxyProtocol()) { + boolean isProxyProtocol = this.geyser.getConfig().getBedrock().isEnableProxyProtocol(); + if (isProxyProtocol) { channel.pipeline().addFirst("proxy-protocol-decoder", new ProxyServerHandler()); } + + boolean isWhitelistedProxyProtocol = isProxyProtocol && !this.geyser.getConfig().getBedrock().getProxyProtocolWhitelistedIPs().isEmpty(); + if (Boolean.parseBoolean(System.getProperty("Geyser.RakRateLimitingDisabled", "false")) || isWhitelistedProxyProtocol) { + // We would already block any non-whitelisted IP addresses in onConnectionRequest so we can remove the rate limiter + channel.pipeline().remove(RakServerRateLimiter.NAME); + } } public void shutdown() { @@ -199,11 +212,26 @@ public final class GeyserServer { GeyserServerInitializer serverInitializer = new GeyserServerInitializer(this.geyser); playerGroup = serverInitializer.getEventLoopGroup(); this.geyser.getLogger().debug("Setting MTU to " + this.geyser.getConfig().getMtu()); + + int rakPacketLimit = positivePropOrDefault("Geyser.RakPacketLimit", DEFAULT_PACKET_LIMIT); + this.geyser.getLogger().debug("Setting RakNet packet limit to " + rakPacketLimit); + + boolean isWhitelistedProxyProtocol = this.geyser.getConfig().getBedrock().isEnableProxyProtocol() + && !this.geyser.getConfig().getBedrock().getProxyProtocolWhitelistedIPs().isEmpty(); + int rakOfflinePacketLimit = positivePropOrDefault("Geyser.RakOfflinePacketLimit", isWhitelistedProxyProtocol ? Integer.MAX_VALUE : DEFAULT_OFFLINE_PACKET_LIMIT); + this.geyser.getLogger().debug("Setting RakNet offline packet limit to " + rakOfflinePacketLimit); + + int rakGlobalPacketLimit = positivePropOrDefault("Geyser.RakGlobalPacketLimit", DEFAULT_GLOBAL_PACKET_LIMIT); + this.geyser.getLogger().debug("Setting RakNet global packet limit to " + rakGlobalPacketLimit); + return new ServerBootstrap() .channelFactory(RakChannelFactory.server(TRANSPORT.datagramChannel())) .group(group, childGroup) .option(RakChannelOption.RAK_HANDLE_PING, true) .option(RakChannelOption.RAK_MAX_MTU, this.geyser.getConfig().getMtu()) + .option(RakChannelOption.RAK_PACKET_LIMIT, rakPacketLimit) + .option(RakChannelOption.RAK_OFFLINE_PACKET_LIMIT, rakOfflinePacketLimit) + .option(RakChannelOption.RAK_GLOBAL_PACKET_LIMIT, rakGlobalPacketLimit) .childHandler(serverInitializer); } @@ -352,6 +380,27 @@ public final class GeyserServer { } } + private static int positivePropOrDefault(String property, int defaultValue) { + String value = System.getProperty(property); + try { + int parsed = value != null ? Integer.parseInt(value) : defaultValue; + + if (parsed < 1) { + GeyserImpl.getInstance().getLogger().warning( + "Non-postive integer value for " + property + ": " + value + ". Using default value: " + defaultValue + ); + return defaultValue; + } + + return parsed; + } catch (NumberFormatException e) { + GeyserImpl.getInstance().getLogger().warning( + "Invalid integer value for " + property + ": " + value + ". Using default value: " + defaultValue + ); + return defaultValue; + } + } + private static Transport compatibleTransport() { TransportHelper.TransportMethod transportMethod = TransportHelper.determineTransportMethod(); if (transportMethod == TransportHelper.TransportMethod.EPOLL) { diff --git a/core/src/main/java/org/geysermc/geyser/util/FileUtils.java b/core/src/main/java/org/geysermc/geyser/util/FileUtils.java index c8cd31058..c8423c3be 100644 --- a/core/src/main/java/org/geysermc/geyser/util/FileUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/FileUtils.java @@ -27,6 +27,7 @@ package org.geysermc.geyser.util; import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.annotation.Nulls; +import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import org.geysermc.geyser.GeyserBootstrap; @@ -56,6 +57,8 @@ public class FileUtils { */ public static T loadConfig(File src, Class valueType) throws IOException { ObjectMapper objectMapper = new ObjectMapper(new YAMLFactory()) + // Allow inference of single values as arrays + .enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY) .setDefaultSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY)); return objectMapper.readValue(src, valueType); } diff --git a/core/src/main/java/org/geysermc/geyser/util/WebUtils.java b/core/src/main/java/org/geysermc/geyser/util/WebUtils.java index fbcbd4a3c..f453092b3 100644 --- a/core/src/main/java/org/geysermc/geyser/util/WebUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/WebUtils.java @@ -40,6 +40,7 @@ import java.nio.file.Files; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.Map; +import java.util.stream.Stream; public class WebUtils { @@ -176,6 +177,13 @@ public class WebUtils { return connectionToString(con); } + /** + * Find a SRV record for the given address + * + * @param geyser Geyser instance + * @param remoteAddress Address to find the SRV record for + * @return The SRV record or null if not found + */ public static String @Nullable [] findSrvRecord(GeyserImpl geyser, String remoteAddress) { try { // Searches for a server address and a port from a SRV record of the specified host name @@ -193,4 +201,26 @@ public class WebUtils { } return null; } + + /** + * Get a stream of lines from the given URL + * + * @param reqURL URL to fetch + * @return Stream of lines from the URL or an empty stream if the request fails + */ + public static Stream getLineStream(String reqURL) { + try { + URL url = new URL(reqURL); + HttpURLConnection con = (HttpURLConnection) url.openConnection(); + con.setRequestMethod("GET"); + con.setRequestProperty("User-Agent", "Geyser-" + GeyserImpl.getInstance().getPlatformType().toString() + "/" + GeyserImpl.VERSION); // Otherwise Java 8 fails on checking updates + con.setConnectTimeout(10000); + con.setReadTimeout(10000); + + return connectionToString(con).lines(); + } catch (Exception e) { + GeyserImpl.getInstance().getLogger().error("Error while trying to get a stream from " + reqURL, e); + return Stream.empty(); + } + } } diff --git a/core/src/main/resources/config.yml b/core/src/main/resources/config.yml index 0617b316c..c70b0d7ab 100644 --- a/core/src/main/resources/config.yml +++ b/core/src/main/resources/config.yml @@ -39,8 +39,8 @@ bedrock: # A list of allowed PROXY protocol speaking proxy IP addresses/subnets. Only effective when "enable-proxy-protocol" is enabled, and # should really only be used when you are not able to use a proper firewall (usually true with shared hosting providers etc.). # Keeping this list empty means there is no IP address whitelist. - # Both IP addresses and subnets are supported. - #proxy-protocol-whitelisted-ips: [ "127.0.0.1", "172.18.0.0/16" ] + # IP addresses, subnets, and links to plain text files are supported. + #proxy-protocol-whitelisted-ips: [ "127.0.0.1", "172.18.0.0/16", "https://example.com/whitelist.txt" ] remote: # The IP address of the remote (Java Edition) server # If it is "auto", for standalone version the remote address will be set to 127.0.0.1, diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0e446a48f..b194c5a4b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ gson = "2.3.1" # Provided by Spigot 1.8.8 websocket = "1.5.1" protocol = "3.0.0.Beta1-20240313.120922-126" protocol-connection = "3.0.0.Beta1-20240313.120922-125" -raknet = "1.0.0.CR1-20240330.101522-15" +raknet = "1.0.0.CR1-20240330.103819-16" blockstateupdater="1.20.70-20240303.125052-2" mcauthlib = "d9d773e" mcprotocollib = "1.20.4-2-20240116.220521-7" From fa441f1c7b85da8174fc535a8efb00885b9de9ba Mon Sep 17 00:00:00 2001 From: Sage Date: Mon, 1 Apr 2024 23:33:12 +0200 Subject: [PATCH 223/344] Add ConnectionRequestEvent (#4533) * Add ConnectionRequestEvent and implement it * Add debug message and use InetSocketAddress instead of string * Provide both proxy and real client ip And add some minor javadocs * Make ProxyIp nullable * Apply changes from pr Co-authored-by: rtm516 * Apply changes from pr Co-authored-by: rtm516 * Apply changes from pr Co-authored-by: rtm516 * Bump API version * Dont JiJ common on mod platforms --------- Co-authored-by: rtm516 Co-authored-by: Kas-tle <26531652+Kas-tle@users.noreply.github.com> --- .../connection/ConnectionRequestEvent.java | 88 +++++++++++++++++++ bootstrap/mod/fabric/build.gradle.kts | 1 + bootstrap/mod/neoforge/build.gradle.kts | 1 + .../geyser/network/netty/GeyserServer.java | 9 ++ gradle.properties | 4 +- 5 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 api/src/main/java/org/geysermc/geyser/api/event/connection/ConnectionRequestEvent.java diff --git a/api/src/main/java/org/geysermc/geyser/api/event/connection/ConnectionRequestEvent.java b/api/src/main/java/org/geysermc/geyser/api/event/connection/ConnectionRequestEvent.java new file mode 100644 index 000000000..5c1f4ef51 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/event/connection/ConnectionRequestEvent.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2019-2024 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.api.event.connection; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.event.Cancellable; +import org.geysermc.event.Event; + +import java.net.InetSocketAddress; + +/** + * Called whenever a client attempts to connect to the server, before the connection is accepted. + */ +public final class ConnectionRequestEvent implements Event, Cancellable { + + private boolean cancelled; + private final InetSocketAddress ip; + private final InetSocketAddress proxyIp; + + public ConnectionRequestEvent(@NonNull InetSocketAddress ip, @Nullable InetSocketAddress proxyIp) { + this.ip = ip; + this.proxyIp = proxyIp; + } + + /** + * The IP address of the client attempting to connect + * + * @return the IP address of the client attempting to connect + */ + @NonNull + public InetSocketAddress getInetSocketAddress() { + return ip; + } + + /** + * The IP address of the proxy handling the connection. It will return null if there is no proxy. + * + * @return the IP address of the proxy handling the connection + */ + @Nullable + public InetSocketAddress getProxyIp() { + return proxyIp; + } + + /** + * The cancel status of this event. If this event is cancelled, the connection will be rejected. + * + * @return the cancel status of this event + */ + @Override + public boolean isCancelled() { + return cancelled; + } + + /** + * Sets the cancel status of this event. If this event is canceled, the connection will be rejected. + * + * @param cancelled the cancel status of this event. + */ + @Override + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } +} diff --git a/bootstrap/mod/fabric/build.gradle.kts b/bootstrap/mod/fabric/build.gradle.kts index 538147b15..ec8ae03bc 100644 --- a/bootstrap/mod/fabric/build.gradle.kts +++ b/bootstrap/mod/fabric/build.gradle.kts @@ -41,6 +41,7 @@ dependencies { // Let's shade in our own api shadow(projects.api) { isTransitive = false } + shadow(projects.common) { isTransitive = false } // Permissions modImplementation(libs.fabric.permissions) diff --git a/bootstrap/mod/neoforge/build.gradle.kts b/bootstrap/mod/neoforge/build.gradle.kts index f7204332b..ff77bcc5c 100644 --- a/bootstrap/mod/neoforge/build.gradle.kts +++ b/bootstrap/mod/neoforge/build.gradle.kts @@ -31,6 +31,7 @@ dependencies { // Let's shade in our own api shadow(projects.api) { isTransitive = false } + shadow(projects.common) { isTransitive = false } // Include all transitive deps of core via JiJ includeTransitive(projects.core) diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java b/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java index ce904d465..f4059a9e7 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java @@ -49,6 +49,7 @@ import org.cloudburstmc.netty.handler.codec.raknet.server.RakServerOfflineHandle import org.cloudburstmc.netty.handler.codec.raknet.server.RakServerRateLimiter; import org.cloudburstmc.protocol.bedrock.BedrockPong; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.event.connection.ConnectionRequestEvent; import org.geysermc.geyser.command.defaults.ConnectionTestCommand; import org.geysermc.geyser.configuration.GeyserConfiguration; import org.geysermc.geyser.event.type.GeyserBedrockPingEventImpl; @@ -261,6 +262,14 @@ public final class GeyserServer { } else { ip = ""; } + + ConnectionRequestEvent requestEvent = new ConnectionRequestEvent(inetSocketAddress, this.proxiedAddresses.get(inetSocketAddress)); + geyser.eventBus().fire(requestEvent); + if (requestEvent.isCancelled()) { + geyser.getLogger().debug("Connection request from " + ip + " was cancelled using the API!"); + return false; + } + geyser.getLogger().info(GeyserLocale.getLocaleStringLog("geyser.network.attempt_connect", ip)); return true; } diff --git a/gradle.properties b/gradle.properties index a8e5eaaaf..a7c0bf93d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,5 +7,5 @@ org.gradle.vfs.watch=false group=org.geysermc id=geyser -version=2.2.2-SNAPSHOT -description=Allows for players from Minecraft: Bedrock Edition to join Minecraft: Java Edition servers. \ No newline at end of file +version=2.2.3-SNAPSHOT +description=Allows for players from Minecraft: Bedrock Edition to join Minecraft: Java Edition servers. From 08aa5282d4a8e42acfaba3315e2e62c54e9efc06 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Mon, 1 Apr 2024 15:50:58 -0700 Subject: [PATCH 224/344] Ensure proxiedAddresses is not null before lookup (#4539) --- .../java/org/geysermc/geyser/network/netty/GeyserServer.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java b/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java index f4059a9e7..db103d10e 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java @@ -263,7 +263,10 @@ public final class GeyserServer { ip = ""; } - ConnectionRequestEvent requestEvent = new ConnectionRequestEvent(inetSocketAddress, this.proxiedAddresses.get(inetSocketAddress)); + ConnectionRequestEvent requestEvent = new ConnectionRequestEvent( + inetSocketAddress, + this.proxiedAddresses != null ? this.proxiedAddresses.get(inetSocketAddress) : null + ); geyser.eventBus().fire(requestEvent); if (requestEvent.isCancelled()) { geyser.getLogger().debug("Connection request from " + ip + " was cancelled using the API!"); From 47237e07b789e93056a0761376c688f03b86b8ae Mon Sep 17 00:00:00 2001 From: rtm516 Date: Tue, 2 Apr 2024 00:10:12 +0100 Subject: [PATCH 225/344] Fix block custom registration failing with simmilar named items (#4540) --- .../CustomBlockRegistryPopulator.java | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java index 36b1fc859..b2d238ddb 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java @@ -1,3 +1,28 @@ +/* + * Copyright (c) 2019-2024 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 it.unimi.dsi.fastutil.ints.Int2ObjectMap; @@ -80,7 +105,6 @@ public class CustomBlockRegistryPopulator { } private static Set CUSTOM_BLOCKS; - private static Set CUSTOM_BLOCK_NAMES; private static Map CUSTOM_BLOCK_ITEM_OVERRIDES; private static Map NON_VANILLA_BLOCK_STATE_OVERRIDES; private static Map BLOCK_STATE_OVERRIDES_QUEUE; @@ -90,19 +114,19 @@ public class CustomBlockRegistryPopulator { */ private static void populateBedrock() { CUSTOM_BLOCKS = new ObjectOpenHashSet<>(); - CUSTOM_BLOCK_NAMES = new ObjectOpenHashSet<>(); CUSTOM_BLOCK_ITEM_OVERRIDES = new HashMap<>(); NON_VANILLA_BLOCK_STATE_OVERRIDES = new HashMap<>(); BLOCK_STATE_OVERRIDES_QUEUE = new HashMap<>(); + Set customBlockIdentifiers = new ObjectOpenHashSet<>(); GeyserImpl.getInstance().getEventBus().fire(new GeyserDefineCustomBlocksEvent() { @Override public void register(@NonNull CustomBlockData customBlockData) { if (customBlockData.name().isEmpty()) { throw new IllegalArgumentException("Custom block name must have at least 1 character."); } - if (!CUSTOM_BLOCK_NAMES.add(customBlockData.name())) { - throw new IllegalArgumentException("Another custom block was already registered under the name: " + customBlockData.name()); + if (!customBlockIdentifiers.add(customBlockData.identifier())) { + throw new IllegalArgumentException("Another custom block was already registered under the identifier: " + customBlockData.identifier()); } if (Character.isDigit(customBlockData.name().charAt(0))) { throw new IllegalArgumentException("Custom block can not start with a digit. Name: " + customBlockData.name()); From 29bd8966820c9e0bb836de870caff457c5f5fbf6 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Tue, 2 Apr 2024 02:11:03 +0100 Subject: [PATCH 226/344] Fix CreativeCategory enum numbers (#4542) --- .../org/geysermc/geyser/api/util/CreativeCategory.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/api/src/main/java/org/geysermc/geyser/api/util/CreativeCategory.java b/api/src/main/java/org/geysermc/geyser/api/util/CreativeCategory.java index 207320b1e..a3f9d069c 100644 --- a/api/src/main/java/org/geysermc/geyser/api/util/CreativeCategory.java +++ b/api/src/main/java/org/geysermc/geyser/api/util/CreativeCategory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2023 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2024 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 @@ -31,12 +31,11 @@ import org.checkerframework.checker.nullness.qual.NonNull; * Represents the creative menu categories or tabs. */ public enum CreativeCategory { - COMMANDS("commands", 1), - CONSTRUCTION("construction", 2), + CONSTRUCTION("construction", 1), + NATURE("nature", 2), EQUIPMENT("equipment", 3), ITEMS("items", 4), - NATURE("nature", 5), - NONE("none", 6); + NONE("none", 5); private final String internalName; private final int id; From 1819ed4dbdb328f559ed87361f5f7326028ed94e Mon Sep 17 00:00:00 2001 From: Eclipse <116838833+eclipseisoffline@users.noreply.github.com> Date: Thu, 4 Apr 2024 18:55:00 +0000 Subject: [PATCH 227/344] Remove Java custom armor trims when translating item to Bedrock to prevent visual issues (#4548) * Fix (or workaround) armor items with custom armor trims having no texture on bedrock * Fix armor items with custom trims causing issues on entity models by removing the Trim tag entirely * Refer to minecraft namespace inline for consistency --- .../java/org/geysermc/geyser/item/type/ArmorItem.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java index 38144f318..b58f760d1 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java @@ -47,6 +47,14 @@ public class ArmorItem extends Item { if (tag.get("Trim") instanceof CompoundTag trim) { StringTag material = trim.remove("material"); StringTag pattern = trim.remove("pattern"); + + // discard custom trim patterns/materials to prevent visual glitches on bedrock + if (!material.getValue().startsWith("minecraft:") + || !pattern.getValue().startsWith("minecraft:")) { + tag.remove("Trim"); + return; + } + // bedrock has an uppercase first letter key, and the value is not namespaced trim.put(new StringTag("Material", stripNamespace(material.getValue()))); trim.put(new StringTag("Pattern", stripNamespace(pattern.getValue()))); From 0972e4f4d7892f1387a87eb918f3137b86a590aa Mon Sep 17 00:00:00 2001 From: rtm516 Date: Fri, 5 Apr 2024 22:21:27 +0100 Subject: [PATCH 228/344] Update CreativeCategory none to have the correct value (#4549) --- .../java/org/geysermc/geyser/api/util/CreativeCategory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/org/geysermc/geyser/api/util/CreativeCategory.java b/api/src/main/java/org/geysermc/geyser/api/util/CreativeCategory.java index a3f9d069c..245eb9bc2 100644 --- a/api/src/main/java/org/geysermc/geyser/api/util/CreativeCategory.java +++ b/api/src/main/java/org/geysermc/geyser/api/util/CreativeCategory.java @@ -35,7 +35,7 @@ public enum CreativeCategory { NATURE("nature", 2), EQUIPMENT("equipment", 3), ITEMS("items", 4), - NONE("none", 5); + NONE("none", 6); private final String internalName; private final int id; From 3d9f3ac64582886a85a9c5bb28e8d2a0ca6376fc Mon Sep 17 00:00:00 2001 From: Denys Loshkarev <26629861+denysloshkarev@users.noreply.github.com> Date: Sun, 7 Apr 2024 01:12:56 +0300 Subject: [PATCH 229/344] Show 1.20.73 as being supported (#4543) * update version supported by plugin * Update README.md --- README.md | 2 +- .../src/main/java/org/geysermc/geyser/network/GameProtocol.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8a28e7177..8dcbfb186 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,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.20.40 - 1.20.72 and Minecraft Java 1.20.4 +### Currently supporting Minecraft Bedrock 1.20.40 - 1.20.73 and Minecraft Java 1.20.4 ## 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/GameProtocol.java b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java index 900463c5c..d975ebbf6 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java @@ -72,7 +72,7 @@ public final class GameProtocol { .minecraftVersion("1.20.60/1.20.62") .build()); SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC.toBuilder() - .minecraftVersion("1.20.70/1.20.72") + .minecraftVersion("1.20.70/1.20.73") .build()); } From fa2e4e5a9418080cd9bd3b1ae464099928c49ffc Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sun, 7 Apr 2024 22:44:58 -0400 Subject: [PATCH 230/344] Reduce processing for incoming TrimDataPackets --- .../geysermc/geyser/network/GameProtocol.java | 32 +++++++++++++------ .../geyser/network/LoggingPacketHandler.java | 5 +++ 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java index d975ebbf6..f43706db0 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java @@ -27,13 +27,17 @@ package org.geysermc.geyser.network; import com.github.steveice10.mc.protocol.codec.MinecraftCodec; import com.github.steveice10.mc.protocol.codec.PacketCodec; +import io.netty.buffer.ByteBuf; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; +import org.cloudburstmc.protocol.bedrock.codec.BedrockCodecHelper; +import org.cloudburstmc.protocol.bedrock.codec.v582.serializer.TrimDataSerializer_v582; import org.cloudburstmc.protocol.bedrock.codec.v622.Bedrock_v622; import org.cloudburstmc.protocol.bedrock.codec.v630.Bedrock_v630; import org.cloudburstmc.protocol.bedrock.codec.v649.Bedrock_v649; import org.cloudburstmc.protocol.bedrock.codec.v662.Bedrock_v662; import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec; +import org.cloudburstmc.protocol.bedrock.packet.TrimDataPacket; import org.geysermc.geyser.session.GeyserSession; import java.util.ArrayList; @@ -48,7 +52,7 @@ public final class GameProtocol { * Default Bedrock codec that should act as a fallback. Should represent the latest available * release of the game that Geyser supports. */ - public static final BedrockCodec DEFAULT_BEDROCK_CODEC = Bedrock_v662.CODEC; + public static final BedrockCodec DEFAULT_BEDROCK_CODEC = processCodec(Bedrock_v662.CODEC); /** * A list of all supported Bedrock versions that can join Geyser @@ -62,18 +66,18 @@ public final class GameProtocol { private static final PacketCodec DEFAULT_JAVA_CODEC = MinecraftCodec.CODEC; static { - SUPPORTED_BEDROCK_CODECS.add(Bedrock_v622.CODEC.toBuilder() + SUPPORTED_BEDROCK_CODECS.add(processCodec(Bedrock_v622.CODEC.toBuilder() .minecraftVersion("1.20.40/1.20.41") - .build()); - SUPPORTED_BEDROCK_CODECS.add(Bedrock_v630.CODEC.toBuilder() + .build())); + SUPPORTED_BEDROCK_CODECS.add(processCodec(Bedrock_v630.CODEC.toBuilder() .minecraftVersion("1.20.50/1.20.51") - .build()); - SUPPORTED_BEDROCK_CODECS.add(Bedrock_v649.CODEC.toBuilder() + .build())); + SUPPORTED_BEDROCK_CODECS.add(processCodec(Bedrock_v649.CODEC.toBuilder() .minecraftVersion("1.20.60/1.20.62") - .build()); - SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC.toBuilder() + .build())); + SUPPORTED_BEDROCK_CODECS.add(processCodec(DEFAULT_BEDROCK_CODEC.toBuilder() .minecraftVersion("1.20.70/1.20.73") - .build()); + .build())); } /** @@ -164,6 +168,16 @@ public final class GameProtocol { return joiner.toString(); } + private static BedrockCodec processCodec(BedrockCodec codec) { + return codec.toBuilder() + .updateSerializer(TrimDataPacket.class, new TrimDataSerializer_v582() { + @Override + public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, TrimDataPacket packet) { + } + }) + .build(); + } + private GameProtocol() { } } diff --git a/core/src/main/java/org/geysermc/geyser/network/LoggingPacketHandler.java b/core/src/main/java/org/geysermc/geyser/network/LoggingPacketHandler.java index 0cfcc3d46..910f76ffb 100644 --- a/core/src/main/java/org/geysermc/geyser/network/LoggingPacketHandler.java +++ b/core/src/main/java/org/geysermc/geyser/network/LoggingPacketHandler.java @@ -891,4 +891,9 @@ public class LoggingPacketHandler implements BedrockPacketHandler { public PacketSignal handle(ToggleCrafterSlotRequestPacket packet) { return defaultHandler(packet); } + + @Override + public PacketSignal handle(TrimDataPacket packet) { + return defaultHandler(packet); + } } \ No newline at end of file From c91182132c78cb4575fce15260a9bf4abd4dce94 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Mon, 8 Apr 2024 10:05:48 +0100 Subject: [PATCH 231/344] Update Crowdin on README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8dcbfb186..ce2b67af1 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) [![Discord](https://img.shields.io/discord/613163671870242838.svg?color=%237289da&label=discord)](https://discord.gg/geysermc) -[![Crowdin](https://badges.crowdin.net/geyser/localized.svg)](https://translate.geysermc.org/) +[![Crowdin](https://badges.crowdin.net/e/51361b7f8a01644a238d0fe8f3bddc62/localized.svg)](https://translate.geysermc.org/) Geyser is a bridge between Minecraft: Bedrock Edition and Minecraft: Java Edition, closing the gap from those wanting to play true cross-platform. From ca0e226aac445ad8b0c213c10a3647a1874eae03 Mon Sep 17 00:00:00 2001 From: Eclipse <116838833+eclipseisoffline@users.noreply.github.com> Date: Thu, 11 Apr 2024 01:05:15 +0000 Subject: [PATCH 232/344] Fix breaking of custom head blocks added by Polymer by adding a default fallback to block mappings (#4557) --- .../bedrock/entity/player/BedrockActionTranslator.java | 4 ++-- .../protocol/java/level/JavaBlockDestructionTranslator.java | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java index 90a841ac2..33410f240 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java @@ -163,7 +163,7 @@ public class BedrockActionTranslator extends PacketTranslator Date: Fri, 12 Apr 2024 13:12:38 +0100 Subject: [PATCH 233/344] Fix user agent strings (#4562) --- .../org/geysermc/geyser/skin/SkinProvider.java | 4 ++-- .../org/geysermc/geyser/util/WebUtils.java | 18 +++++++++++------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/skin/SkinProvider.java b/core/src/main/java/org/geysermc/geyser/skin/SkinProvider.java index 12a1e8b2b..683712c22 100644 --- a/core/src/main/java/org/geysermc/geyser/skin/SkinProvider.java +++ b/core/src/main/java/org/geysermc/geyser/skin/SkinProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2024 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 @@ -674,7 +674,7 @@ public class SkinProvider { image = readFiveZigCape(imageUrl); } else { HttpURLConnection con = (HttpURLConnection) new URL(imageUrl).openConnection(); - con.setRequestProperty("User-Agent", "Geyser-" + GeyserImpl.getInstance().getPlatformType().toString() + "/" + GeyserImpl.VERSION); + con.setRequestProperty("User-Agent", WebUtils.getUserAgent()); con.setConnectTimeout(10000); con.setReadTimeout(10000); diff --git a/core/src/main/java/org/geysermc/geyser/util/WebUtils.java b/core/src/main/java/org/geysermc/geyser/util/WebUtils.java index f453092b3..1b7f2d9d9 100644 --- a/core/src/main/java/org/geysermc/geyser/util/WebUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/WebUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2024 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 @@ -55,7 +55,7 @@ public class WebUtils { URL url = new URL(reqURL); HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.setRequestMethod("GET"); - con.setRequestProperty("User-Agent", "Geyser-" + GeyserImpl.getInstance().getPlatformType().toString() + "/" + GeyserImpl.VERSION); // Otherwise Java 8 fails on checking updates + con.setRequestProperty("User-Agent", getUserAgent()); // Otherwise Java 8 fails on checking updates con.setConnectTimeout(10000); con.setReadTimeout(10000); @@ -73,7 +73,7 @@ public class WebUtils { */ public static JsonNode getJson(String reqURL) throws IOException { HttpURLConnection con = (HttpURLConnection) new URL(reqURL).openConnection(); - con.setRequestProperty("User-Agent", "Geyser-" + GeyserImpl.getInstance().getPlatformType().toString() + "/" + GeyserImpl.VERSION); + con.setRequestProperty("User-Agent", getUserAgent()); con.setConnectTimeout(10000); con.setReadTimeout(10000); return GeyserImpl.JSON_MAPPER.readTree(con.getInputStream()); @@ -88,7 +88,7 @@ public class WebUtils { public static void downloadFile(String reqURL, String fileLocation) { try { HttpURLConnection con = (HttpURLConnection) new URL(reqURL).openConnection(); - con.setRequestProperty("User-Agent", "Geyser-" + GeyserImpl.getInstance().getPlatformType().toString() + "/" + GeyserImpl.VERSION); + con.setRequestProperty("User-Agent", getUserAgent()); InputStream in = con.getInputStream(); Files.copy(in, Paths.get(fileLocation), StandardCopyOption.REPLACE_EXISTING); } catch (Exception e) { @@ -109,7 +109,7 @@ public class WebUtils { HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.setRequestMethod("POST"); con.setRequestProperty("Content-Type", "text/plain"); - con.setRequestProperty("User-Agent", "Geyser-" + GeyserImpl.getInstance().getPlatformType().toString() + "/" + GeyserImpl.VERSION); + con.setRequestProperty("User-Agent", getUserAgent()); con.setDoOutput(true); OutputStream out = con.getOutputStream(); @@ -164,7 +164,7 @@ public class WebUtils { HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.setRequestMethod("POST"); con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); - con.setRequestProperty("User-Agent", "Geyser-" + GeyserImpl.getInstance().getPlatformType().toString() + "/" + GeyserImpl.VERSION); + con.setRequestProperty("User-Agent", getUserAgent()); con.setDoOutput(true); try (OutputStream out = con.getOutputStream()) { @@ -213,7 +213,7 @@ public class WebUtils { URL url = new URL(reqURL); HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.setRequestMethod("GET"); - con.setRequestProperty("User-Agent", "Geyser-" + GeyserImpl.getInstance().getPlatformType().toString() + "/" + GeyserImpl.VERSION); // Otherwise Java 8 fails on checking updates + con.setRequestProperty("User-Agent", getUserAgent()); // Otherwise Java 8 fails on checking updates con.setConnectTimeout(10000); con.setReadTimeout(10000); @@ -223,4 +223,8 @@ public class WebUtils { return Stream.empty(); } } + + public static String getUserAgent() { + return "Geyser-" + GeyserImpl.getInstance().getPlatformType().platformName() + "/" + GeyserImpl.VERSION; + } } From a24f68412315fdabe93053d7722f9c9f15fc6511 Mon Sep 17 00:00:00 2001 From: chris Date: Sun, 14 Apr 2024 00:16:26 +0200 Subject: [PATCH 234/344] Update to Gradle 8.7, bump loom to 1.6 (#4565) * Update to Gradle 8.6, bump loom to 1.6 * update to gradle 8.7 --- bootstrap/mod/fabric/build.gradle.kts | 11 +------ gradle/libs.versions.toml | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 60756 -> 43462 bytes gradle/wrapper/gradle-wrapper.properties | 4 ++- gradlew | 35 ++++++++++++++--------- gradlew.bat | 21 +++++++------- 6 files changed, 38 insertions(+), 35 deletions(-) diff --git a/bootstrap/mod/fabric/build.gradle.kts b/bootstrap/mod/fabric/build.gradle.kts index ec8ae03bc..53e4dfe53 100644 --- a/bootstrap/mod/fabric/build.gradle.kts +++ b/bootstrap/mod/fabric/build.gradle.kts @@ -22,16 +22,11 @@ dependencies { // These are NOT transitively included, and instead shadowed + relocated. // Avoids fabric complaining about non-SemVer versioning - // TODO: re-evaluate after loom 1.6 (https://github.com/FabricMC/fabric-loom/pull/1075) shadow(libs.protocol.connection) { isTransitive = false } shadow(libs.protocol.common) { isTransitive = false } shadow(libs.protocol.codec) { isTransitive = false } shadow(libs.mcauthlib) { isTransitive = false } shadow(libs.raknet) { isTransitive = false } - shadow(libs.netty.codec.haproxy) { isTransitive = false } - shadow("org.cloudburstmc:nbt:3.0.2.Final") { isTransitive = false } - shadow("io.netty:netty-codec-dns:4.1.103.Final") { isTransitive = false } - shadow("io.netty:netty-resolver-dns-classes-macos:4.1.103.Final") { isTransitive = false } // Consequences of shading + relocating mcauthlib: shadow/relocate mcpl! shadow(libs.mcprotocollib) { isTransitive = false } @@ -39,7 +34,7 @@ dependencies { // Since we also relocate cloudburst protocol: shade erosion common shadow(libs.erosion.common) { isTransitive = false } - // Let's shade in our own api + // Let's shade in our own api/common module shadow(projects.api) { isTransitive = false } shadow(projects.common) { isTransitive = false } @@ -52,12 +47,8 @@ application { mainClass.set("org.geysermc.geyser.platform.fabric.GeyserFabricMain") } -relocate("org.cloudburstmc.nbt") relocate("org.cloudburstmc.netty") relocate("org.cloudburstmc.protocol") -relocate("io.netty.handler.codec.dns") -relocate("io.netty.handler.codec.haproxy") -relocate("io.netty.resolver.dns.macos") relocate("com.github.steveice10.mc.protocol") relocate("com.github.steveice10.mc.auth") relocate("com.github.steveice10.packetlib") diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b194c5a4b..04c83ac78 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -40,7 +40,7 @@ mixin = "0.8.5" indra = "3.1.3" shadow = "8.1.1" architectury-plugin = "3.4-SNAPSHOT" -architectury-loom = "1.4-SNAPSHOT" +architectury-loom = "1.6-SNAPSHOT" minotaur = "2.8.7" lombok = "8.4" blossom = "1.2.0" diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 249e5832f090a2944b7473328c07c9755baa3196..d64cd4917707c1f8861d8cb53dd15194d4248596 100644 GIT binary patch literal 43462 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 literal 60756 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 /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -133,22 +131,29 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -193,11 +198,15 @@ if "$cygwin" || "$msys" ; then done fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/gradlew.bat b/gradlew.bat index f127cfd49..25da30dbd 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -26,6 +26,7 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -42,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -56,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail From 5151c25e1a28a9096a411711a9e6ae57b8314654 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Tue, 16 Apr 2024 20:52:46 -0700 Subject: [PATCH 235/344] Support RakNet Cookies (#4554) * Support cookies Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Use cloudburst upstream raknet * Comment out mavenLocal() --------- Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .../kotlin/geyser.modded-conventions.gradle.kts | 1 + core/build.gradle.kts | 4 ++++ .../java/org/geysermc/geyser/dump/DumpInfo.java | 3 +++ .../geyser/network/netty/GeyserServer.java | 17 +++++++++-------- gradle/libs.versions.toml | 2 +- settings.gradle.kts | 3 ++- 6 files changed, 20 insertions(+), 10 deletions(-) diff --git a/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts b/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts index 91bde525e..e011b7139 100644 --- a/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts @@ -107,6 +107,7 @@ dependencies { } repositories { + // mavenLocal() maven("https://repo.opencollab.dev/maven-releases/") maven("https://repo.opencollab.dev/maven-snapshots/") maven("https://jitpack.io") diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 054f4f0ae..93c9f4f13 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -6,6 +6,10 @@ plugins { } dependencies { + constraints { + implementation(libs.raknet) // Ensure protocol does not override the RakNet version + } + api(projects.common) api(projects.api) 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 818607314..e54bbc1eb 100644 --- a/core/src/main/java/org/geysermc/geyser/dump/DumpInfo.java +++ b/core/src/main/java/org/geysermc/geyser/dump/DumpInfo.java @@ -78,6 +78,7 @@ public class DumpInfo { private final GeyserConfiguration config; private final Floodgate floodgate; private final Object2IntMap userPlatforms; + private final int connectionAttempts; private final HashInfo hashInfo; private final RamInfo ramInfo; private LogsInfo logsInfo; @@ -129,6 +130,8 @@ public class DumpInfo { userPlatforms.put(device, userPlatforms.getOrDefault(device, 0) + 1); } + this.connectionAttempts = GeyserImpl.getInstance().getGeyserServer().getConnectionAttempts(); + this.bootstrapInfo = GeyserImpl.getInstance().getBootstrap().getDumpInfo(); this.flagsInfo = new FlagsInfo(); diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java b/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java index db103d10e..8ead16623 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java @@ -74,7 +74,6 @@ import java.util.function.IntFunction; import java.util.function.Supplier; import static org.cloudburstmc.netty.channel.raknet.RakConstants.DEFAULT_GLOBAL_PACKET_LIMIT; -import static org.cloudburstmc.netty.channel.raknet.RakConstants.DEFAULT_OFFLINE_PACKET_LIMIT; import static org.cloudburstmc.netty.channel.raknet.RakConstants.DEFAULT_PACKET_LIMIT; public final class GeyserServer { @@ -111,6 +110,10 @@ public final class GeyserServer { private ChannelFuture[] bootstrapFutures; + // Keep track of connection attempts for dump info + @Getter + private int connectionAttempts = 0; + /** * The port to broadcast in the pong. This can be different from the port the server is bound to, e.g. due to port forwarding. */ @@ -217,11 +220,6 @@ public final class GeyserServer { int rakPacketLimit = positivePropOrDefault("Geyser.RakPacketLimit", DEFAULT_PACKET_LIMIT); this.geyser.getLogger().debug("Setting RakNet packet limit to " + rakPacketLimit); - boolean isWhitelistedProxyProtocol = this.geyser.getConfig().getBedrock().isEnableProxyProtocol() - && !this.geyser.getConfig().getBedrock().getProxyProtocolWhitelistedIPs().isEmpty(); - int rakOfflinePacketLimit = positivePropOrDefault("Geyser.RakOfflinePacketLimit", isWhitelistedProxyProtocol ? Integer.MAX_VALUE : DEFAULT_OFFLINE_PACKET_LIMIT); - this.geyser.getLogger().debug("Setting RakNet offline packet limit to " + rakOfflinePacketLimit); - int rakGlobalPacketLimit = positivePropOrDefault("Geyser.RakGlobalPacketLimit", DEFAULT_GLOBAL_PACKET_LIMIT); this.geyser.getLogger().debug("Setting RakNet global packet limit to " + rakGlobalPacketLimit); @@ -231,8 +229,8 @@ public final class GeyserServer { .option(RakChannelOption.RAK_HANDLE_PING, true) .option(RakChannelOption.RAK_MAX_MTU, this.geyser.getConfig().getMtu()) .option(RakChannelOption.RAK_PACKET_LIMIT, rakPacketLimit) - .option(RakChannelOption.RAK_OFFLINE_PACKET_LIMIT, rakOfflinePacketLimit) .option(RakChannelOption.RAK_GLOBAL_PACKET_LIMIT, rakGlobalPacketLimit) + .option(RakChannelOption.RAK_SEND_COOKIE, true) .childHandler(serverInitializer); } @@ -248,6 +246,7 @@ public final class GeyserServer { } if (!isWhitelistedIP) { + connectionAttempts++; return false; } } @@ -270,10 +269,12 @@ public final class GeyserServer { geyser.eventBus().fire(requestEvent); if (requestEvent.isCancelled()) { geyser.getLogger().debug("Connection request from " + ip + " was cancelled using the API!"); + connectionAttempts++; return false; } - geyser.getLogger().info(GeyserLocale.getLocaleStringLog("geyser.network.attempt_connect", ip)); + geyser.getLogger().debug(GeyserLocale.getLocaleStringLog("geyser.network.attempt_connect", ip)); + connectionAttempts++; return true; } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 04c83ac78..3111750a8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ gson = "2.3.1" # Provided by Spigot 1.8.8 websocket = "1.5.1" protocol = "3.0.0.Beta1-20240313.120922-126" protocol-connection = "3.0.0.Beta1-20240313.120922-125" -raknet = "1.0.0.CR1-20240330.103819-16" +raknet = "1.0.0.CR3-20240416.144209-1" blockstateupdater="1.20.70-20240303.125052-2" mcauthlib = "d9d773e" mcprotocollib = "1.20.4-2-20240116.220521-7" diff --git a/settings.gradle.kts b/settings.gradle.kts index 68848bca4..a39bfa3d2 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -4,6 +4,8 @@ enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") dependencyResolutionManagement { repositories { + // mavenLocal() + // Floodgate, Cumulus etc. maven("https://repo.opencollab.dev/main") @@ -30,7 +32,6 @@ dependencyResolutionManagement { mavenContent { releasesOnly() } } - mavenLocal() mavenCentral() // ViaVersion From c8475d8100f6272a9c892ac81635f720c4d0ee58 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Wed, 17 Apr 2024 03:18:17 -0400 Subject: [PATCH 236/344] Always remove entities from cache (#4577) * Always remove entities from cache * Despawn throwable entities in the void --- .../geysermc/geyser/entity/type/Entity.java | 7 ++----- .../geyser/entity/type/FireballEntity.java | 3 +++ .../geyser/entity/type/FishingHookEntity.java | 3 +++ .../geyser/entity/type/ItemEntity.java | 2 +- .../geyser/entity/type/ItemFrameEntity.java | 3 +-- .../geyser/entity/type/ThrowableEntity.java | 20 +++++++++++++++++-- .../entity/type/living/ArmorStandEntity.java | 4 ++-- .../living/monster/EnderDragonEntity.java | 4 ++-- .../geyser/session/cache/EntityCache.java | 12 ++++++----- .../entity/JavaRemoveEntitiesTranslator.java | 2 +- 10 files changed, 40 insertions(+), 20 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java b/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java index a2b7cc6ec..306c244b3 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java @@ -200,11 +200,9 @@ public class Entity implements GeyserEntity { /** * Despawns the entity - * - * @return can be deleted */ - public boolean despawnEntity() { - if (!valid) return true; + public void despawnEntity() { + if (!valid) return; for (Entity passenger : passengers) { // Make sure all passengers on the despawned entity are updated if (passenger == null) continue; @@ -218,7 +216,6 @@ public class Entity implements GeyserEntity { session.sendUpstreamPacket(removeEntityPacket); valid = false; - return true; } public void moveRelative(double relX, double relY, double relZ, float yaw, float pitch, boolean isOnGround) { diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/FireballEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/FireballEntity.java index 3db032f0f..904596b3a 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/FireballEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/FireballEntity.java @@ -72,6 +72,9 @@ public class FireballEntity extends ThrowableEntity { @Override public void tick() { + if (removedInVoid()) { + return; + } moveAbsoluteImmediate(tickMovement(position), getYaw(), getPitch(), getHeadYaw(), false, false); } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/FishingHookEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/FishingHookEntity.java index bcbff16ce..0de11c382 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/FishingHookEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/FishingHookEntity.java @@ -133,6 +133,9 @@ public class FishingHookEntity extends ThrowableEntity { @Override public void tick() { + if (removedInVoid()) { + return; + } if (hooked || !isInAir() && !isInWater() || isOnGround()) { motion = Vector3f.ZERO; return; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/ItemEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ItemEntity.java index bb67a60f6..69fb3faab 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/ItemEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/ItemEntity.java @@ -74,7 +74,7 @@ public class ItemEntity extends ThrowableEntity { @Override public void tick() { - if (isInWater()) { + if (removedInVoid() || isInWater()) { return; } if (!isOnGround() || (motion.getX() * motion.getX() + motion.getZ() * motion.getZ()) > 0.00001) { 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 295972200..ad1d4b928 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 @@ -148,7 +148,7 @@ public class ItemFrameEntity extends Entity { } @Override - public boolean despawnEntity() { + public void despawnEntity() { UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); updateBlockPacket.setDataLayer(0); updateBlockPacket.setBlockPosition(bedrockPosition); @@ -161,7 +161,6 @@ public class ItemFrameEntity extends Entity { session.getItemFrameCache().remove(bedrockPosition, this); valid = false; - return true; } private NbtMap getDefaultTag() { diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/ThrowableEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ThrowableEntity.java index 60840e65b..47884e60a 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/ThrowableEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/ThrowableEntity.java @@ -55,6 +55,9 @@ public class ThrowableEntity extends Entity implements Tickable { */ @Override public void tick() { + if (removedInVoid()) { + return; + } moveAbsoluteImmediate(position.add(motion), getYaw(), getPitch(), getHeadYaw(), isOnGround(), false); float drag = getDrag(); float gravity = getGravity(); @@ -170,14 +173,14 @@ public class ThrowableEntity extends Entity implements Tickable { } @Override - public boolean despawnEntity() { + public void despawnEntity() { if (definition.entityType() == EntityType.ENDER_PEARL) { LevelEventPacket particlePacket = new LevelEventPacket(); particlePacket.setType(LevelEvent.PARTICLE_TELEPORT); particlePacket.setPosition(position); session.sendUpstreamPacket(particlePacket); } - return super.despawnEntity(); + super.despawnEntity(); } @Override @@ -191,4 +194,17 @@ public class ThrowableEntity extends Entity implements Tickable { moveAbsoluteImmediate(position, yaw, pitch, headYaw, isOnGround, teleported); lastJavaPosition = position; } + + /** + * Removes the entity if it is 64 blocks below the world. + * + * @return true if the entity was removed + */ + public boolean removedInVoid() { + if (position.getY() < session.getDimensionType().minY() - 64) { + session.getEntityCache().removeEntity(this); + return true; + } + return false; + } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java index c64776f18..9c56568c8 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java @@ -99,11 +99,11 @@ public class ArmorStandEntity extends LivingEntity { } @Override - public boolean despawnEntity() { + public void despawnEntity() { if (secondEntity != null) { secondEntity.despawnEntity(); } - return super.despawnEntity(); + super.despawnEntity(); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/EnderDragonEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/EnderDragonEntity.java index bb09a23f4..8c00d065a 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/EnderDragonEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/EnderDragonEntity.java @@ -148,11 +148,11 @@ public class EnderDragonEntity extends MobEntity implements Tickable { } @Override - public boolean despawnEntity() { + public void despawnEntity() { for (EnderDragonPartEntity part : allParts) { part.despawnEntity(); } - return super.despawnEntity(); + super.despawnEntity(); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/EntityCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/EntityCache.java index 8a4b9cb6c..6524e1ddc 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/EntityCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/EntityCache.java @@ -85,27 +85,29 @@ public class EntityCache { return false; } - public boolean removeEntity(Entity entity, boolean force) { + public void removeEntity(Entity entity) { if (entity instanceof PlayerEntity player) { session.getPlayerWithCustomHeads().remove(player.getUuid()); } - if (entity != null && entity.isValid() && (force || entity.despawnEntity())) { + if (entity != null) { + if (entity.isValid()) { + entity.despawnEntity(); + } + long geyserId = entityIdTranslations.remove(entity.getEntityId()); entities.remove(geyserId); if (entity instanceof Tickable) { tickableEntities.remove(entity); } - return true; } - return false; } public void removeAllEntities() { List entities = new ArrayList<>(this.entities.values()); for (Entity entity : entities) { - removeEntity(entity, false); + removeEntity(entity); } session.getPlayerWithCustomHeads().clear(); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaRemoveEntitiesTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaRemoveEntitiesTranslator.java index 65229f29d..776cfb4d7 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaRemoveEntitiesTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaRemoveEntitiesTranslator.java @@ -39,7 +39,7 @@ public class JavaRemoveEntitiesTranslator extends PacketTranslator Date: Wed, 17 Apr 2024 23:21:25 +0200 Subject: [PATCH 237/344] Feature: Structure block translation (#4521) * ported camotoy's attempt of implementing structure blocks, removal of a few TODO's * no more parsing of java structure templates * Don't attempt to re-request structure size * ensure we can load structures in even if we know the size * init: send correct structure size/offset/rotation to java, not fully working yet * restore offsets so we are sending correct values to the java server regarding where we want the structure to be placed * something something mirror * attempt at proper offsets for mirroring AND rotations. this was not fun at all * rotation, mirror, offsetting all seem to work * undo import changes * fix NPE * Proper handling of empty structures, ensure that we can clear the structure block outline when a zero vector was sent for structure size * oops * Update core/src/main/java/org/geysermc/geyser/session/cache/StructureBlockCache.java Co-authored-by: rtm516 * Update core/src/main/java/org/geysermc/geyser/translator/level/block/entity/StructureBlockBlockEntityTranslator.java Co-authored-by: rtm516 * Update core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockStructureBlockUpdateTranslator.java Co-authored-by: rtm516 * Update core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockStructureTemplateDataRequestTranslator.java Co-authored-by: rtm516 * consolidate java structure sending into one method * fix merge conflict --------- Co-authored-by: rtm516 --- README.md | 1 - .../populator/BlockRegistryPopulator.java | 16 +- .../geyser/registry/type/BlockMappings.java | 5 + .../geyser/session/GeyserSession.java | 2 + .../session/cache/StructureBlockCache.java | 59 +++++++ .../StructureBlockBlockEntityTranslator.java | 138 +++++++++++++++ ...BedrockInventoryTransactionTranslator.java | 7 + ...BedrockStructureBlockUpdateTranslator.java | 65 +++++++ ...tructureTemplateDataRequestTranslator.java | 91 ++++++++++ .../level/JavaBlockEntityDataTranslator.java | 59 +++++++ .../geysermc/geyser/util/InventoryUtils.java | 2 +- .../geyser/util/StructureBlockUtils.java | 164 ++++++++++++++++++ 12 files changed, 606 insertions(+), 3 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/session/cache/StructureBlockCache.java create mode 100644 core/src/main/java/org/geysermc/geyser/translator/level/block/entity/StructureBlockBlockEntityTranslator.java create mode 100644 core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockStructureBlockUpdateTranslator.java create mode 100644 core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockStructureTemplateDataRequestTranslator.java create mode 100644 core/src/main/java/org/geysermc/geyser/util/StructureBlockUtils.java diff --git a/README.md b/README.md index ce2b67af1..0aa9d009a 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,6 @@ Take a look [here](https://wiki.geysermc.org/geyser/setup/) for how to set up Ge ## What's Left to be Added/Fixed - Near-perfect movement (to the point where anticheat on large servers is unlikely to ban you) - Some Entity Flags -- Structure block UI ## What can't be fixed There are a few things Geyser is unable to support due to various differences between Minecraft Bedrock and Java. For a list of these limitations, see the [Current Limitations](https://wiki.geysermc.org/geyser/current-limitations/) page. 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 4c52a1530..c54431fbe 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 @@ -144,7 +144,7 @@ public final class BlockRegistryPopulator { builder.remove("version"); // Remove all nbt tags which are not needed for differentiating states builder.remove("name_hash"); // Quick workaround - was added in 1.19.20 builder.remove("network_id"); // Added in 1.19.80 - ???? - builder.remove("block_id"); // Added in 1.20.60 //TODO verify this can be just removed + builder.remove("block_id"); // Added in 1.20.60 //noinspection UnstableApiUsage builder.putCompound("states", statesInterner.intern((NbtMap) builder.remove("states"))); vanillaBlockStates.set(i, builder.build()); @@ -229,6 +229,7 @@ public final class BlockRegistryPopulator { Map itemFrames = new Object2ObjectOpenHashMap<>(); Set jigsawDefinitions = new ObjectOpenHashSet<>(); + Map structureBlockDefinitions = new Object2ObjectOpenHashMap<>(); BlockMappings.BlockMappingsBuilder builder = BlockMappings.builder(); while (blocksIterator.hasNext()) { @@ -272,6 +273,18 @@ public final class BlockRegistryPopulator { jigsawDefinitions.add(bedrockDefinition); } + if (javaId.contains("structure_block")) { + int modeIndex = javaId.indexOf("mode="); + if (modeIndex != -1) { + int startIndex = modeIndex + 5; // Length of "mode=" is 5 + int endIndex = javaId.indexOf("]", startIndex); + if (endIndex != -1) { + String modeValue = javaId.substring(startIndex, endIndex); + structureBlockDefinitions.put(modeValue.toUpperCase(), bedrockDefinition); + } + } + } + boolean waterlogged = entry.getKey().contains("waterlogged=true") || javaId.contains("minecraft:bubble_column") || javaId.contains("minecraft:kelp") || javaId.contains("seagrass"); @@ -358,6 +371,7 @@ public final class BlockRegistryPopulator { .itemFrames(itemFrames) .flowerPotBlocks(flowerPotBlocks) .jigsawStates(jigsawDefinitions) + .structureBlockStates(structureBlockDefinitions) .remappedVanillaIds(remappedVanillaIds) .blockProperties(customBlockProperties) .customBlockStateDefinitions(customBlockStateDefinitions) 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 8c0414a6d..c76f024af 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 @@ -61,6 +61,7 @@ public class BlockMappings implements DefinitionRegistry { Map flowerPotBlocks; Set jigsawStates; + Map structureBlockStates; List blockProperties; Object2ObjectMap customBlockStateDefinitions; @@ -96,6 +97,10 @@ public class BlockMappings implements DefinitionRegistry { return false; } + public BlockDefinition getStructureBlockFromMode(String mode) { + return structureBlockStates.get(mode); + } + @Override public @Nullable GeyserBedrockBlock getDefinition(int bedrockId) { if (bedrockId < 0 || bedrockId >= this.bedrockRuntimeMap.length) { diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 7a4a8ff6f..c0749400a 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -214,6 +214,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { private final PistonCache pistonCache; private final PreferencesCache preferencesCache; private final SkullCache skullCache; + private final StructureBlockCache structureBlockCache; private final TagCache tagCache; private final WorldCache worldCache; @@ -625,6 +626,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { this.pistonCache = new PistonCache(this); this.preferencesCache = new PreferencesCache(this); this.skullCache = new SkullCache(this); + this.structureBlockCache = new StructureBlockCache(); this.tagCache = new TagCache(); this.worldCache = new WorldCache(this); this.cameraData = new GeyserCameraData(this); diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/StructureBlockCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/StructureBlockCache.java new file mode 100644 index 000000000..170f80d0a --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/session/cache/StructureBlockCache.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2019-2024 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.session.cache; + +import lombok.Getter; +import lombok.Setter; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.cloudburstmc.math.vector.Vector3i; + +@Setter +@Getter +public final class StructureBlockCache { + + /** + * Stores the current structure's name to be able to detect changes in the loaded structure + */ + private @Nullable String currentStructureName; + + /** + * Stores the offset changes added by Geyser that ensure that structure bounds + * are the same for Java and Bedrock + */ + private @Nullable Vector3i bedrockOffset; + + /** + * Stores the current structure block position while we're waiting on the Java + * server to send the data we need. + */ + private @Nullable Vector3i currentStructureBlock; + + public void clear() { + this.currentStructureName = null; + this.currentStructureBlock = null; + this.bedrockOffset = null; + } +} diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/StructureBlockBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/StructureBlockBlockEntityTranslator.java new file mode 100644 index 000000000..a24d010b7 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/StructureBlockBlockEntityTranslator.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2019-2024 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.translator.level.block.entity; + +import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import org.cloudburstmc.math.vector.Vector3i; +import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtMapBuilder; +import org.cloudburstmc.protocol.bedrock.data.structure.StructureMirror; +import org.cloudburstmc.protocol.bedrock.data.structure.StructureRotation; +import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.util.StructureBlockUtils; + +@BlockEntity(type = BlockEntityType.STRUCTURE_BLOCK) +public class StructureBlockBlockEntityTranslator extends BlockEntityTranslator { + + @Override + public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, CompoundTag tag, int blockState) { + // Sending a structure with size 0 doesn't clear the outline. Hence, we have to force it by replacing the block :/ + int xStructureSize = getOrDefault(tag.get("sizeX"), 0); + int yStructureSize = getOrDefault(tag.get("sizeY"), 0); + int zStructureSize = getOrDefault(tag.get("sizeZ"), 0); + + Vector3i size = Vector3i.from(xStructureSize, yStructureSize, zStructureSize); + + if (size.equals(Vector3i.ZERO)) { + Vector3i position = Vector3i.from(x, y, z); + String mode = getOrDefault(tag.get("mode"), ""); + + // Set to air and back to reset the structure block + UpdateBlockPacket emptyBlockPacket = new UpdateBlockPacket(); + emptyBlockPacket.setDataLayer(0); + emptyBlockPacket.setBlockPosition(position); + emptyBlockPacket.setDefinition(session.getBlockMappings().getBedrockAir()); + session.sendUpstreamPacket(emptyBlockPacket); + + UpdateBlockPacket spawnerBlockPacket = new UpdateBlockPacket(); + spawnerBlockPacket.setDataLayer(0); + spawnerBlockPacket.setBlockPosition(position); + spawnerBlockPacket.setDefinition(session.getBlockMappings().getStructureBlockFromMode(mode)); + session.sendUpstreamPacket(spawnerBlockPacket); + } + + return super.getBlockEntityTag(session, type, x, y, z, tag, blockState); + } + + @Override + public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) { + if (tag.size() < 5) { + return; // These values aren't here + } + + builder.putString("structureName", getOrDefault(tag.get("name"), "")); + + String mode = getOrDefault(tag.get("mode"), ""); + int bedrockData = switch (mode) { + case "LOAD" -> 2; + case "CORNER" -> 3; + case "DATA" -> 4; + default -> 1; // SAVE + }; + + builder.putInt("data", bedrockData); + builder.putString("dataField", ""); // ??? possibly related to Java's "metadata" + + // Mirror behaves different in Java and Bedrock - it requires modifying the position in space as well + String mirror = getOrDefault(tag.get("mirror"), ""); + StructureMirror bedrockMirror = switch (mirror) { + case "FRONT_BACK" -> StructureMirror.X; + case "LEFT_RIGHT" -> StructureMirror.Z; + default -> StructureMirror.NONE; + }; + builder.putByte("mirror", (byte) bedrockMirror.ordinal()); + + builder.putByte("ignoreEntities", getOrDefault(tag.get("ignoreEntities"), (byte) 0)); + builder.putByte("isPowered", getOrDefault(tag.get("powered"), (byte) 0)); + builder.putLong("seed", getOrDefault(tag.get("seed"), 0L)); + builder.putByte("showBoundingBox", getOrDefault(tag.get("showboundingbox"), (byte) 0)); + + String rotation = getOrDefault(tag.get("rotation"), ""); + StructureRotation bedrockRotation = switch (rotation) { + case "CLOCKWISE_90" -> StructureRotation.ROTATE_90; + case "CLOCKWISE_180" -> StructureRotation.ROTATE_180; + case "COUNTERCLOCKWISE_90" -> StructureRotation.ROTATE_270; + default -> StructureRotation.NONE; + }; + builder.putByte("rotation", (byte) bedrockRotation.ordinal()); + + int xStructureSize = getOrDefault(tag.get("sizeX"), 0); + int yStructureSize = getOrDefault(tag.get("sizeY"), 0); + int zStructureSize = getOrDefault(tag.get("sizeZ"), 0); + + // The "positions" are also offsets on Java + int posX = getOrDefault(tag.get("posX"), 0); + int posY = getOrDefault(tag.get("posY"), 0); + int posZ = getOrDefault(tag.get("posZ"), 0); + + Vector3i offset = StructureBlockUtils.calculateOffset(bedrockRotation, bedrockMirror, + xStructureSize, zStructureSize); + + builder.putInt("xStructureOffset", posX + offset.getX()); + builder.putInt("yStructureOffset", posY); + builder.putInt("zStructureOffset", posZ + offset.getZ()); + + builder.putInt("xStructureSize", xStructureSize); + builder.putInt("yStructureSize", yStructureSize); + builder.putInt("zStructureSize", zStructureSize); + + builder.putFloat("integrity", getOrDefault(tag.get("integrity"), 0f)); // Is 1.0f by default on Java but 100.0f on Bedrock + + // Java's "showair" is unrepresented + } +} \ No newline at end of file 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 101035cb5..4ac835268 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 @@ -348,6 +348,13 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator { + + @Override + public void translate(GeyserSession session, StructureBlockUpdatePacket packet) { + StructureEditorData data = packet.getEditorData(); + + UpdateStructureBlockAction action = UpdateStructureBlockAction.UPDATE_DATA; + if (packet.isPowered()) { + if (data.getType() == StructureBlockType.LOAD) { + action = UpdateStructureBlockAction.LOAD_STRUCTURE; + } else if (data.getType() == StructureBlockType.SAVE) { + action = UpdateStructureBlockAction.SAVE_STRUCTURE; + } + } + + UpdateStructureBlockMode mode = switch (data.getType()) { + case CORNER -> UpdateStructureBlockMode.CORNER; + case DATA -> UpdateStructureBlockMode.DATA; + case LOAD -> UpdateStructureBlockMode.LOAD; + default -> UpdateStructureBlockMode.SAVE; + }; + + StructureBlockUtils.sendJavaStructurePacket(session, packet.getBlockPosition(), data.getSettings().getSize(), mode, action, data.getSettings(), + data.isBoundingBoxVisible(), data.getName()); + session.getStructureBlockCache().clear(); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockStructureTemplateDataRequestTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockStructureTemplateDataRequestTranslator.java new file mode 100644 index 000000000..947946f36 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockStructureTemplateDataRequestTranslator.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2019-2024 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.translator.protocol.bedrock; + +import com.github.steveice10.mc.protocol.data.game.inventory.UpdateStructureBlockAction; +import com.github.steveice10.mc.protocol.data.game.inventory.UpdateStructureBlockMode; +import org.cloudburstmc.math.vector.Vector3i; +import org.cloudburstmc.protocol.bedrock.data.structure.StructureSettings; +import org.cloudburstmc.protocol.bedrock.data.structure.StructureTemplateRequestOperation; +import org.cloudburstmc.protocol.bedrock.packet.StructureTemplateDataRequestPacket; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.protocol.PacketTranslator; +import org.geysermc.geyser.translator.protocol.Translator; +import org.geysermc.geyser.util.StructureBlockUtils; + +/** + * Packet used in Bedrock to load structure size into the structure block GUI. It is sent every time the GUI is opened. + * Or, if the player updates the structure name. Which we can use to request the structure size from the Java server! + *

+ * Java does not have this preview, instead, Java clients are forced out of the GUI to look at the area. + */ +@Translator(packet = StructureTemplateDataRequestPacket.class) +public class BedrockStructureTemplateDataRequestTranslator extends PacketTranslator { + + @Override + public void translate(GeyserSession session, StructureTemplateDataRequestPacket packet) { + // All other operation types are ignored by Geyser since we do not support exporting/importing structures + if (packet.getOperation().equals(StructureTemplateRequestOperation.QUERY_SAVED_STRUCTURE)) { + Vector3i size = packet.getSettings().getSize(); + StructureSettings settings = packet.getSettings(); + + // If we send a load packet to the Java server when the structure size is known, it would place the structure. + String currentStructureName = session.getStructureBlockCache().getCurrentStructureName(); + + // Case 1: Opening a structure block with information about structure size, but not yet saved by us + // Case 2: Getting an update from Bedrock with new information, doesn't bother us if it's the same structure + if (!packet.getSettings().getSize().equals(Vector3i.ZERO)) { + if (currentStructureName == null) { + Vector3i offset = StructureBlockUtils.calculateOffset(settings.getRotation(), settings.getMirror(), + settings.getSize().getX(), settings.getSize().getZ()); + session.getStructureBlockCache().setBedrockOffset(offset); + session.getStructureBlockCache().setCurrentStructureName(packet.getName()); + StructureBlockUtils.sendStructureData(session, size, packet.getName()); + return; + } else if (packet.getName().equals(currentStructureName)) { + StructureBlockUtils.sendStructureData(session, size, packet.getName()); + return; + } + } + + // Request a "structure load" from Java server, so it sends us the structure's size + // See the block entity translator for more info + session.getStructureBlockCache().setCurrentStructureBlock(packet.getPosition()); + + StructureBlockUtils.sendJavaStructurePacket(session, + packet.getPosition(), + Vector3i.ZERO, // We expect the Java server to tell us the size + UpdateStructureBlockMode.LOAD, + UpdateStructureBlockAction.LOAD_STRUCTURE, + settings, + true, + packet.getName() + ); + } else { + StructureBlockUtils.sendEmptyStructureData(session); + } + } +} \ No newline at end of file diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEntityDataTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEntityDataTranslator.java index c67a6dee4..325bae593 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEntityDataTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEntityDataTranslator.java @@ -28,9 +28,13 @@ package org.geysermc.geyser.translator.protocol.java.level; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundBlockEntityDataPacket; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.Tag; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; +import org.cloudburstmc.protocol.bedrock.data.structure.StructureMirror; +import org.cloudburstmc.protocol.bedrock.data.structure.StructureRotation; import org.cloudburstmc.protocol.bedrock.packet.ContainerOpenPacket; import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket; import org.geysermc.geyser.level.block.BlockStateValues; @@ -41,6 +45,7 @@ import org.geysermc.geyser.translator.level.block.entity.SkullBlockEntityTransla import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.util.BlockEntityUtils; +import org.geysermc.geyser.util.StructureBlockUtils; @Translator(packet = ClientboundBlockEntityDataPacket.class) public class JavaBlockEntityDataTranslator extends PacketTranslator { @@ -95,5 +100,59 @@ public class JavaBlockEntityDataTranslator extends PacketTranslator 5 + ) { + CompoundTag map = packet.getNbt(); + + String mode = getOrDefault(map.get("mode"), ""); + if (!mode.equalsIgnoreCase("LOAD")) { + return; + } + + String mirror = getOrDefault(map.get("mirror"), ""); + StructureMirror bedrockMirror = switch (mirror) { + case "FRONT_BACK" -> StructureMirror.X; + case "LEFT_RIGHT" -> StructureMirror.Z; + default -> StructureMirror.NONE; + }; + + String rotation = getOrDefault(map.get("rotation"), ""); + StructureRotation bedrockRotation = switch (rotation) { + case "CLOCKWISE_90" -> StructureRotation.ROTATE_90; + case "CLOCKWISE_180" -> StructureRotation.ROTATE_180; + case "COUNTERCLOCKWISE_90" -> StructureRotation.ROTATE_270; + default -> StructureRotation.NONE; + }; + + String name = getOrDefault(map.get("name"), ""); + int sizeX = getOrDefault(map.get("sizeX"), 0); + int sizeY = getOrDefault(map.get("sizeY"), 0); + int sizeZ = getOrDefault(map.get("sizeZ"), 0); + + session.getStructureBlockCache().setCurrentStructureBlock(null); + + Vector3i size = Vector3i.from(sizeX, sizeY, sizeZ); + if (size.equals(Vector3i.ZERO)) { + StructureBlockUtils.sendEmptyStructureData(session); + return; + } + + Vector3i offset = StructureBlockUtils.calculateOffset(bedrockRotation, bedrockMirror, + sizeX, sizeZ); + session.getStructureBlockCache().setBedrockOffset(offset); + session.getStructureBlockCache().setCurrentStructureName(name); + StructureBlockUtils.sendStructureData(session, size, name); + } + } + + + protected T getOrDefault(Tag tag, T defaultValue) { + //noinspection unchecked + return (tag != null && tag.getValue() != null) ? (T) tag.getValue() : defaultValue; } } diff --git a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java index 30b2907cc..25976f0f5 100644 --- a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java @@ -125,7 +125,7 @@ public class InventoryUtils { InventoryTranslator translator = session.getInventoryTranslator(); translator.closeInventory(session, inventory); if (confirm && inventory.isDisplayed() && !inventory.isPending() - && !(translator instanceof LecternInventoryTranslator) // TODO: double-check + && !(translator instanceof LecternInventoryTranslator) // Closing lecterns is not followed with a close confirmation ) { session.setClosingInventory(true); } diff --git a/core/src/main/java/org/geysermc/geyser/util/StructureBlockUtils.java b/core/src/main/java/org/geysermc/geyser/util/StructureBlockUtils.java new file mode 100644 index 000000000..9b3cfb53f --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/util/StructureBlockUtils.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2019-2024 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.util; + +import com.github.steveice10.mc.protocol.data.game.inventory.UpdateStructureBlockAction; +import com.github.steveice10.mc.protocol.data.game.inventory.UpdateStructureBlockMode; +import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundSetStructureBlockPacket; +import org.cloudburstmc.math.vector.Vector3i; +import org.cloudburstmc.nbt.NbtList; +import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtMapBuilder; +import org.cloudburstmc.nbt.NbtType; +import org.cloudburstmc.protocol.bedrock.data.structure.StructureMirror; +import org.cloudburstmc.protocol.bedrock.data.structure.StructureRotation; +import org.cloudburstmc.protocol.bedrock.data.structure.StructureSettings; +import org.cloudburstmc.protocol.bedrock.data.structure.StructureTemplateResponseType; +import org.cloudburstmc.protocol.bedrock.packet.StructureTemplateDataResponsePacket; +import org.geysermc.geyser.session.GeyserSession; + +public class StructureBlockUtils { + + private static final NbtMap EMPTY_STRUCTURE_DATA; + + static { + NbtMapBuilder builder = NbtMap.builder(); + builder.putInt("format_version", 1); + builder.putCompound("structure", NbtMap.builder() + .putList("block_indices", NbtType.LIST, NbtList.EMPTY, NbtList.EMPTY) + .putList("entities", NbtType.COMPOUND) + .putCompound("palette", NbtMap.EMPTY) + .build()); + builder.putList("structure_world_origin", NbtType.INT, 0, 0, 0); + EMPTY_STRUCTURE_DATA = builder.build(); + } + + public static void sendEmptyStructureData(GeyserSession session) { + StructureTemplateDataResponsePacket responsePacket = new StructureTemplateDataResponsePacket(); + responsePacket.setName(""); + responsePacket.setSave(false); + responsePacket.setType(StructureTemplateResponseType.QUERY); + session.sendUpstreamPacket(responsePacket); + } + + public static void sendStructureData(GeyserSession session,Vector3i size, String name) { + StructureTemplateDataResponsePacket responsePacket = new StructureTemplateDataResponsePacket(); + responsePacket.setName(name); + responsePacket.setSave(true); + responsePacket.setTag(EMPTY_STRUCTURE_DATA.toBuilder() + // Bedrock does not like negative sizes here + .putList("size", NbtType.INT, Math.abs(size.getX()), size.getY(), Math.abs(size.getZ())) + .build()); + responsePacket.setType(StructureTemplateResponseType.QUERY); + session.sendUpstreamPacket(responsePacket); + } + + public static Vector3i calculateOffset(StructureRotation structureRotation, StructureMirror structureMirror, + int sizeX, int sizeZ) { + int newOffsetX = 0; + int newOffsetZ = 0; + + switch (structureRotation) { + case ROTATE_90 -> { + switch (structureMirror) { + case NONE -> newOffsetX -= sizeZ - 1; + case X -> { + newOffsetZ -= sizeX - 1; + newOffsetX -= sizeZ - 1; + } + } + } + case ROTATE_180 -> { + switch (structureMirror) { + case NONE -> { + newOffsetX -= sizeX - 1; + newOffsetZ -= sizeZ - 1; + } + case Z -> newOffsetX -= sizeX - 1; + case X -> newOffsetZ -= sizeZ - 1; + } + } + case ROTATE_270 -> { + switch (structureMirror) { + case NONE -> newOffsetZ -= sizeX - 1; + case Z -> { + newOffsetZ -= sizeX - 1; + newOffsetX -= sizeZ - 1; + } + } + } + default -> { + switch (structureMirror) { + case Z -> newOffsetZ -= sizeZ - 1; + case X -> newOffsetX -= sizeX - 1; + } + } + } + + return Vector3i.from(newOffsetX, 0, newOffsetZ); + } + + public static void sendJavaStructurePacket(GeyserSession session, Vector3i blockPosition, Vector3i size, UpdateStructureBlockMode mode, UpdateStructureBlockAction action, + StructureSettings settings, boolean boundingBoxVisible, String structureName) { + + com.github.steveice10.mc.protocol.data.game.level.block.StructureMirror mirror = switch (settings.getMirror()) { + case X -> com.github.steveice10.mc.protocol.data.game.level.block.StructureMirror.FRONT_BACK; + case Z -> com.github.steveice10.mc.protocol.data.game.level.block.StructureMirror.LEFT_RIGHT; + default -> com.github.steveice10.mc.protocol.data.game.level.block.StructureMirror.NONE; + }; + + com.github.steveice10.mc.protocol.data.game.level.block.StructureRotation rotation = switch (settings.getRotation()) { + case ROTATE_90 -> com.github.steveice10.mc.protocol.data.game.level.block.StructureRotation.CLOCKWISE_90; + case ROTATE_180 -> com.github.steveice10.mc.protocol.data.game.level.block.StructureRotation.CLOCKWISE_180; + case ROTATE_270 -> com.github.steveice10.mc.protocol.data.game.level.block.StructureRotation.COUNTERCLOCKWISE_90; + default -> com.github.steveice10.mc.protocol.data.game.level.block.StructureRotation.NONE; + }; + + Vector3i offset = settings.getOffset(); + if (session.getStructureBlockCache().getBedrockOffset() != null) { + offset = settings.getOffset().sub(session.getStructureBlockCache().getBedrockOffset()); + } + + ServerboundSetStructureBlockPacket structureBlockPacket = new ServerboundSetStructureBlockPacket( + blockPosition, + action, + mode, + structureName, + offset, + settings.getSize(), + mirror, + rotation, + "", + settings.getIntegrityValue(), + settings.getIntegritySeed(), + settings.isIgnoringEntities(), + false, + boundingBoxVisible + ); + + session.sendDownstreamPacket(structureBlockPacket); + } +} From 576a1b7d7a6360bfffc4923c708446f4a92f7c96 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Wed, 17 Apr 2024 17:53:56 -0400 Subject: [PATCH 238/344] Remove map cache (#4576) --- .../geyser/session/GeyserSession.java | 2 - .../BedrockMapInfoRequestTranslator.java | 50 ------------------- .../java/level/JavaMapItemDataTranslator.java | 17 ++----- 3 files changed, 5 insertions(+), 64 deletions(-) delete mode 100644 core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockMapInfoRequestTranslator.java diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index c0749400a..2a7b9b3fc 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -262,8 +262,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { @Setter private ItemMappings itemMappings; - private final Long2ObjectMap storedMaps = new Long2ObjectOpenHashMap<>(); - /** * Required to decode biomes correctly. */ diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockMapInfoRequestTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockMapInfoRequestTranslator.java deleted file mode 100644 index 3e885b63f..000000000 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockMapInfoRequestTranslator.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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.translator.protocol.bedrock; - -import org.cloudburstmc.protocol.bedrock.packet.ClientboundMapItemDataPacket; -import org.cloudburstmc.protocol.bedrock.packet.MapInfoRequestPacket; -import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.translator.protocol.PacketTranslator; -import org.geysermc.geyser.translator.protocol.Translator; - -import java.util.concurrent.TimeUnit; - -@Translator(packet = MapInfoRequestPacket.class) -public class BedrockMapInfoRequestTranslator extends PacketTranslator { - - @Override - public void translate(GeyserSession session, MapInfoRequestPacket packet) { - long mapId = packet.getUniqueMapId(); - - ClientboundMapItemDataPacket mapPacket = session.getStoredMaps().remove(mapId); - if (mapPacket != null) { - // Delay the packet 100ms to prevent the client from ignoring the packet - session.scheduleInEventLoop(() -> session.sendUpstreamPacket(mapPacket), - 100, TimeUnit.MILLISECONDS); - } - } -} diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaMapItemDataTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaMapItemDataTranslator.java index 34fbf2d9c..01b0f324f 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaMapItemDataTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaMapItemDataTranslator.java @@ -44,7 +44,6 @@ public class JavaMapItemDataTranslator extends PacketTranslator Date: Thu, 18 Apr 2024 00:16:41 -0400 Subject: [PATCH 239/344] Reset metadata and attributes if needed when respawning (#4566) * Reset metadata and attributes if needed when respawning * Minor edits * Reset attributes in JavaLoginTranslator * Fix client bug when updating absorption and health in the same tick --- .../entity/attribute/GeyserAttributeType.java | 6 ++- .../entity/type/player/PlayerEntity.java | 5 ++- .../type/player/SessionPlayerEntity.java | 39 +++++++++++++++++++ .../geyser/session/GeyserSession.java | 2 +- .../protocol/java/JavaLoginTranslator.java | 2 +- .../protocol/java/JavaRespawnTranslator.java | 8 ++++ 6 files changed, 57 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/entity/attribute/GeyserAttributeType.java b/core/src/main/java/org/geysermc/geyser/entity/attribute/GeyserAttributeType.java index 234c1afe9..88d493275 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/attribute/GeyserAttributeType.java +++ b/core/src/main/java/org/geysermc/geyser/entity/attribute/GeyserAttributeType.java @@ -51,7 +51,7 @@ public enum GeyserAttributeType { MAX_HEALTH("minecraft:generic.max_health", null, 0f, 1024f, 20f), // Bedrock Attributes - ABSORPTION(null, "minecraft:absorption", 0f, Float.MAX_VALUE, 0f), + ABSORPTION(null, "minecraft:absorption", 0f, 1024f, 0f), EXHAUSTION(null, "minecraft:player.exhaustion", 0f, 5f, 0f), EXPERIENCE(null, "minecraft:player.experience", 0f, 1f, 0f), EXPERIENCE_LEVEL(null, "minecraft:player.level", 0f, 24791.00f, 0f), @@ -66,6 +66,10 @@ public enum GeyserAttributeType { private final float maximum; private final float defaultValue; + public AttributeData getAttribute() { + return getAttribute(defaultValue); + } + public AttributeData getAttribute(float value) { return getAttribute(value, maximum); } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java index 9e3888138..20819f75e 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java @@ -55,6 +55,7 @@ import org.cloudburstmc.protocol.bedrock.packet.SetEntityLinkPacket; import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket; import org.geysermc.geyser.api.entity.type.player.GeyserPlayerEntity; import org.geysermc.geyser.entity.EntityDefinitions; +import org.geysermc.geyser.entity.attribute.GeyserAttributeType; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.LivingEntity; import org.geysermc.geyser.entity.type.living.animal.tameable.ParrotEntity; @@ -283,7 +284,7 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity { attributesPacket.setRuntimeEntityId(geyserId); // Setting to a higher maximum since plugins/datapacks can probably extend the Bedrock soft limit attributesPacket.setAttributes(Collections.singletonList( - new AttributeData("minecraft:absorption", 0.0f, 1024f, entityMetadata.getPrimitiveValue(), 0.0f))); + GeyserAttributeType.ABSORPTION.getAttribute(entityMetadata.getPrimitiveValue()))); session.sendUpstreamPacket(attributesPacket); } @@ -307,7 +308,7 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity { * Sets the parrot occupying the shoulder. Bedrock Edition requires a full entity whereas Java Edition just * spawns it from the NBT data provided */ - private void setParrot(CompoundTag tag, boolean isLeft) { + protected void setParrot(CompoundTag tag, boolean isLeft) { if (tag != null && !tag.isEmpty()) { if ((isLeft && leftParrot != null) || (!isLeft && rightParrot != null)) { // No need to update a parrot's data when it already exists diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java index 751a24871..89aa540d8 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java @@ -30,6 +30,7 @@ import com.github.steveice10.mc.protocol.data.game.entity.attribute.AttributeTyp import com.github.steveice10.mc.protocol.data.game.entity.metadata.GlobalPos; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose; import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.FloatEntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import lombok.Getter; @@ -255,13 +256,51 @@ public class SessionPlayerEntity extends PlayerEntity { return session.getAuthData().uuid(); } + @Override + public void setAbsorptionHearts(FloatEntityMetadata entityMetadata) { + // The bedrock client can glitch when sending a health and absorption attribute in the same tick + // This can happen when switching servers. Resending the absorption attribute fixes the issue + attributes.put(GeyserAttributeType.ABSORPTION, GeyserAttributeType.ABSORPTION.getAttribute(entityMetadata.getPrimitiveValue())); + super.setAbsorptionHearts(entityMetadata); + } + public void resetMetadata() { // Reset all metadata to their default values // This is used when a player respawns + this.flags.clear(); this.initializeMetadata(); // Reset air this.resetAir(); + + // Explicitly reset all metadata not handled by initializeMetadata + setParrot(null, true); + setParrot(null, false); + + // Absorption is metadata in java edition + attributes.remove(GeyserAttributeType.ABSORPTION); + UpdateAttributesPacket attributesPacket = new UpdateAttributesPacket(); + attributesPacket.setRuntimeEntityId(geyserId); + attributesPacket.setAttributes(Collections.singletonList( + GeyserAttributeType.ABSORPTION.getAttribute(0f))); + session.sendUpstreamPacket(attributesPacket); + + dirtyMetadata.put(EntityDataTypes.EFFECT_COLOR, 0); + dirtyMetadata.put(EntityDataTypes.EFFECT_AMBIENCE, (byte) 0); + dirtyMetadata.put(EntityDataTypes.FREEZING_EFFECT_STRENGTH, 0f); + + silent = false; + } + + public void resetAttributes() { + attributes.clear(); + maxHealth = GeyserAttributeType.MAX_HEALTH.getDefaultValue(); + + UpdateAttributesPacket attributesPacket = new UpdateAttributesPacket(); + attributesPacket.setRuntimeEntityId(geyserId); + attributesPacket.setAttributes(Collections.singletonList( + GeyserAttributeType.MOVEMENT_SPEED.getAttribute())); + session.sendUpstreamPacket(attributesPacket); } public void resetAir() { diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 2a7b9b3fc..aff21182e 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -712,7 +712,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { // Default move speed // Bedrock clients move very fast by default until they get an attribute packet correcting the speed attributesPacket.setAttributes(Collections.singletonList( - new AttributeData("minecraft:movement", 0.0f, 1024f, 0.1f, 0.1f))); + GeyserAttributeType.MOVEMENT_SPEED.getAttribute())); upstream.sendPacket(attributesPacket); GameRulesChangedPacket gamerulePacket = new GameRulesChangedPacket(); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java index 23c19e84f..4a15157f9 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java @@ -71,7 +71,7 @@ public class JavaLoginTranslator extends PacketTranslator Date: Thu, 18 Apr 2024 07:29:40 -0700 Subject: [PATCH 240/344] Update release for preview builds (#4575) --- .github/workflows/build.yml | 47 +++++++++++++++----- .github/workflows/preview.yml | 73 +++++++++++++++++++++++++++++++ .github/workflows/pullrequest.yml | 18 ++++++++ 3 files changed, 127 insertions(+), 11 deletions(-) create mode 100644 .github/workflows/preview.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1d70d9948..c7b439182 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,6 +8,7 @@ on: paths-ignore: - '.github/ISSUE_TEMPLATE/*.yml' - '.github/actions/pullrequest.yml' + - '.github/actions/preview.yml' - '.idea/copyright/*.xml' - '.gitignore' - 'CONTRIBUTING.md' @@ -19,6 +20,8 @@ on: jobs: build: runs-on: ubuntu-latest + env: + PROJECT: 'geyser' steps: - name: Checkout repository and submodules # See https://github.com/actions/checkout/commits @@ -103,6 +106,34 @@ jobs: with: arguments: publish + - name: Get Release Metadata + if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} + uses: Kas-tle/base-release-action@b863fa0f89bd15267a96a72efb84aec25f168d4c # https://github.com/Kas-tle/base-release-action/releases/tag/main-11 + with: + appID: ${{ secrets.RELEASE_APP_ID }} + appPrivateKey: ${{ secrets.RELEASE_APP_PK }} + files: | + bungeecord:bootstrap/bungeecord/build/libs/Geyser-BungeeCord.jar + fabric:bootstrap/mod/fabric/build/libs/Geyser-Fabric.jar + neoforge:bootstrap/mod/neoforge/build/libs/Geyser-NeoForge.jar + spigot:bootstrap/spigot/build/libs/Geyser-Spigot.jar + standalone:bootstrap/standalone/build/libs/Geyser-Standalone.jar + velocity:bootstrap/velocity/build/libs/Geyser-Velocity.jar + viaproxy:bootstrap/viaproxy/build/libs/Geyser-ViaProxy.jar + releaseEnabled: false + saveMetadata: true + - name: Update Generated Metadata + if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} + run: | + cat metadata.json + echo + version=$(cat gradle.properties | grep -o "version=[0-9\\.]*" | cut -d"=" -f2) + cat metadata.json | jq --arg project "${PROJECT}" --arg version "${version}" ' + . + | .changes |= map({"commit", "summary", "message"}) + | .downloads |= map_values({"name", "sha256"}) + | {$project, "repo", $version, "number": .build, "changes", "downloads"} + ' | tee metadata.json - name: Publish to Downloads API if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} shell: bash @@ -114,19 +145,13 @@ jobs: # Save the private key to a file echo "$DOWNLOADS_PRIVATE_KEY" > id_ecdsa chmod 600 id_ecdsa - # Set the project - project=geyser - # Get the version from gradle.properties - version=$(cat gradle.properties | grep -o "version=[0-9\\.]*" | cut -d"=" -f2) # Create the build folder - ssh -o StrictHostKeyChecking=no -i id_ecdsa $DOWNLOADS_USERNAME@$DOWNLOADS_SERVER_IP mkdir -p "~/uploads/$project/$GITHUB_RUN_NUMBER/" + ssh -o StrictHostKeyChecking=no -i id_ecdsa $DOWNLOADS_USERNAME@$DOWNLOADS_SERVER_IP mkdir -p "~/uploads/$PROJECT/$GITHUB_RUN_NUMBER/" # Copy over artifacts - rsync -P -e "ssh -o StrictHostKeyChecking=no -i id_ecdsa" bootstrap/**/build/libs/Geyser-*.jar $DOWNLOADS_USERNAME@$DOWNLOADS_SERVER_IP:~/uploads/$project/$GITHUB_RUN_NUMBER/ - rsync -P -e "ssh -o StrictHostKeyChecking=no -i id_ecdsa" bootstrap/mod/**/build/libs/Geyser-*.jar $DOWNLOADS_USERNAME@$DOWNLOADS_SERVER_IP:~/uploads/$project/$GITHUB_RUN_NUMBER/ + rsync -P -e "ssh -o StrictHostKeyChecking=no -i id_ecdsa" bootstrap/**/build/libs/Geyser-*.jar $DOWNLOADS_USERNAME@$DOWNLOADS_SERVER_IP:~/uploads/$PROJECT/$GITHUB_RUN_NUMBER/ + rsync -P -e "ssh -o StrictHostKeyChecking=no -i id_ecdsa" bootstrap/mod/**/build/libs/Geyser-*.jar $DOWNLOADS_USERNAME@$DOWNLOADS_SERVER_IP:~/uploads/$PROJECT/$GITHUB_RUN_NUMBER/ # Run the build script - # Push the metadata - echo "{\"project\": \"$project\", \"version\": \"$version\", \"id\": $GITHUB_RUN_NUMBER, \"commit\": \"$GITHUB_SHA\"}" > metadata.json - rsync -P -e "ssh -o StrictHostKeyChecking=no -i id_ecdsa" metadata.json $DOWNLOADS_USERNAME@$DOWNLOADS_SERVER_IP:~/uploads/$project/$GITHUB_RUN_NUMBER/ + rsync -P -e "ssh -o StrictHostKeyChecking=no -i id_ecdsa" metadata.json $DOWNLOADS_USERNAME@$DOWNLOADS_SERVER_IP:~/uploads/$PROJECT/$GITHUB_RUN_NUMBER/ - name: Publish to Modrinth (Fabric) uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 @@ -152,4 +177,4 @@ jobs: uses: Tim203/actions-git-discord-webhook@70f38ded3aca51635ec978ab4e1a58cd4cd0c2ff with: webhook_url: ${{ secrets.DISCORD_WEBHOOK }} - status: ${{ job.status }} + status: ${{ job.status }} \ No newline at end of file diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml new file mode 100644 index 000000000..794ade4d4 --- /dev/null +++ b/.github/workflows/preview.yml @@ -0,0 +1,73 @@ +name: Upload Preview + +on: + workflow_dispatch: + inputs: + runId: + required: true + description: 'ID of the action to pull artifacts from' + build: + required: true + description: 'Build number for the release' + version: + required: true + description: 'Version under which to upload to the Downloads API' + +jobs: + upload: + runs-on: ubuntu-latest + env: + PROJECT: 'geyser-preview' + BUILD: ${{ github.event.inputs.build }} + VERSION: ${{ github.event.inputs.version }} + steps: + - uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # https://github.com/actions/download-artifact/releases/tag/v4.1.4 + with: + run-id: ${{ github.event.inputs.runId }} + github-token: ${{ secrets.GITHUB_TOKEN }} + merge-multiple: true + - name: Get Preview Metadata + if: success() + uses: Kas-tle/base-release-action@b863fa0f89bd15267a96a72efb84aec25f168d4c # https://github.com/Kas-tle/base-release-action/releases/tag/main-11 + with: + appID: ${{ secrets.RELEASE_APP_ID }} + appPrivateKey: ${{ secrets.RELEASE_APP_PK }} + files: | + bungeecord:Geyser-BungeeCord.jar + fabric:Geyser-Fabric.jar + neoforge:Geyser-NeoForge.jar + spigot:Geyser-Spigot.jar + standalone:Geyser-Standalone.jar + velocity:Geyser-Velocity.jar + viaproxy:Geyser-ViaProxy.jar + releaseEnabled: false + saveMetadata: true + updateReleaseData: false + - name: Update Generated Metadata + if: success() + run: | + cat metadata.json + echo + cat metadata.json | jq --arg project "${PROJECT}" --arg version "${VERSION}" --arg number "${BUILD}" ' + . + | .downloads |= map_values({"name", "sha256"}) + | {$project, "repo", $version, "number": $number | tonumber, "changes": [], "downloads"} + ' | tee metadata.json + - name: Publish to Downloads API + if: success() + shell: bash + env: + DOWNLOADS_USERNAME: ${{ vars.DOWNLOADS_USERNAME }} + DOWNLOADS_PRIVATE_KEY: ${{ secrets.DOWNLOADS_PRIVATE_KEY }} + DOWNLOADS_SERVER_IP: ${{ secrets.DOWNLOADS_SERVER_IP }} + run: | + # Save the private key to a file + echo "$DOWNLOADS_PRIVATE_KEY" > id_ecdsa + chmod 600 id_ecdsa + # Create the build folder + ssh -o StrictHostKeyChecking=no -i id_ecdsa $DOWNLOADS_USERNAME@$DOWNLOADS_SERVER_IP mkdir -p "~/uploads/$PROJECT/$BUILD/" + # Copy over artifacts + rsync -P -e "ssh -o StrictHostKeyChecking=no -i id_ecdsa" Geyser-*.jar $DOWNLOADS_USERNAME@$DOWNLOADS_SERVER_IP:~/uploads/$PROJECT/$BUILD/ + # Run the build script + # Push the metadata + rsync -P -e "ssh -o StrictHostKeyChecking=no -i id_ecdsa" metadata.json $DOWNLOADS_USERNAME@$DOWNLOADS_SERVER_IP:~/uploads/$PROJECT/$BUILD/ \ No newline at end of file diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 93be4711e..18223e7dc 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -102,3 +102,21 @@ jobs: name: Geyser ViaProxy path: geyser/bootstrap/viaproxy/build/libs/Geyser-ViaProxy.jar if-no-files-found: error + + - name: Trigger Preview Deployment + if: >- + contains(github.event.pull_request.labels.*.name, 'PR: Needs Testing') + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea + with: + script: | + github.rest.actions.createWorkflowDispatch({ + owner: context.repo.owner, + repo: context.repo.repo, + workflow_id: 'preview.yml', + ref: 'master', + inputs: { + runId: '${{ github.run_id }}', + build: '${{ github.run_number }}', + version: 'pr.${{ github.event.pull_request.number }}' + } + }); \ No newline at end of file From ae96ad2ec4afd81a7c1478ea8f52c10af0350ab0 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Thu, 18 Apr 2024 17:18:05 +0100 Subject: [PATCH 241/344] Change preview builds project --- .github/workflows/preview.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index 794ade4d4..a2955a081 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -17,7 +17,7 @@ jobs: upload: runs-on: ubuntu-latest env: - PROJECT: 'geyser-preview' + PROJECT: 'geyserpreview' BUILD: ${{ github.event.inputs.build }} VERSION: ${{ github.event.inputs.version }} steps: @@ -70,4 +70,4 @@ jobs: rsync -P -e "ssh -o StrictHostKeyChecking=no -i id_ecdsa" Geyser-*.jar $DOWNLOADS_USERNAME@$DOWNLOADS_SERVER_IP:~/uploads/$PROJECT/$BUILD/ # Run the build script # Push the metadata - rsync -P -e "ssh -o StrictHostKeyChecking=no -i id_ecdsa" metadata.json $DOWNLOADS_USERNAME@$DOWNLOADS_SERVER_IP:~/uploads/$PROJECT/$BUILD/ \ No newline at end of file + rsync -P -e "ssh -o StrictHostKeyChecking=no -i id_ecdsa" metadata.json $DOWNLOADS_USERNAME@$DOWNLOADS_SERVER_IP:~/uploads/$PROJECT/$BUILD/ From 0cc2921eda30e2fe44951d1886bdb7ec6c3acbdf Mon Sep 17 00:00:00 2001 From: ookiegajwa <91029880+ookiegajwa@users.noreply.github.com> Date: Thu, 18 Apr 2024 20:23:33 -0500 Subject: [PATCH 242/344] Translate scoreboard display name and number format (#4567) The following caveats apply because selectively removing or modifying the score numbers on Bedrock cannot be done without removing all of them: * "blank" and "styled" number formats are ignored for "list" and "sidebar" display slots * The "fixed" number format is appended to the end of the "list" and "sidebar" entry names instead of replacing the score number * The "below_name" slot has no limitations and displays identically to Java --- .../entity/type/player/PlayerEntity.java | 54 +++++++++++++--- .../geysermc/geyser/scoreboard/Objective.java | 34 +++++++++- .../org/geysermc/geyser/scoreboard/Score.java | 62 ++++++++++++++++++- .../geyser/scoreboard/Scoreboard.java | 4 +- .../java/scoreboard/JavaResetScorePacket.java | 4 +- .../JavaSetObjectiveTranslator.java | 16 ++++- .../scoreboard/JavaSetScoreTranslator.java | 18 ++---- 7 files changed, 157 insertions(+), 35 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java index 20819f75e..b957a0243 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java @@ -25,6 +25,11 @@ package org.geysermc.geyser.entity.type.player; +import com.github.steveice10.mc.protocol.codec.NbtComponentSerializer; +import com.github.steveice10.mc.protocol.data.game.chat.numbers.BlankFormat; +import com.github.steveice10.mc.protocol.data.game.chat.numbers.FixedFormat; +import com.github.steveice10.mc.protocol.data.game.chat.numbers.NumberFormat; +import com.github.steveice10.mc.protocol.data.game.chat.numbers.StyledFormat; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose; import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; @@ -33,6 +38,7 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.FloatEnt import com.github.steveice10.mc.protocol.data.game.scoreboard.ScoreboardPosition; import com.github.steveice10.mc.protocol.data.game.scoreboard.TeamColor; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.StringTag; import lombok.Getter; import lombok.Setter; import net.kyori.adventure.text.Component; @@ -64,6 +70,7 @@ import org.geysermc.geyser.scoreboard.Score; import org.geysermc.geyser.scoreboard.Team; import org.geysermc.geyser.scoreboard.UpdateType; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.util.ChunkUtils; @@ -415,14 +422,36 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity { public void setBelowNameText(Objective objective) { if (objective != null && objective.getUpdateType() != UpdateType.REMOVE) { - int amount; Score score = objective.getScores().get(username); + String numberString; + NumberFormat numberFormat; + int amount; if (score != null) { - amount = score.getCurrentData().getScore(); + amount = score.getScore(); + numberFormat = score.getNumberFormat(); + if (numberFormat == null) { + numberFormat = objective.getNumberFormat(); + } } else { amount = 0; + numberFormat = objective.getNumberFormat(); } - String displayString = amount + " " + objective.getDisplayName(); + + if (numberFormat instanceof BlankFormat) { + numberString = ""; + } else if (numberFormat instanceof FixedFormat fixedFormat) { + numberString = MessageTranslator.convertMessage(fixedFormat.getValue()); + } else if (numberFormat instanceof StyledFormat styledFormat) { + CompoundTag styledAmount = styledFormat.getStyle().clone(); + styledAmount.put(new StringTag("text", String.valueOf(amount))); + + numberString = MessageTranslator.convertJsonMessage( + NbtComponentSerializer.tagComponentToJson(styledAmount).toString()); + } else { + numberString = String.valueOf(amount); + } + + String displayString = numberString + " " + ChatColor.RESET + objective.getDisplayName(); if (valid) { // Already spawned - we still need to run the rest of this code because the spawn packet will be @@ -431,13 +460,22 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity { packet.setRuntimeEntityId(geyserId); packet.getMetadata().put(EntityDataTypes.SCORE, displayString); session.sendUpstreamPacket(packet); + } else { + // Not spawned yet, store score value in dirtyMetadata to be picked up by #spawnEntity + dirtyMetadata.put(EntityDataTypes.SCORE, displayString); + } + } else { + if (valid) { + SetEntityDataPacket packet = new SetEntityDataPacket(); + packet.setRuntimeEntityId(geyserId); + packet.getMetadata().put(EntityDataTypes.SCORE, ""); + session.sendUpstreamPacket(packet); + } else { + // Not spawned yet, store score value in dirtyMetadata to be picked up by #spawnEntity + dirtyMetadata.put(EntityDataTypes.SCORE, ""); } - } else if (valid) { - SetEntityDataPacket packet = new SetEntityDataPacket(); - packet.setRuntimeEntityId(geyserId); - packet.getMetadata().put(EntityDataTypes.SCORE, ""); - session.sendUpstreamPacket(packet); } + } /** diff --git a/core/src/main/java/org/geysermc/geyser/scoreboard/Objective.java b/core/src/main/java/org/geysermc/geyser/scoreboard/Objective.java index fd9e0fbf3..c00c69660 100644 --- a/core/src/main/java/org/geysermc/geyser/scoreboard/Objective.java +++ b/core/src/main/java/org/geysermc/geyser/scoreboard/Objective.java @@ -25,13 +25,16 @@ package org.geysermc.geyser.scoreboard; +import com.github.steveice10.mc.protocol.data.game.chat.numbers.NumberFormat; import com.github.steveice10.mc.protocol.data.game.scoreboard.ScoreboardPosition; import com.github.steveice10.mc.protocol.data.game.scoreboard.TeamColor; import lombok.Getter; import lombok.Setter; +import net.kyori.adventure.text.Component; import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Map; +import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; @Getter @@ -47,6 +50,7 @@ public final class Objective { private ScoreboardPosition displaySlot; private String displaySlotName; private String displayName = "unknown"; + private NumberFormat numberFormat; private int type = 0; // 0 = integer, 1 = heart private Map scores = new ConcurrentHashMap<>(); @@ -85,25 +89,29 @@ public final class Objective { }; } - public void registerScore(String id, int score) { + public void registerScore(String id, int score, Component displayName, NumberFormat numberFormat) { if (!scores.containsKey(id)) { long scoreId = scoreboard.getNextId().getAndIncrement(); Score scoreObject = new Score(scoreId, id) .setScore(score) .setTeam(scoreboard.getTeamFor(id)) + .setDisplayName(displayName) + .setNumberFormat(numberFormat) .setUpdateType(UpdateType.ADD); scores.put(id, scoreObject); } } - public void setScore(String id, int score) { + public void setScore(String id, int score, Component displayName, NumberFormat numberFormat) { Score stored = scores.get(id); if (stored != null) { stored.setScore(score) + .setDisplayName(displayName) + .setNumberFormat(numberFormat) .setUpdateType(UpdateType.UPDATE); return; } - registerScore(id, score); + registerScore(id, score, displayName, numberFormat); } public void removeScore(String id) { @@ -128,6 +136,26 @@ public final class Objective { return this; } + public Objective setNumberFormat(NumberFormat numberFormat) { + if (Objects.equals(this.numberFormat, numberFormat)) { + return this; + } + + this.numberFormat = numberFormat; + if (updateType == UpdateType.NOTHING) { + updateType = UpdateType.UPDATE; + } + + // Update the number format for scores that are following this objective's number format + for (Score score : scores.values()) { + if (score.getNumberFormat() == null) { + score.setUpdateType(UpdateType.UPDATE); + } + } + + return this; + } + public Objective setType(int type) { this.type = type; if (updateType == UpdateType.NOTHING) { diff --git a/core/src/main/java/org/geysermc/geyser/scoreboard/Score.java b/core/src/main/java/org/geysermc/geyser/scoreboard/Score.java index 0a6623e97..ec17818c4 100644 --- a/core/src/main/java/org/geysermc/geyser/scoreboard/Score.java +++ b/core/src/main/java/org/geysermc/geyser/scoreboard/Score.java @@ -25,9 +25,16 @@ package org.geysermc.geyser.scoreboard; +import com.github.steveice10.mc.protocol.data.game.chat.numbers.FixedFormat; +import com.github.steveice10.mc.protocol.data.game.chat.numbers.NumberFormat; +import net.kyori.adventure.text.Component; import org.cloudburstmc.protocol.bedrock.data.ScoreInfo; import lombok.Getter; import lombok.experimental.Accessors; +import org.geysermc.geyser.text.ChatColor; +import org.geysermc.geyser.translator.text.MessageTranslator; + +import java.util.Objects; @Getter @Accessors(chain = true) @@ -52,6 +59,10 @@ public final class Score { } public String getDisplayName() { + String displayName = cachedData.displayName; + if (displayName != null) { + return displayName; + } Team team = cachedData.team; if (team != null) { return team.getDisplayName(name); @@ -88,6 +99,35 @@ public final class Score { return this; } + public Score setDisplayName(Component displayName) { + if (currentData.displayName != null && displayName != null) { + String convertedDisplayName = MessageTranslator.convertMessage(displayName); + if (!currentData.displayName.equals(convertedDisplayName)) { + currentData.displayName = convertedDisplayName; + setUpdateType(UpdateType.UPDATE); + } + return this; + } + // simplified from (this.displayName != null && displayName == null) || (this.displayName == null && displayName != null) + if (currentData.displayName != null || displayName != null) { + currentData.displayName = MessageTranslator.convertMessage(displayName); + setUpdateType(UpdateType.UPDATE); + } + return this; + } + + public NumberFormat getNumberFormat() { + return currentData.numberFormat; + } + + public Score setNumberFormat(NumberFormat numberFormat) { + if (!Objects.equals(currentData.numberFormat, numberFormat)) { + currentData.numberFormat = numberFormat; + setUpdateType(UpdateType.UPDATE); + } + return this; + } + public UpdateType getUpdateType() { return currentData.updateType; } @@ -105,7 +145,7 @@ public final class Score { (currentData.team != null && currentData.team.shouldUpdate()); } - public void update(String objectiveName) { + public void update(Objective objective) { if (cachedData == null) { cachedData = new ScoreData(); cachedData.updateType = UpdateType.ADD; @@ -119,13 +159,26 @@ public final class Score { currentData.changed = false; cachedData.team = currentData.team; cachedData.score = currentData.score; + cachedData.displayName = currentData.displayName; + cachedData.numberFormat = currentData.numberFormat; String name = this.name; - if (cachedData.team != null) { + if (cachedData.displayName != null) { + name = cachedData.displayName; + } else if (cachedData.team != null) { cachedData.team.prepareUpdate(); name = cachedData.team.getDisplayName(name); } - cachedInfo = new ScoreInfo(id, objectiveName, cachedData.score, name); + + NumberFormat numberFormat = cachedData.numberFormat; + if (numberFormat == null) { + numberFormat = objective.getNumberFormat(); + } + if (numberFormat instanceof FixedFormat fixedFormat) { + name += " " + ChatColor.RESET + MessageTranslator.convertMessage(fixedFormat.getValue()); + } + + cachedInfo = new ScoreInfo(id, objective.getObjectiveName(), cachedData.score, name); } @Getter @@ -136,6 +189,9 @@ public final class Score { private Team team; private int score; + private String displayName; + private NumberFormat numberFormat; + private ScoreData() { updateType = UpdateType.ADD; } diff --git a/core/src/main/java/org/geysermc/geyser/scoreboard/Scoreboard.java b/core/src/main/java/org/geysermc/geyser/scoreboard/Scoreboard.java index 216370bde..dfd74a79e 100644 --- a/core/src/main/java/org/geysermc/geyser/scoreboard/Scoreboard.java +++ b/core/src/main/java/org/geysermc/geyser/scoreboard/Scoreboard.java @@ -240,7 +240,7 @@ public final class Scoreboard { boolean update = score.shouldUpdate(); if (update) { - score.update(objective.getObjectiveName()); + score.update(objective); } if (score.getUpdateType() != REMOVE && update) { @@ -281,7 +281,7 @@ public final class Scoreboard { } if (score.shouldUpdate()) { - score.update(objective.getObjectiveName()); + score.update(objective); add = true; } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaResetScorePacket.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaResetScorePacket.java index 418037760..01b4fddea 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaResetScorePacket.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaResetScorePacket.java @@ -54,7 +54,7 @@ public class JavaResetScorePacket extends PacketTranslator objective.setDisplayName(MessageTranslator.convertMessage(packet.getDisplayName())) - .setType(packet.getType().ordinal()); + case ADD, UPDATE -> { + objective.setDisplayName(MessageTranslator.convertMessage(packet.getDisplayName())) + .setNumberFormat(packet.getNumberFormat()) + .setType(packet.getType().ordinal()); + if (objective == scoreboard.getObjectiveSlots().get(ScoreboardPosition.BELOW_NAME)) { + // Update the score tag of all players + for (PlayerEntity entity : session.getEntityCache().getAllPlayerEntities()) { + if (entity.isValid()) { + entity.setBelowNameText(objective); + } + } + } + } case REMOVE -> { scoreboard.unregisterObjective(packet.getName()); if (objective != null && objective == scoreboard.getObjectiveSlots().get(ScoreboardPosition.BELOW_NAME)) { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaSetScoreTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaSetScoreTranslator.java index 594e2cbed..6bffee3d3 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaSetScoreTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaSetScoreTranslator.java @@ -28,8 +28,6 @@ package org.geysermc.geyser.translator.protocol.java.scoreboard; import com.github.steveice10.mc.protocol.data.game.scoreboard.ScoreboardPosition; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetScorePacket; import org.checkerframework.checker.nullness.qual.Nullable; -import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; -import org.cloudburstmc.protocol.bedrock.packet.SetEntityDataPacket; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserLogger; import org.geysermc.geyser.entity.type.player.PlayerEntity; @@ -54,7 +52,6 @@ public class JavaSetScoreTranslator extends PacketTranslator Date: Fri, 19 Apr 2024 05:41:06 -0400 Subject: [PATCH 243/344] Fix default wolf and cat collar color (#4582) --- .../living/animal/tameable/CatEntity.java | 11 +++++----- .../living/animal/tameable/WolfEntity.java | 22 ++++++++++++++----- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/CatEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/CatEntity.java index 412157b5d..93cb92c7d 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/CatEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/CatEntity.java @@ -45,7 +45,7 @@ import java.util.UUID; public class CatEntity extends TameableEntity { - private byte collarColor; + private byte collarColor = 14; // Red - default public CatEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); @@ -76,10 +76,7 @@ public class CatEntity extends TameableEntity { @Override public void setTameableFlags(ByteEntityMetadata entityMetadata) { super.setTameableFlags(entityMetadata); - // Update collar color if tamed - if (getFlag(EntityFlag.TAMED)) { - dirtyMetadata.put(EntityDataTypes.COLOR, collarColor); - } + updateCollarColor(); } public void setCatVariant(IntEntityMetadata entityMetadata) { @@ -101,6 +98,10 @@ public class CatEntity extends TameableEntity { public void setCollarColor(IntEntityMetadata entityMetadata) { collarColor = (byte) entityMetadata.getPrimitiveValue(); + updateCollarColor(); + } + + private void updateCollarColor() { // Needed or else wild cats are a red color if (getFlag(EntityFlag.TAMED)) { dirtyMetadata.put(EntityDataTypes.COLOR, collarColor); diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java index 0f5b36ec3..c75247fdf 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java @@ -32,6 +32,7 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; +import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.Items; @@ -41,6 +42,7 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; +import java.util.Collections; import java.util.Set; import java.util.UUID; @@ -54,7 +56,7 @@ public class WolfEntity extends TameableEntity { Items.PORKCHOP, Items.BEEF, Items.RABBIT, Items.COOKED_PORKCHOP, Items.COOKED_BEEF, Items.ROTTEN_FLESH, Items.MUTTON, Items.COOKED_MUTTON, Items.COOKED_RABBIT); - private byte collarColor; + private byte collarColor = 14; // Red - default public WolfEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); @@ -64,19 +66,27 @@ public class WolfEntity extends TameableEntity { public void setTameableFlags(ByteEntityMetadata entityMetadata) { super.setTameableFlags(entityMetadata); // Reset wolf color - byte xd = entityMetadata.getPrimitiveValue(); - boolean angry = (xd & 0x02) == 0x02; - if (angry) { + if (getFlag(EntityFlag.ANGRY)) { dirtyMetadata.put(EntityDataTypes.COLOR, (byte) 0); + } else if (getFlag(EntityFlag.TAMED)) { + updateCollarColor(); + + // This fixes tail angle when taming + UpdateAttributesPacket packet = new UpdateAttributesPacket(); + packet.setRuntimeEntityId(geyserId); + packet.setAttributes(Collections.singletonList(createHealthAttribute())); + session.sendUpstreamPacket(packet); } } public void setCollarColor(IntEntityMetadata entityMetadata) { collarColor = (byte) entityMetadata.getPrimitiveValue(); - if (getFlag(EntityFlag.ANGRY)) { - return; + if (!getFlag(EntityFlag.ANGRY) && getFlag(EntityFlag.TAMED)) { + updateCollarColor(); } + } + private void updateCollarColor() { dirtyMetadata.put(EntityDataTypes.COLOR, collarColor); if (ownerBedrockId == 0) { // If a color is set and there is no owner entity ID, set one. From 94f664ad8d065df32d0ce23cabd1e698ea7faf1e Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 19 Apr 2024 11:50:40 +0200 Subject: [PATCH 244/344] Fix: Properly check whether the `so_reuseport` socket option is available (#4579) * Try to properly check if so_reuseport is available * io_uring "support" * comment out io_uring, for now * Make IO_uring opt-in via `-DGeyser.io_uring=true` flag * dont include io_uring * oops - bungee editing on mobile is hard * oops - spigot * oops - velocity * properly exclude all io_uring on all platforms except standalone --------- Co-authored-by: Kas-tle <26531652+Kas-tle@users.noreply.github.com> --- bootstrap/bungeecord/build.gradle.kts | 1 + bootstrap/spigot/build.gradle.kts | 1 + bootstrap/velocity/build.gradle.kts | 4 +- bootstrap/viaproxy/build.gradle.kts | 1 + .../geyser.modded-conventions.gradle.kts | 2 + core/build.gradle.kts | 7 +--- .../geyser/network/netty/Bootstraps.java | 17 +++++++- .../geyser/network/netty/GeyserServer.java | 40 ++++++++++++++----- gradle/libs.versions.toml | 2 + 9 files changed, 56 insertions(+), 19 deletions(-) diff --git a/bootstrap/bungeecord/build.gradle.kts b/bootstrap/bungeecord/build.gradle.kts index 1b57ffa5a..e93c096a1 100644 --- a/bootstrap/bungeecord/build.gradle.kts +++ b/bootstrap/bungeecord/build.gradle.kts @@ -22,6 +22,7 @@ tasks.withType { dependencies { exclude(dependency("com.google.*:.*")) + exclude(dependency("io.netty.incubator:.*")) exclude(dependency("io.netty:netty-transport-native-epoll:.*")) exclude(dependency("io.netty:netty-transport-native-unix-common:.*")) exclude(dependency("io.netty:netty-handler:.*")) diff --git a/bootstrap/spigot/build.gradle.kts b/bootstrap/spigot/build.gradle.kts index 41da1a0de..1d135c33d 100644 --- a/bootstrap/spigot/build.gradle.kts +++ b/bootstrap/spigot/build.gradle.kts @@ -41,6 +41,7 @@ tasks.withType { // We cannot shade Netty, or else native libraries will not load // Needed because older Spigot builds do not provide the haproxy module + exclude(dependency("io.netty.incubator:.*")) exclude(dependency("io.netty:netty-transport-classes-epoll:.*")) exclude(dependency("io.netty:netty-transport-native-epoll:.*")) exclude(dependency("io.netty:netty-transport-native-unix-common:.*")) diff --git a/bootstrap/velocity/build.gradle.kts b/bootstrap/velocity/build.gradle.kts index 97e9d1f57..da826803c 100644 --- a/bootstrap/velocity/build.gradle.kts +++ b/bootstrap/velocity/build.gradle.kts @@ -12,7 +12,8 @@ platformRelocate("org.yaml") exclude("com.google.*:*") -// Needed because Velocity provides every dependency except netty-resolver-dns +// Needed because Velocity provides every dependency except netty-resolver-dns +exclude("io.netty.incubator:.*") exclude("io.netty:netty-transport-native-epoll:*") exclude("io.netty:netty-transport-native-unix-common:*") exclude("io.netty:netty-transport-native-kqueue:*") @@ -57,6 +58,7 @@ tasks.withType { exclude(dependency("io.netty:netty-transport:.*")) exclude(dependency("io.netty:netty-codec:.*")) exclude(dependency("io.netty:netty-codec-haproxy:.*")) + exclude(dependency("io.netty.incubator:.*")) exclude(dependency("org.slf4j:.*")) exclude(dependency("org.ow2.asm:.*")) // Exclude all Kyori dependencies except the legacy NBT serializer diff --git a/bootstrap/viaproxy/build.gradle.kts b/bootstrap/viaproxy/build.gradle.kts index 01c5b5b34..6eadc790f 100644 --- a/bootstrap/viaproxy/build.gradle.kts +++ b/bootstrap/viaproxy/build.gradle.kts @@ -22,6 +22,7 @@ tasks.withType { dependencies { exclude(dependency("com.google.*:.*")) exclude(dependency("io.netty:.*")) + exclude(dependency("io.netty.incubator:.*")) exclude(dependency("org.slf4j:.*")) exclude(dependency("org.ow2.asm:.*")) } diff --git a/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts b/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts index e011b7139..3d41dbbb4 100644 --- a/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts @@ -26,6 +26,8 @@ provided("io.netty", "netty-transport-native-epoll") provided("io.netty", "netty-transport-native-unix-common") provided("io.netty", "netty-transport-classes-kqueue") provided("io.netty", "netty-transport-native-kqueue") +provided("io.netty.incubator", "netty-incubator-transport-native-io_uring") +provided("io.netty.incubator", "netty-incubator-transport-classes-io_uring") provided("io.netty", "netty-handler") provided("io.netty", "netty-common") provided("io.netty", "netty-buffer") diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 93c9f4f13..b1244d55d 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -47,6 +47,8 @@ dependencies { implementation(libs.netty.transport.native.epoll) { artifact { classifier = "linux-x86_64" } } implementation(libs.netty.transport.native.epoll) { artifact { classifier = "linux-aarch_64" } } implementation(libs.netty.transport.native.kqueue) { artifact { classifier = "osx-x86_64" } } + implementation(libs.netty.transport.native.io.uring) { artifact { classifier = "linux-x86_64" } } + implementation(libs.netty.transport.native.io.uring) { artifact { classifier = "linux-aarch_64" } } // Adventure text serialization api(libs.bundles.adventure) @@ -66,11 +68,6 @@ dependencies { api(libs.events) } -configurations.api { - // This is still experimental - additionally, it could only really benefit standalone - exclude(group = "io.netty.incubator", module = "netty-incubator-transport-native-io_uring") -} - tasks.processResources { // This is solely for backwards compatibility for other programs that used this file before the switch to gradle. // It used to be generated by the maven Git-Commit-Id-Plugin diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/Bootstraps.java b/core/src/main/java/org/geysermc/geyser/network/netty/Bootstraps.java index 9f889a6e7..fbc333106 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/Bootstraps.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/Bootstraps.java @@ -49,6 +49,7 @@ public final class Bootstraps { String kernelVersion; try { kernelVersion = Native.KERNEL_VERSION; + GeyserImpl.getInstance().getLogger().debug("Kernel version: " + kernelVersion); } catch (Throwable e) { GeyserImpl.getInstance().getLogger().debug("Could not determine kernel version! " + e.getMessage()); kernelVersion = null; @@ -67,10 +68,22 @@ public final class Bootstraps { } @SuppressWarnings({"rawtypes, unchecked"}) - public static void setupBootstrap(AbstractBootstrap bootstrap) { + public static boolean setupBootstrap(AbstractBootstrap bootstrap) { + boolean success = true; if (REUSEPORT_AVAILABLE) { - bootstrap.option(UnixChannelOption.SO_REUSEPORT, true); + // Guessing whether so_reuseport is available based on kernel version is cool, but unreliable. + Channel channel = bootstrap.register().channel(); + if (channel.config().setOption(UnixChannelOption.SO_REUSEPORT, true)) { + bootstrap.option(UnixChannelOption.SO_REUSEPORT, true); + } else { + // If this occurs, we guessed wrong and reuseport is not available + GeyserImpl.getInstance().getLogger().debug("so_reuseport is not available despite version being " + Native.KERNEL_VERSION); + success = false; + } + // Now yeet that channel + channel.close(); } + return success; } private static int[] fromString(String input) { diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java b/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java index 8ead16623..652901f36 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.network.netty; -import com.github.steveice10.packetlib.helper.TransportHelper; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -39,6 +38,9 @@ import io.netty.channel.kqueue.KQueueEventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.DatagramChannel; import io.netty.channel.socket.nio.NioDatagramChannel; +import io.netty.incubator.channel.uring.IOUring; +import io.netty.incubator.channel.uring.IOUringDatagramChannel; +import io.netty.incubator.channel.uring.IOUringEventLoopGroup; import io.netty.util.concurrent.Future; import lombok.Getter; import net.jodah.expiringmap.ExpirationPolicy; @@ -106,7 +108,7 @@ public final class GeyserServer { @Getter private final ExpiringMap proxiedAddresses; - private final int listenCount; + private int listenCount; private ChannelFuture[] bootstrapFutures; @@ -127,8 +129,11 @@ public final class GeyserServer { this.childGroup = TRANSPORT.eventLoopGroupFactory().apply(threadCount); this.bootstrap = this.createBootstrap(); - // setup SO_REUSEPORT if exists - Bootstraps.setupBootstrap(this.bootstrap); + // setup SO_REUSEPORT if exists - or, if the option does not actually exist, reset listen count + // otherwise, we try to bind multiple times which wont work if so_reuseport is not valid + if (!Bootstraps.setupBootstrap(this.bootstrap)) { + this.listenCount = 1; + } if (this.geyser.getConfig().getBedrock().isEnableProxyProtocol()) { this.proxiedAddresses = ExpiringMap.builder() @@ -415,22 +420,35 @@ public final class GeyserServer { } private static Transport compatibleTransport() { - TransportHelper.TransportMethod transportMethod = TransportHelper.determineTransportMethod(); - if (transportMethod == TransportHelper.TransportMethod.EPOLL) { + if (isClassAvailable("io.netty.incubator.channel.uring.IOUring") + && IOUring.isAvailable() + && Boolean.parseBoolean(System.getProperty("Geyser.io_uring"))) { + return new Transport(IOUringDatagramChannel.class, IOUringEventLoopGroup::new); + } + + if (isClassAvailable("io.netty.channel.epoll.Epoll") && Epoll.isAvailable()) { return new Transport(EpollDatagramChannel.class, EpollEventLoopGroup::new); } - if (transportMethod == TransportHelper.TransportMethod.KQUEUE) { + if (isClassAvailable("io.netty.channel.kqueue.KQueue") && KQueue.isAvailable()) { return new Transport(KQueueDatagramChannel.class, KQueueEventLoopGroup::new); } - // if (transportMethod == TransportHelper.TransportMethod.IO_URING) { - // return new Transport(IOUringDatagramChannel.class, IOUringEventLoopGroup::new); - // } - return new Transport(NioDatagramChannel.class, NioEventLoopGroup::new); } private record Transport(Class datagramChannel, IntFunction eventLoopGroupFactory) { } + + /** + * Used so implementations can opt to remove these dependencies if so desired + */ + private static boolean isClassAvailable(String className) { + try { + Class.forName(className); + return true; + } catch (ClassNotFoundException e) { + return false; + } + } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3111750a8..7feec84e0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,6 +6,7 @@ events = "1.1-SNAPSHOT" jackson = "2.17.0" fastutil = "8.5.2" netty = "4.1.107.Final" +netty-io-uring = "0.0.25.Final-SNAPSHOT" guava = "29.0-jre" gson = "2.3.1" # Provided by Spigot 1.8.8 websocket = "1.5.1" @@ -75,6 +76,7 @@ netty-codec-haproxy = { group = "io.netty", name = "netty-codec-haproxy", versio netty-handler = { group = "io.netty", name = "netty-handler", version.ref = "netty" } netty-transport-native-epoll = { group = "io.netty", name = "netty-transport-native-epoll", version.ref = "netty" } netty-transport-native-kqueue = { group = "io.netty", name = "netty-transport-native-kqueue", version.ref = "netty" } +netty-transport-native-io_uring = { group = "io.netty.incubator", name = "netty-incubator-transport-native-io_uring", version.ref = "netty-io-uring" } log4j-api = { group = "org.apache.logging.log4j", name = "log4j-api", version.ref = "log4j" } log4j-core = { group = "org.apache.logging.log4j", name = "log4j-core", version.ref = "log4j" } From 525a9ccec4f3dfdcbec328c9b382a782540cb7d9 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Fri, 19 Apr 2024 18:47:00 -0700 Subject: [PATCH 245/344] Fix Preview Workflow (#4583) * Fix preview workflow * Correct path to artifacts * Uncomment repo checks * Don't enforce repo/branch on preview deploy * Correct paths-ignore for build --- .../{pullrequest.yml => build-remote.yml} | 68 +++++++------------ .github/workflows/build.yml | 22 ++++-- .github/workflows/preview.yml | 33 +++++++-- .github/workflows/pull-request.yml | 24 +++++++ core/build.gradle.kts | 5 +- 5 files changed, 92 insertions(+), 60 deletions(-) rename .github/workflows/{pullrequest.yml => build-remote.yml} (65%) create mode 100644 .github/workflows/pull-request.yml diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/build-remote.yml similarity index 65% rename from .github/workflows/pullrequest.yml rename to .github/workflows/build-remote.yml index 18223e7dc..75bcfaff5 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/build-remote.yml @@ -1,13 +1,27 @@ -name: Build Pull Request +name: Build Remote -on: - pull_request: - merge_group: +on: + workflow_call: + inputs: + repository: + required: true + description: 'The repo of the remote' + type: string + ref: + required: true + description: 'The ref of the remote' + type: string + +permissions: {} jobs: build: runs-on: ubuntu-latest steps: + - name: Set Build Number + run: | + echo "BUILD_NUMBER=${GITHUB_RUN_NUMBER}" >> $GITHUB_ENV + - name: Set up JDK 17 # See https://github.com/actions/setup-java/commits uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4.0.0 @@ -15,29 +29,12 @@ jobs: java-version: 17 distribution: temurin - - name: Check if the author has forked the API repo - # See https://github.com/Kas-tle/find-forks-action/commits - uses: Kas-tle/find-forks-action@1b5447d1e3c7a8ed79583dd817cc5399686eed3a - id: find_forks - with: - owner: GeyserMC - repo: api - token: ${{ secrets.GITHUB_TOKEN }} - - - name: Use author's API repo if it exists - if: ${{ steps.find_forks.outputs.target_branch_found == 'true' }} - env: - API_FORK_URL: ${{ steps.find_forks.outputs.user_fork_url }} - API_FORK_BRANCH: ${{ github.event.pull_request.head.ref }} - run: | - git clone "${API_FORK_URL}" --single-branch --branch "${API_FORK_BRANCH}" api - cd api - ./gradlew publishToMavenLocal - - name: Checkout repository and submodules # See https://github.com/actions/checkout/commits uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: + repository: ${{ inputs.repository }} + ref: ${{ inputs.ref }} submodules: recursive path: geyser @@ -46,11 +43,12 @@ jobs: uses: gradle/wrapper-validation-action@699bb18358f12c5b78b37bb0111d3a0e2276e0e2 # v2.1.1 - name: Build Geyser - # See https://github.com/gradle/gradle-build-action/commits - uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 from https://github.com/gradle/actions/commits + # See https://github.com/gradle/actions/commits + uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 with: arguments: build build-root-directory: geyser + cache-read-only: true - name: Archive artifacts (Geyser Fabric) # See https://github.com/actions/upload-artifact/commits @@ -101,22 +99,4 @@ jobs: with: name: Geyser ViaProxy path: geyser/bootstrap/viaproxy/build/libs/Geyser-ViaProxy.jar - if-no-files-found: error - - - name: Trigger Preview Deployment - if: >- - contains(github.event.pull_request.labels.*.name, 'PR: Needs Testing') - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea - with: - script: | - github.rest.actions.createWorkflowDispatch({ - owner: context.repo.owner, - repo: context.repo.repo, - workflow_id: 'preview.yml', - ref: 'master', - inputs: { - runId: '${{ github.run_id }}', - build: '${{ github.run_number }}', - version: 'pr.${{ github.event.pull_request.number }}' - } - }); \ No newline at end of file + if-no-files-found: error \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c7b439182..9582df3e8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,8 +7,9 @@ on: - 'gh-readonly-queue/**' paths-ignore: - '.github/ISSUE_TEMPLATE/*.yml' - - '.github/actions/pullrequest.yml' - - '.github/actions/preview.yml' + - '.github/actions/workflows/build-remote.yml' + - '.github/actions/workflows/preview.yml' + - '.github/actions/workflows/pull-request.yml' - '.idea/copyright/*.xml' - '.gitignore' - 'CONTRIBUTING.md' @@ -23,6 +24,13 @@ jobs: env: PROJECT: 'geyser' steps: + - name: Set Build Number + env: + BUILD_JSON: ${{ vars.RELEASEACTION_PREVRELEASE }} + run: | + BUILD_NUMBER=$(echo $BUILD_JSON | jq --arg branch "${GITHUB_REF_NAME}" 'if .[$branch] == null then 1 else .[$branch] | .t | tonumber + 1 end // 1') + echo "BUILD_NUMBER=${BUILD_NUMBER}" >> $GITHUB_ENV + - name: Checkout repository and submodules # See https://github.com/actions/checkout/commits uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 @@ -40,8 +48,8 @@ jobs: distribution: temurin - name: Build - # See https://github.com/gradle/gradle-build-action/commits - uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 from https://github.com/gradle/actions/commits + # See https://github.com/gradle/actions/commits + uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 with: arguments: build gradle-home-cache-cleanup: true @@ -108,7 +116,8 @@ jobs: - name: Get Release Metadata if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} - uses: Kas-tle/base-release-action@b863fa0f89bd15267a96a72efb84aec25f168d4c # https://github.com/Kas-tle/base-release-action/releases/tag/main-11 + # See https://github.com/Kas-tle/base-release-action/releases/tag/main-11 + uses: Kas-tle/base-release-action@b863fa0f89bd15267a96a72efb84aec25f168d4c # main-11 with: appID: ${{ secrets.RELEASE_APP_ID }} appPrivateKey: ${{ secrets.RELEASE_APP_PK }} @@ -134,6 +143,7 @@ jobs: | .downloads |= map_values({"name", "sha256"}) | {$project, "repo", $version, "number": .build, "changes", "downloads"} ' | tee metadata.json + echo - name: Publish to Downloads API if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} shell: bash @@ -177,4 +187,4 @@ jobs: uses: Tim203/actions-git-discord-webhook@70f38ded3aca51635ec978ab4e1a58cd4cd0c2ff with: webhook_url: ${{ secrets.DISCORD_WEBHOOK }} - status: ${{ job.status }} \ No newline at end of file + status: ${{ job.status }} diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index a2955a081..ccac3ba85 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -12,23 +12,44 @@ on: version: required: true description: 'Version under which to upload to the Downloads API' + workflow_call: + inputs: + build: + required: true + description: 'Build number for the release' + type: string + version: + required: true + description: 'Version under which to upload to the Downloads API' + type: string jobs: upload: runs-on: ubuntu-latest env: - PROJECT: 'geyserpreview' - BUILD: ${{ github.event.inputs.build }} - VERSION: ${{ github.event.inputs.version }} + PROJECT: 'geyser-preview' steps: - - uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # https://github.com/actions/download-artifact/releases/tag/v4.1.4 + - name: Set Variables + id: setvars + run: | + if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then + echo "BUILD=${{ github.event.inputs.build }}" >> $GITHUB_ENV + echo "VERSION=${{ github.event.inputs.version }}" >> $GITHUB_ENV + echo "RUN=${{ github.event.inputs.runId }}" >> $GITHUB_OUTPUT + else + echo "BUILD=${{ inputs.build }}" >> $GITHUB_ENV + echo "VERSION=${{ inputs.version }}" >> $GITHUB_ENV + echo "RUN=${{ github.run_id }}" >> $GITHUB_OUTPUT + fi + - uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 with: - run-id: ${{ github.event.inputs.runId }} + run-id: ${{ steps.setvars.outputs.RUN }} github-token: ${{ secrets.GITHUB_TOKEN }} merge-multiple: true - name: Get Preview Metadata if: success() - uses: Kas-tle/base-release-action@b863fa0f89bd15267a96a72efb84aec25f168d4c # https://github.com/Kas-tle/base-release-action/releases/tag/main-11 + # See https://github.com/Kas-tle/base-release-action/releases/tag/main-11 + uses: Kas-tle/base-release-action@664c39985eb9d0d393ce98e7eb8414d3d98e762a # main-11 with: appID: ${{ secrets.RELEASE_APP_ID }} appPrivateKey: ${{ secrets.RELEASE_APP_PK }} diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml new file mode 100644 index 000000000..bc5e57b6b --- /dev/null +++ b/.github/workflows/pull-request.yml @@ -0,0 +1,24 @@ +name: Process Pull Request + +on: + pull_request_target: + +jobs: + build: + # Forbid access to secrets nor GH Token perms while building the PR + permissions: {} + secrets: {} + uses: ./.github/workflows/build-remote.yml + with: + repository: ${{ github.event.pull_request.head.repo.full_name }} + ref: ${{ github.event.pull_request.head.sha }} + preview: + needs: [build] + if: >- + contains(github.event.pull_request.labels.*.name, 'PR: Needs Testing') + # Allow access to secrets if we are uploading a preview + secrets: inherit + uses: ./.github/workflows/preview.yml + with: + build: ${{ github.run_number }} + version: pr.${{ github.event.pull_request.number }} \ No newline at end of file diff --git a/core/build.gradle.kts b/core/build.gradle.kts index b1244d55d..42d4e13c5 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -98,7 +98,7 @@ configure { } fun Project.buildNumber(): Int = - (System.getenv("GITHUB_RUN_NUMBER") ?: jenkinsBuildNumber())?.let { Integer.parseInt(it) } ?: -1 + (System.getenv("BUILD_NUMBER"))?.let { Integer.parseInt(it) } ?: -1 inner class GitInfo { val branch: String @@ -131,9 +131,6 @@ inner class GitInfo { } } -// todo remove this when we're not using Jenkins anymore -fun jenkinsBuildNumber(): String? = System.getenv("BUILD_NUMBER") - // Manual task to download the bedrock data files from the CloudburstMC/Data repository // Invoke with ./gradlew :core:downloadBedrockData --suffix=1_20_70 // Set suffix to the current Bedrock version From 1bca6421d30966fb4f1b7703df2885da43517d6c Mon Sep 17 00:00:00 2001 From: rtm516 Date: Sat, 20 Apr 2024 03:12:27 +0100 Subject: [PATCH 246/344] Update preview action to use correct project --- .github/workflows/preview.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index ccac3ba85..13712d5ef 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -27,7 +27,7 @@ jobs: upload: runs-on: ubuntu-latest env: - PROJECT: 'geyser-preview' + PROJECT: 'geyserpreview' steps: - name: Set Variables id: setvars From 810c9ced724360b3b52efa3b70eef1682e2bb86b Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Sat, 20 Apr 2024 17:21:39 -0400 Subject: [PATCH 247/344] Fix filled cauldrons only showing as water (#4585) * Fix filled cauldrons only showing as water * Update comment --- .../org/geysermc/geyser/level/block/BlockStateValues.java | 4 ++-- .../translator/level/block/entity/BedrockOnlyBlockEntity.java | 2 +- .../java/level/JavaLevelChunkWithLightTranslator.java | 4 ++-- 3 files changed, 5 insertions(+), 5 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 e665a22ef..52759c709 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 @@ -260,8 +260,6 @@ public final class BlockStateValues { } /** - * 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 isNonWaterCauldron(int state) { @@ -269,6 +267,8 @@ public final class BlockStateValues { } /** + * Cauldrons (since Bedrock 1.18.30) must have a block entity packet sent on chunk load to fix rendering issues. + *

* When using a bucket on a cauldron sending a ServerboundUseItemPacket can result in the liquid being placed. * * @return if this Java block state is a cauldron 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 07b075690..051986473 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 @@ -63,7 +63,7 @@ public interface BedrockOnlyBlockEntity extends RequiresBlockState { return FlowerPotBlockEntityTranslator.getTag(session, blockState, position); } else if (PistonBlockEntityTranslator.isBlock(blockState)) { return PistonBlockEntityTranslator.getTag(blockState, position); - } else if (BlockStateValues.isNonWaterCauldron(blockState)) { + } 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") 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 8a35bbb5c..a98ead719 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 @@ -200,7 +200,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator> 8) & 0xF), (packet.getZ() << 4) + ((yzx >> 4) & 0xF)), javaId @@ -259,7 +259,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator Date: Sat, 20 Apr 2024 19:07:39 -0700 Subject: [PATCH 248/344] Fallback to GITHUB_RUN_NUMBER if RELEASEACTION_PREVRELEASE is unset (#4587) This is so there is still a build number when built on other repositories --- .github/workflows/build.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9582df3e8..1ef0118ff 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,9 +7,9 @@ on: - 'gh-readonly-queue/**' paths-ignore: - '.github/ISSUE_TEMPLATE/*.yml' - - '.github/actions/workflows/build-remote.yml' - - '.github/actions/workflows/preview.yml' - - '.github/actions/workflows/pull-request.yml' + - '.github/workflows/build-remote.yml' + - '.github/workflows/preview.yml' + - '.github/workflows/pull-request.yml' - '.idea/copyright/*.xml' - '.gitignore' - 'CONTRIBUTING.md' @@ -29,7 +29,7 @@ jobs: BUILD_JSON: ${{ vars.RELEASEACTION_PREVRELEASE }} run: | BUILD_NUMBER=$(echo $BUILD_JSON | jq --arg branch "${GITHUB_REF_NAME}" 'if .[$branch] == null then 1 else .[$branch] | .t | tonumber + 1 end // 1') - echo "BUILD_NUMBER=${BUILD_NUMBER}" >> $GITHUB_ENV + echo "BUILD_NUMBER=${BUILD_NUMBER:=$GITHUB_RUN_NUMBER}" >> $GITHUB_ENV - name: Checkout repository and submodules # See https://github.com/actions/checkout/commits From 3fa79529365e4ceae3fb4f95b2acde2f1305a13d Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Tue, 23 Apr 2024 09:16:18 -0700 Subject: [PATCH 249/344] 1.20.80 Support and Protocol Changes (#4561) * Make evil more harder Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Deregister more unused packets Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Add more unused packets Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Pin protocol to 68dc192 * Correction * Update Protocol * More kicking Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * stop reading when there is no item to read (#9) * Bump protocol Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * 1.20.80 Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Remove unused postinitchannel GeyserServerInitializer * Pull protocol jitpack from cloudburst again * Actually builds Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Bump protocol to fix BossEventPacket & EmotePacket Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Add remove before merge comment Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Bump protocol to fix BlockEntityDataPacket and ignore serverbound BossEventPacket Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Bump protocol & add more illegal/ignored packets Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Remove deprecated packet Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Ignore ClientCacheStatusPacket instead of disallow Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Define static serializers Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Less static class nonsense more correct order Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Remove unused import Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Bump protocol Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Move codec processing to CodecProcessor Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Falsify recipe symetry assumption Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Update Protocol for 2 wrong packet IDs & 5 wrong directions * Jitpack protocol from Geyser repo --------- Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Co-authored-by: chris --- README.md | 2 +- .../geyser/network/CodecProcessor.java | 292 + .../geysermc/geyser/network/GameProtocol.java | 29 +- .../network/GeyserServerInitializer.java | 8 + .../geyser/network/InvalidPacketHandler.java | 58 + .../populator/BlockRegistryPopulator.java | 4 +- .../registry/populator/Conversion662_649.java | 4 + .../registry/populator/Conversion671_662.java | 182 + .../populator/ItemRegistryPopulator.java | 4 +- .../populator/RecipeRegistryPopulator.java | 2 +- .../java/JavaUpdateRecipesTranslator.java | 2 +- .../JavaContainerSetSlotTranslator.java | 3 +- .../bedrock/block_palette.1_20_80.nbt | Bin 0 -> 176786 bytes .../bedrock/creative_items.1_20_80.json | 5812 +++++++++++++++ .../resources/bedrock/entity_identifiers.dat | Bin 7886 -> 7951 bytes .../bedrock/runtime_item_states.1_20_80.json | 6274 +++++++++++++++++ core/src/main/resources/mappings | 2 +- gradle/libs.versions.toml | 15 +- 18 files changed, 12661 insertions(+), 32 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/network/CodecProcessor.java create mode 100644 core/src/main/java/org/geysermc/geyser/network/InvalidPacketHandler.java create mode 100644 core/src/main/java/org/geysermc/geyser/registry/populator/Conversion671_662.java create mode 100644 core/src/main/resources/bedrock/block_palette.1_20_80.nbt create mode 100644 core/src/main/resources/bedrock/creative_items.1_20_80.json create mode 100644 core/src/main/resources/bedrock/runtime_item_states.1_20_80.json diff --git a/README.md b/README.md index 0aa9d009a..e17c9d2bb 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,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.20.40 - 1.20.73 and Minecraft Java 1.20.4 +### Currently supporting Minecraft Bedrock 1.20.40 - 1.20.80 and Minecraft Java 1.20.4 ## 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/CodecProcessor.java b/core/src/main/java/org/geysermc/geyser/network/CodecProcessor.java new file mode 100644 index 000000000..4ad02a644 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/network/CodecProcessor.java @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2019-2024 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.network; + +import io.netty.buffer.ByteBuf; +import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; +import org.cloudburstmc.protocol.bedrock.codec.BedrockCodecHelper; +import org.cloudburstmc.protocol.bedrock.codec.BedrockPacketSerializer; +import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.MobArmorEquipmentSerializer_v291; +import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.MobEquipmentSerializer_v291; +import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.PlayerHotbarSerializer_v291; +import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.SetEntityLinkSerializer_v291; +import org.cloudburstmc.protocol.bedrock.codec.v390.serializer.PlayerSkinSerializer_v390; +import org.cloudburstmc.protocol.bedrock.codec.v407.serializer.InventoryContentSerializer_v407; +import org.cloudburstmc.protocol.bedrock.codec.v407.serializer.InventorySlotSerializer_v407; +import org.cloudburstmc.protocol.bedrock.codec.v486.serializer.BossEventSerializer_v486; +import org.cloudburstmc.protocol.bedrock.codec.v557.serializer.SetEntityDataSerializer_v557; +import org.cloudburstmc.protocol.bedrock.codec.v662.serializer.SetEntityMotionSerializer_v662; +import org.cloudburstmc.protocol.bedrock.packet.AnvilDamagePacket; +import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket; +import org.cloudburstmc.protocol.bedrock.packet.BossEventPacket; +import org.cloudburstmc.protocol.bedrock.packet.ClientCacheBlobStatusPacket; +import org.cloudburstmc.protocol.bedrock.packet.ClientCacheStatusPacket; +import org.cloudburstmc.protocol.bedrock.packet.ClientCheatAbilityPacket; +import org.cloudburstmc.protocol.bedrock.packet.ClientToServerHandshakePacket; +import org.cloudburstmc.protocol.bedrock.packet.CodeBuilderSourcePacket; +import org.cloudburstmc.protocol.bedrock.packet.CraftingEventPacket; +import org.cloudburstmc.protocol.bedrock.packet.CreatePhotoPacket; +import org.cloudburstmc.protocol.bedrock.packet.DebugInfoPacket; +import org.cloudburstmc.protocol.bedrock.packet.DisconnectPacket; +import org.cloudburstmc.protocol.bedrock.packet.EditorNetworkPacket; +import org.cloudburstmc.protocol.bedrock.packet.EntityFallPacket; +import org.cloudburstmc.protocol.bedrock.packet.GameTestRequestPacket; +import org.cloudburstmc.protocol.bedrock.packet.InventoryContentPacket; +import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket; +import org.cloudburstmc.protocol.bedrock.packet.LabTablePacket; +import org.cloudburstmc.protocol.bedrock.packet.MapCreateLockedCopyPacket; +import org.cloudburstmc.protocol.bedrock.packet.MapInfoRequestPacket; +import org.cloudburstmc.protocol.bedrock.packet.MobArmorEquipmentPacket; +import org.cloudburstmc.protocol.bedrock.packet.MobEquipmentPacket; +import org.cloudburstmc.protocol.bedrock.packet.MultiplayerSettingsPacket; +import org.cloudburstmc.protocol.bedrock.packet.NpcRequestPacket; +import org.cloudburstmc.protocol.bedrock.packet.PhotoInfoRequestPacket; +import org.cloudburstmc.protocol.bedrock.packet.PhotoTransferPacket; +import org.cloudburstmc.protocol.bedrock.packet.PlayerAuthInputPacket; +import org.cloudburstmc.protocol.bedrock.packet.PlayerHotbarPacket; +import org.cloudburstmc.protocol.bedrock.packet.PlayerSkinPacket; +import org.cloudburstmc.protocol.bedrock.packet.PurchaseReceiptPacket; +import org.cloudburstmc.protocol.bedrock.packet.RefreshEntitlementsPacket; +import org.cloudburstmc.protocol.bedrock.packet.ScriptMessagePacket; +import org.cloudburstmc.protocol.bedrock.packet.SetEntityDataPacket; +import org.cloudburstmc.protocol.bedrock.packet.SetEntityLinkPacket; +import org.cloudburstmc.protocol.bedrock.packet.SetEntityMotionPacket; +import org.cloudburstmc.protocol.bedrock.packet.SettingsCommandPacket; +import org.cloudburstmc.protocol.bedrock.packet.SimpleEventPacket; +import org.cloudburstmc.protocol.bedrock.packet.SubChunkRequestPacket; +import org.cloudburstmc.protocol.bedrock.packet.SubClientLoginPacket; +import org.cloudburstmc.protocol.bedrock.packet.TickSyncPacket; +import org.cloudburstmc.protocol.common.util.VarInts; + +/** + * Processes the Bedrock codec to remove or modify unused or unsafe packets and fields. + */ +class CodecProcessor { + + /** + * Generic serializer that throws an exception when trying to serialize or deserialize a packet, leading to client disconnection. + */ + @SuppressWarnings("rawtypes") + private static final BedrockPacketSerializer ILLEGAL_SERIALIZER = new BedrockPacketSerializer<>() { + @Override + public void serialize(ByteBuf buffer, BedrockCodecHelper helper, BedrockPacket packet) { + throw new IllegalArgumentException("Server tried to send unused packet " + packet.getClass().getSimpleName() + "!"); + } + + @Override + public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, BedrockPacket packet) { + throw new IllegalArgumentException("Client tried to send unused packet " + packet.getClass().getSimpleName() + "!"); + } + }; + + /** + * Generic serializer that does nothing when trying to serialize or deserialize a packet. + */ + @SuppressWarnings("rawtypes") + private static final BedrockPacketSerializer IGNORED_SERIALIZER = new BedrockPacketSerializer<>() { + @Override + public void serialize(ByteBuf buffer, BedrockCodecHelper helper, BedrockPacket packet) { + } + + @Override + public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, BedrockPacket packet) { + } + }; + + /** + * Serializer that throws an exception when trying to deserialize InventoryContentPacket since server-auth inventory is used. + */ + private static final BedrockPacketSerializer INVENTORY_CONTENT_SERIALIZER = new InventoryContentSerializer_v407() { + @Override + public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, InventoryContentPacket packet) { + throw new IllegalArgumentException("Client cannot send InventoryContentPacket in server-auth inventory environment!"); + } + }; + + /** + * Serializer that throws an exception when trying to deserialize InventorySlotPacket since server-auth inventory is used. + */ + private static final BedrockPacketSerializer INVENTORY_SLOT_SERIALIZER = new InventorySlotSerializer_v407() { + @Override + public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, InventorySlotPacket packet) { + throw new IllegalArgumentException("Client cannot send InventorySlotPacket in server-auth inventory environment!"); + } + }; + + /** + * Serializer that does nothing when trying to deserialize BossEventPacket since it is not used from the client. + */ + private static final BedrockPacketSerializer BOSS_EVENT_SERIALIZER = new BossEventSerializer_v486() { + @Override + public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, BossEventPacket packet) { + } + }; + + /** + * Serializer that does nothing when trying to deserialize MobArmorEquipmentPacket since it is not used from the client. + */ + private static final BedrockPacketSerializer MOB_ARMOR_EQUIPMENT_SERIALIZER = new MobArmorEquipmentSerializer_v291() { + @Override + public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, MobArmorEquipmentPacket packet) { + } + }; + + /** + * Serializer that does nothing when trying to deserialize PlayerHotbarPacket since it is not used from the client. + */ + private static final BedrockPacketSerializer PLAYER_HOTBAR_SERIALIZER = new PlayerHotbarSerializer_v291() { + @Override + public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, PlayerHotbarPacket packet) { + } + }; + + /** + * Serializer that does nothing when trying to deserialize PlayerSkinPacket since it is not used from the client. + */ + private static final BedrockPacketSerializer PLAYER_SKIN_SERIALIZER = new PlayerSkinSerializer_v390() { + @Override + public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, PlayerSkinPacket packet) { + } + }; + + /** + * Serializer that does nothing when trying to deserialize SetEntityDataPacket since it is not used from the client. + */ + private static final BedrockPacketSerializer SET_ENTITY_DATA_SERIALIZER = new SetEntityDataSerializer_v557() { + @Override + public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, SetEntityDataPacket packet) { + } + }; + + /** + * Serializer that does nothing when trying to deserialize SetEntityMotionPacket since it is not used from the client. + */ + private static final BedrockPacketSerializer SET_ENTITY_MOTION_SERIALIZER = new SetEntityMotionSerializer_v662() { + @Override + public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, SetEntityMotionPacket packet) { + } + }; + + /** + * Serializer that does nothing when trying to deserialize SetEntityLinkPacket since it is not used from the client. + */ + private static final BedrockPacketSerializer SET_ENTITY_LINK_SERIALIZER = new SetEntityLinkSerializer_v291() { + @Override + public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, SetEntityLinkPacket packet) { + } + }; + + /** + * Serializer that skips over the item when trying to deserialize MobEquipmentPacket since only the slot info is used. + */ + private static final BedrockPacketSerializer MOB_EQUIPMENT_SERIALIZER = new MobEquipmentSerializer_v291() { + @Override + public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, MobEquipmentPacket packet) { + packet.setRuntimeEntityId(VarInts.readUnsignedLong(buffer)); + fakeItemRead(buffer); + packet.setInventorySlot(buffer.readUnsignedByte()); + packet.setHotbarSlot(buffer.readUnsignedByte()); + packet.setContainerId(buffer.readByte()); + } + }; + + @SuppressWarnings("unchecked") + static BedrockCodec processCodec(BedrockCodec codec) { + return codec.toBuilder() + // Illegal unused serverbound EDU packets + .updateSerializer(PhotoTransferPacket.class, ILLEGAL_SERIALIZER) + .updateSerializer(LabTablePacket.class, ILLEGAL_SERIALIZER) + .updateSerializer(CodeBuilderSourcePacket.class, ILLEGAL_SERIALIZER) + .updateSerializer(CreatePhotoPacket.class, ILLEGAL_SERIALIZER) + .updateSerializer(NpcRequestPacket.class, ILLEGAL_SERIALIZER) + .updateSerializer(PhotoInfoRequestPacket.class, ILLEGAL_SERIALIZER) + // Illegal unused serverbound packets for featured servers + .updateSerializer(PurchaseReceiptPacket.class, ILLEGAL_SERIALIZER) + // Illegal unused serverbound packets that are deprecated + .updateSerializer(ClientCheatAbilityPacket.class, ILLEGAL_SERIALIZER) + // Illegal unusued serverbound packets that relate to unused features + .updateSerializer(PlayerAuthInputPacket.class, ILLEGAL_SERIALIZER) + .updateSerializer(ClientCacheBlobStatusPacket.class, ILLEGAL_SERIALIZER) + .updateSerializer(SubClientLoginPacket.class, ILLEGAL_SERIALIZER) + .updateSerializer(SubChunkRequestPacket.class, ILLEGAL_SERIALIZER) + .updateSerializer(GameTestRequestPacket.class, ILLEGAL_SERIALIZER) + // Ignored serverbound packets + .updateSerializer(CraftingEventPacket.class, IGNORED_SERIALIZER) // Make illegal when 1.20.40 is removed + .updateSerializer(ClientToServerHandshakePacket.class, IGNORED_SERIALIZER) + .updateSerializer(EntityFallPacket.class, IGNORED_SERIALIZER) + .updateSerializer(MapCreateLockedCopyPacket.class, IGNORED_SERIALIZER) + .updateSerializer(MapInfoRequestPacket.class, IGNORED_SERIALIZER) + .updateSerializer(SettingsCommandPacket.class, IGNORED_SERIALIZER) + .updateSerializer(AnvilDamagePacket.class, IGNORED_SERIALIZER) + .updateSerializer(RefreshEntitlementsPacket.class, IGNORED_SERIALIZER) + // Illegal when serverbound due to Geyser specific setup + .updateSerializer(InventoryContentPacket.class, INVENTORY_CONTENT_SERIALIZER) + .updateSerializer(InventorySlotPacket.class, INVENTORY_SLOT_SERIALIZER) + // Ignored only when serverbound + .updateSerializer(BossEventPacket.class, BOSS_EVENT_SERIALIZER) + .updateSerializer(MobArmorEquipmentPacket.class, MOB_ARMOR_EQUIPMENT_SERIALIZER) + .updateSerializer(PlayerHotbarPacket.class, PLAYER_HOTBAR_SERIALIZER) + .updateSerializer(PlayerSkinPacket.class, PLAYER_SKIN_SERIALIZER) + .updateSerializer(SetEntityDataPacket.class, SET_ENTITY_DATA_SERIALIZER) + .updateSerializer(SetEntityMotionPacket.class, SET_ENTITY_MOTION_SERIALIZER) + .updateSerializer(SetEntityLinkPacket.class, SET_ENTITY_LINK_SERIALIZER) + // Valid serverbound packets where reading of some fields can be skipped + .updateSerializer(MobEquipmentPacket.class, MOB_EQUIPMENT_SERIALIZER) + // // Illegal bidirectional packets + .updateSerializer(DebugInfoPacket.class, ILLEGAL_SERIALIZER) + .updateSerializer(EditorNetworkPacket.class, ILLEGAL_SERIALIZER) + .updateSerializer(ScriptMessagePacket.class, ILLEGAL_SERIALIZER) + // // Ignored bidirectional packets + .updateSerializer(ClientCacheStatusPacket.class, IGNORED_SERIALIZER) + .updateSerializer(DisconnectPacket.class, IGNORED_SERIALIZER) + .updateSerializer(SimpleEventPacket.class, IGNORED_SERIALIZER) + .updateSerializer(TickSyncPacket.class, IGNORED_SERIALIZER) + .updateSerializer(MultiplayerSettingsPacket.class, IGNORED_SERIALIZER) + .build(); + } + + /** + * Fake reading an item from the buffer to improve performance. + * + * @param buffer + */ + private static void fakeItemRead(ByteBuf buffer) { + int id = VarInts.readInt(buffer); // Runtime ID + if (id == 0) { // nothing more to read + return; + } + buffer.skipBytes(2); // count + VarInts.readUnsignedInt(buffer); // damage + boolean hasNetId = buffer.readBoolean(); + if (hasNetId) { + VarInts.readInt(buffer); + } + + VarInts.readInt(buffer); // Block runtime ID + int streamSize = VarInts.readUnsignedInt(buffer); + buffer.skipBytes(streamSize); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java index f43706db0..b5fc4440c 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java @@ -27,17 +27,14 @@ package org.geysermc.geyser.network; import com.github.steveice10.mc.protocol.codec.MinecraftCodec; import com.github.steveice10.mc.protocol.codec.PacketCodec; -import io.netty.buffer.ByteBuf; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; -import org.cloudburstmc.protocol.bedrock.codec.BedrockCodecHelper; -import org.cloudburstmc.protocol.bedrock.codec.v582.serializer.TrimDataSerializer_v582; import org.cloudburstmc.protocol.bedrock.codec.v622.Bedrock_v622; import org.cloudburstmc.protocol.bedrock.codec.v630.Bedrock_v630; import org.cloudburstmc.protocol.bedrock.codec.v649.Bedrock_v649; import org.cloudburstmc.protocol.bedrock.codec.v662.Bedrock_v662; +import org.cloudburstmc.protocol.bedrock.codec.v671.Bedrock_v671; import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec; -import org.cloudburstmc.protocol.bedrock.packet.TrimDataPacket; import org.geysermc.geyser.session.GeyserSession; import java.util.ArrayList; @@ -48,11 +45,12 @@ import java.util.StringJoiner; * Contains information about the supported protocols in Geyser. */ public final class GameProtocol { + /** * Default Bedrock codec that should act as a fallback. Should represent the latest available * release of the game that Geyser supports. */ - public static final BedrockCodec DEFAULT_BEDROCK_CODEC = processCodec(Bedrock_v662.CODEC); + public static final BedrockCodec DEFAULT_BEDROCK_CODEC = CodecProcessor.processCodec(Bedrock_v671.CODEC); /** * A list of all supported Bedrock versions that can join Geyser @@ -66,18 +64,21 @@ public final class GameProtocol { private static final PacketCodec DEFAULT_JAVA_CODEC = MinecraftCodec.CODEC; static { - SUPPORTED_BEDROCK_CODECS.add(processCodec(Bedrock_v622.CODEC.toBuilder() + SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v622.CODEC.toBuilder() .minecraftVersion("1.20.40/1.20.41") .build())); - SUPPORTED_BEDROCK_CODECS.add(processCodec(Bedrock_v630.CODEC.toBuilder() + SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v630.CODEC.toBuilder() .minecraftVersion("1.20.50/1.20.51") .build())); - SUPPORTED_BEDROCK_CODECS.add(processCodec(Bedrock_v649.CODEC.toBuilder() + SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v649.CODEC.toBuilder() .minecraftVersion("1.20.60/1.20.62") .build())); - SUPPORTED_BEDROCK_CODECS.add(processCodec(DEFAULT_BEDROCK_CODEC.toBuilder() + SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v662.CODEC.toBuilder() .minecraftVersion("1.20.70/1.20.73") .build())); + SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(DEFAULT_BEDROCK_CODEC.toBuilder() + .minecraftVersion("1.20.80") + .build())); } /** @@ -168,16 +169,6 @@ public final class GameProtocol { return joiner.toString(); } - private static BedrockCodec processCodec(BedrockCodec codec) { - return codec.toBuilder() - .updateSerializer(TrimDataPacket.class, new TrimDataSerializer_v582() { - @Override - public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, TrimDataPacket packet) { - } - }) - .build(); - } - private GameProtocol() { } } diff --git a/core/src/main/java/org/geysermc/geyser/network/GeyserServerInitializer.java b/core/src/main/java/org/geysermc/geyser/network/GeyserServerInitializer.java index bb8e87440..662e2f4c7 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GeyserServerInitializer.java +++ b/core/src/main/java/org/geysermc/geyser/network/GeyserServerInitializer.java @@ -25,12 +25,16 @@ package org.geysermc.geyser.network; +import io.netty.buffer.ByteBuf; import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; import io.netty.channel.DefaultEventLoopGroup; +import io.netty.channel.SimpleChannelInboundHandler; import io.netty.util.concurrent.DefaultThreadFactory; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.protocol.bedrock.BedrockPeer; import org.cloudburstmc.protocol.bedrock.BedrockServerSession; +import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec; import org.cloudburstmc.protocol.bedrock.netty.initializer.BedrockServerInitializer; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.event.bedrock.SessionInitializeEvent; @@ -63,6 +67,10 @@ public class GeyserServerInitializer extends BedrockServerInitializer { bedrockServerSession.setLogging(true); GeyserSession session = new GeyserSession(this.geyser, bedrockServerSession, this.eventLoopGroup.next()); + + Channel channel = bedrockServerSession.getPeer().getChannel(); + channel.pipeline().addAfter(BedrockPacketCodec.NAME, InvalidPacketHandler.NAME, new InvalidPacketHandler(session)); + bedrockServerSession.setPacketHandler(new UpstreamPacketHandler(this.geyser, session)); this.geyser.eventBus().fire(new SessionInitializeEvent(session)); } catch (Throwable e) { diff --git a/core/src/main/java/org/geysermc/geyser/network/InvalidPacketHandler.java b/core/src/main/java/org/geysermc/geyser/network/InvalidPacketHandler.java new file mode 100644 index 000000000..3e836711b --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/network/InvalidPacketHandler.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2019-2024 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.network; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import lombok.RequiredArgsConstructor; +import org.geysermc.geyser.session.GeyserSession; + +import java.util.stream.Stream; + +@RequiredArgsConstructor +public class InvalidPacketHandler extends ChannelInboundHandlerAdapter { + public static final String NAME = "rak-error-handler"; + + private final GeyserSession session; + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + Throwable rootCause = Stream.iterate(cause, Throwable::getCause) + .filter(element -> element.getCause() == null) + .findFirst() + .orElse(cause); + + + if (!(rootCause instanceof IllegalArgumentException)) { + super.exceptionCaught(ctx, cause); + return; + } + + // Kick users that try to send illegal packets + session.getGeyser().getLogger().warning(rootCause.getMessage()); + session.disconnect("Invalid packet received!"); + } +} 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 c54431fbe..e76edc059 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 @@ -43,6 +43,7 @@ import org.cloudburstmc.protocol.bedrock.codec.v622.Bedrock_v622; import org.cloudburstmc.protocol.bedrock.codec.v630.Bedrock_v630; import org.cloudburstmc.protocol.bedrock.codec.v649.Bedrock_v649; import org.cloudburstmc.protocol.bedrock.codec.v662.Bedrock_v662; +import org.cloudburstmc.protocol.bedrock.codec.v671.Bedrock_v671; import org.cloudburstmc.protocol.bedrock.data.BlockPropertyData; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.geysermc.geyser.GeyserImpl; @@ -122,7 +123,8 @@ public final class BlockRegistryPopulator { .put(ObjectIntPair.of("1_20_50", Bedrock_v630.CODEC.getProtocolVersion()), Conversion649_630::remapBlock) // Only changes in 1.20.60 are hard_stained_glass (an EDU only block) .put(ObjectIntPair.of("1_20_60", Bedrock_v649.CODEC.getProtocolVersion()), Conversion662_649::remapBlock) - .put(ObjectIntPair.of("1_20_70", Bedrock_v662.CODEC.getProtocolVersion()), tag -> tag) + .put(ObjectIntPair.of("1_20_70", Bedrock_v662.CODEC.getProtocolVersion()), Conversion671_662::remapBlock) + .put(ObjectIntPair.of("1_20_80", Bedrock_v671.CODEC.getProtocolVersion()), tag -> tag) .build(); // We can keep this strong as nothing should be garbage collected diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion662_649.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion662_649.java index cddeae7bf..0fe1610f2 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion662_649.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion662_649.java @@ -44,6 +44,8 @@ public class Conversion662_649 { static GeyserMappingItem remapItem(@SuppressWarnings("unused") Item item, GeyserMappingItem mapping) { + mapping = Conversion671_662.remapItem(item, mapping); + String identifer = mapping.getBedrockIdentifier(); if (identifer.equals("minecraft:grass_block")) { @@ -93,6 +95,8 @@ public class Conversion662_649 { } static NbtMap remapBlock(NbtMap tag) { + tag = Conversion671_662.remapBlock(tag); + final String name = tag.getString("name"); if (!NEW_BLOCKS.contains(name)) { diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion671_662.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion671_662.java new file mode 100644 index 000000000..2c6db7567 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion671_662.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2019-2024 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 org.cloudburstmc.nbt.NbtMap; +import org.geysermc.geyser.item.type.Item; +import org.geysermc.geyser.registry.type.GeyserMappingItem; + +import java.util.List; +import java.util.stream.Stream; + +public class Conversion671_662 { + private static final List NEW_CORAL_FANS = List.of("minecraft:tube_coral_fan", "minecraft:brain_coral_fan", "minecraft:bubble_coral_fan", "minecraft:fire_coral_fan", "minecraft:horn_coral_fan"); + private static final List NEW_DEAD_CORAL_FANS = List.of("minecraft:dead_tube_coral_fan", "minecraft:dead_brain_coral_fan", "minecraft:dead_bubble_coral_fan", "minecraft:dead_fire_coral_fan", "minecraft:dead_horn_coral_fan"); + private static final List NEW_FLOWERS = List.of("minecraft:poppy", "minecraft:blue_orchid", "minecraft:allium", "minecraft:azure_bluet", "minecraft:red_tulip", "minecraft:orange_tulip", "minecraft:white_tulip", "minecraft:pink_tulip", "minecraft:oxeye_daisy", "minecraft:cornflower", "minecraft:lily_of_the_valley"); + private static final List NEW_SAPLINGS = List.of("minecraft:oak_sapling", "minecraft:spruce_sapling", "minecraft:birch_sapling", "minecraft:jungle_sapling", "minecraft:acacia_sapling", "minecraft:dark_oak_sapling", "minecraft:bamboo_sapling"); + private static final List NEW_BLOCKS = Stream.of(NEW_CORAL_FANS, NEW_DEAD_CORAL_FANS, NEW_FLOWERS, NEW_SAPLINGS).flatMap(List::stream).toList(); + + static GeyserMappingItem remapItem(@SuppressWarnings("unused") Item item, GeyserMappingItem mapping) { + String identifer = mapping.getBedrockIdentifier(); + + if (!NEW_BLOCKS.contains(identifer)) { + return mapping; + } + + if (NEW_FLOWERS.contains(identifer)) { + switch (identifer) { + case "minecraft:poppy" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(0); } + case "minecraft:blue_orchid" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(1); } + case "minecraft:allium" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(2); } + case "minecraft:azure_bluet" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(3); } + case "minecraft:red_tulip" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(4); } + case "minecraft:orange_tulip" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(5); } + case "minecraft:white_tulip" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(6); } + case "minecraft:pink_tulip" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(7); } + case "minecraft:oxeye_daisy" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(8); } + case "minecraft:cornflower" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(9); } + case "minecraft:lily_of_the_valley" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(10); } + } + } + + if (NEW_SAPLINGS.contains(identifer)) { + switch (identifer) { + case "minecraft:oak_sapling" -> { return mapping.withBedrockIdentifier("minecraft:sapling").withBedrockData(0); } + case "minecraft:spruce_sapling" -> { return mapping.withBedrockIdentifier("minecraft:sapling").withBedrockData(1); } + case "minecraft:birch_sapling" -> { return mapping.withBedrockIdentifier("minecraft:sapling").withBedrockData(2); } + case "minecraft:jungle_sapling" -> { return mapping.withBedrockIdentifier("minecraft:sapling").withBedrockData(3); } + case "minecraft:acacia_sapling" -> { return mapping.withBedrockIdentifier("minecraft:sapling").withBedrockData(4); } + case "minecraft:dark_oak_sapling" -> { return mapping.withBedrockIdentifier("minecraft:sapling").withBedrockData(5); } + } + } + + if (NEW_CORAL_FANS.contains(identifer)) { + switch (identifer) { + case "minecraft:tube_coral_fan" -> { return mapping.withBedrockIdentifier("minecraft:coral_fan").withBedrockData(0); } + case "minecraft:brain_coral_fan" -> { return mapping.withBedrockIdentifier("minecraft:coral_fan").withBedrockData(1); } + case "minecraft:bubble_coral_fan" -> { return mapping.withBedrockIdentifier("minecraft:coral_fan").withBedrockData(2); } + case "minecraft:fire_coral_fan" -> { return mapping.withBedrockIdentifier("minecraft:coral_fan").withBedrockData(3); } + case "minecraft:horn_coral_fan" -> { return mapping.withBedrockIdentifier("minecraft:coral_fan").withBedrockData(4); } + } + } + + if (NEW_DEAD_CORAL_FANS.contains(identifer)) { + switch (identifer) { + case "minecraft:dead_tube_coral_fan" -> { return mapping.withBedrockIdentifier("minecraft:coral_fan_dead").withBedrockData(0); } + case "minecraft:dead_brain_coral_fan" -> { return mapping.withBedrockIdentifier("minecraft:coral_fan_dead").withBedrockData(1); } + case "minecraft:dead_bubble_coral_fan" -> { return mapping.withBedrockIdentifier("minecraft:coral_fan_dead").withBedrockData(2); } + case "minecraft:dead_fire_coral_fan" -> { return mapping.withBedrockIdentifier("minecraft:coral_fan_dead").withBedrockData(3); } + case "minecraft:dead_horn_coral_fan" -> { return mapping.withBedrockIdentifier("minecraft:coral_fan_dead").withBedrockData(4); } + } + } + + return mapping; + } + + static NbtMap remapBlock(NbtMap tag) { + final String name = tag.getString("name"); + + if (!NEW_BLOCKS.contains(name)) { + return tag; + } + + if (name.equals("minecraft:bamboo_sapling")) { + NbtMap states = tag.getCompound("states") + .toBuilder() + .putString("sapling_type", "oak") + .build(); + + return tag.toBuilder().putCompound("states", states).build(); + } + + String replacement; + + if (NEW_SAPLINGS.contains(name)) { + replacement = "minecraft:sapling"; + String saplingType = name.replaceAll("minecraft:|_sapling", "");; + + NbtMap states = tag.getCompound("states") + .toBuilder() + .putString("sapling_type", saplingType) + .build(); + + return tag.toBuilder().putString("name", replacement).putCompound("states", states).build(); + } + + if (NEW_FLOWERS.contains(name)) { + replacement = "minecraft:red_flower"; + String flowerType; + + switch (name) { + case "minecraft:poppy" -> flowerType = "poppy"; + case "minecraft:blue_orchid" -> flowerType = "orchid"; + case "minecraft:allium" -> flowerType = "allium"; + case "minecraft:azure_bluet" -> flowerType = "houstonia"; + case "minecraft:red_tulip" -> flowerType = "tulip_red"; + case "minecraft:orange_tulip" -> flowerType = "tulip_orange"; + case "minecraft:white_tulip" -> flowerType = "tulip_white"; + case "minecraft:pink_tulip" -> flowerType = "tulip_pink"; + case "minecraft:oxeye_daisy" -> flowerType = "oxeye"; + case "minecraft:cornflower" -> flowerType = "cornflower"; + case "minecraft:lily_of_the_valley" -> flowerType = "lily_of_the_valley"; + default -> throw new IllegalStateException("Unexpected value: " + name); + } + + NbtMap states = tag.getCompound("states") + .toBuilder() + .putString("flower_type", flowerType) + .build(); + + return tag.toBuilder().putString("name", replacement).putCompound("states", states).build(); + } + + boolean isLiveCoralFan = NEW_CORAL_FANS.contains(name); + boolean isDeadCoralFan = NEW_DEAD_CORAL_FANS.contains(name); + + if (isLiveCoralFan || isDeadCoralFan) { + replacement = isLiveCoralFan ? "minecraft:coral_fan" : "minecraft:coral_fan_dead"; + String coralColor; + + switch (name) { + case "minecraft:tube_coral_fan", "minecraft:dead_tube_coral_fan" -> coralColor = "blue"; + case "minecraft:brain_coral_fan", "minecraft:dead_brain_coral_fan" -> coralColor = "pink"; + case "minecraft:bubble_coral_fan", "minecraft:dead_bubble_coral_fan" -> coralColor = "purple"; + case "minecraft:fire_coral_fan", "minecraft:dead_fire_coral_fan" -> coralColor = "yellow"; + case "minecraft:horn_coral_fan", "minecraft:dead_horn_coral_fan" -> coralColor = "red"; + default -> throw new IllegalStateException("Unexpected value: " + name); + } + + NbtMap states = tag.getCompound("states") + .toBuilder() + .putString("coral_color", coralColor) + .build(); + + return tag.toBuilder().putString("name", replacement).putCompound("states", states).build(); + } + + return tag; + } +} \ No newline at end of file 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 708f92dc5..5b64da7a1 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 @@ -42,6 +42,7 @@ import org.cloudburstmc.protocol.bedrock.codec.v622.Bedrock_v622; import org.cloudburstmc.protocol.bedrock.codec.v630.Bedrock_v630; import org.cloudburstmc.protocol.bedrock.codec.v649.Bedrock_v649; import org.cloudburstmc.protocol.bedrock.codec.v662.Bedrock_v662; +import org.cloudburstmc.protocol.bedrock.codec.v671.Bedrock_v671; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; @@ -93,7 +94,8 @@ public class ItemRegistryPopulator { paletteVersions.add(new PaletteVersion("1_20_40", Bedrock_v622.CODEC.getProtocolVersion(), Collections.emptyMap(), Conversion630_622::remapItem)); paletteVersions.add(new PaletteVersion("1_20_50", Bedrock_v630.CODEC.getProtocolVersion(), Collections.emptyMap(), Conversion649_630::remapItem)); paletteVersions.add(new PaletteVersion("1_20_60", Bedrock_v649.CODEC.getProtocolVersion(), Collections.emptyMap(), Conversion662_649::remapItem)); - paletteVersions.add(new PaletteVersion("1_20_70", Bedrock_v662.CODEC.getProtocolVersion())); + paletteVersions.add(new PaletteVersion("1_20_70", Bedrock_v662.CODEC.getProtocolVersion(), Collections.emptyMap(), Conversion671_662::remapItem)); + paletteVersions.add(new PaletteVersion("1_20_80", Bedrock_v671.CODEC.getProtocolVersion())); GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap(); 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 f8929c900..5e4d5fc7a 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 @@ -173,7 +173,7 @@ public class RecipeRegistryPopulator { /* Convert end */ return ShapedRecipeData.shaped(uuid.toString(), shape.get(0).length(), shape.size(), - inputs.stream().map(ItemDescriptorWithCount::fromItem).toList(), Collections.singletonList(output), uuid, "crafting_table", 0, netId); + inputs.stream().map(ItemDescriptorWithCount::fromItem).toList(), Collections.singletonList(output), uuid, "crafting_table", 0, netId, false); } List inputs = new ObjectArrayList<>(); for (JsonNode entry : node.get("inputs")) { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java index 7beb37af9..94c69b780 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java @@ -162,7 +162,7 @@ public class JavaUpdateRecipesTranslator extends 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 literal 0 HcmV?d00001 diff --git a/core/src/main/resources/bedrock/creative_items.1_20_80.json b/core/src/main/resources/bedrock/creative_items.1_20_80.json new file mode 100644 index 000000000..02feea34b --- /dev/null +++ b/core/src/main/resources/bedrock/creative_items.1_20_80.json @@ -0,0 +1,5812 @@ +{ + "items": [ + { + "id": "minecraft:oak_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQFAAAACAQAbmFtZRQAbWluZWNyYWZ0Om9ha19wbGFua3MECQBuYW1lX2hhc2ilMDLR92rQ4wMKAG5ldHdvcmtfaWS2GotyCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:spruce_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTiAwAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9wbGFua3MECQBuYW1lX2hhc2iumBkmFGFE8gMKAG5ldHdvcmtfaWSo8TFgCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:birch_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTjAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX3BsYW5rcwQJAG5hbWVfaGFzaLrrAKJqV2WFAwoAbmV0d29ya19pZL+e3ZAKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:jungle_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTkAwAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9wbGFua3MECQBuYW1lX2hhc2iBM3k4T3FAugMKAG5ldHdvcmtfaWSXUmBCCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:acacia_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTlAwAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9wbGFua3MECQBuYW1lX2hhc2g60edJxO5/aAMKAG5ldHdvcmtfaWTUXozECgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:dark_oak_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTmAwAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX3BsYW5rcwQJAG5hbWVfaGFzaAr64wkQ9cA7AwoAbmV0d29ya19pZFbMeR0KBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:mangrove_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTlAgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX3BsYW5rcwQJAG5hbWVfaGFzaPvLtcEA0F8xAwoAbmV0d29ya19pZEvnlCYKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:cherry_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAwAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9wbGFua3MECQBuYW1lX2hhc2hNIvVh/lVW7gMKAG5ldHdvcmtfaWQTXpRoCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:bamboo_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT9AgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19wbGFua3MECQBuYW1lX2hhc2gYnjNz7SCCjgMKAG5ldHdvcmtfaWTi8ySSCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:bamboo_mosaic", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT8AgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19tb3NhaWMECQBuYW1lX2hhc2izSEgiMKOp/AMKAG5ldHdvcmtfaWQZ/p8xCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:crimson_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTxAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fcGxhbmtzBAkAbmFtZV9oYXNoJc5IKqNXJnwDCgBuZXR3b3JrX2lkwtJDdQoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:warped_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTyAQAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9wbGFua3MECQBuYW1lX2hhc2g3yGXEWhe6LgMKAG5ldHdvcmtfaWStTABvCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWSE4JosCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCwBjb2JibGVzdG9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWTUvV6XCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEQBtb3NzeV9jb2JibGVzdG9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWT4opb2CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBwBncmFuaXRlCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQAMQTVCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBwBkaW9yaXRlCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQIbDOcCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCABhbmRlc2l0ZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWSZKhusCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCQBzYW5kc3RvbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWSp4zgCCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlDQByZWRfc2FuZHN0b25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRbqVHTCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCwBzdG9uZV9icmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRr0ZT/CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEQBtb3NzeV9zdG9uZV9icmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRnLis3CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBQBicmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQNLzfSCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlDABuZXRoZXJfYnJpY2sIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQ5h0xwCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEAByZWRfbmV0aGVyX2JyaWNrCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWS9J0B2CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCQBlbmRfYnJpY2sIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRPbkJeCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCgBwcmlzbWFyaW5lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:blackstone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQUAgAACAQAbmFtZRkAbWluZWNyYWZ0OmJsYWNrc3RvbmVfd2FsbAQJAG5hbWVfaGFzaMP8XppUSU1RAwoAbmV0d29ya19pZMbeBBsKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:polished_blackstone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQoAgAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfd2FsbAQJAG5hbWVfaGFzaP6SwV08YwzAAwoAbmV0d29ya19pZAJLsz8KBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:polished_blackstone_brick_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQVAgAACAQAbmFtZSgAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfd2FsbAQJAG5hbWVfaGFzaBBIDZbHxiEzAwoAbmV0d29ya19pZEbLV8cKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:cobbled_deepslate_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR9AgAACAQAbmFtZSAAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3dhbGwECQBuYW1lX2hhc2iECY5oKxeT+gMKAG5ldHdvcmtfaWRCnPrFCgYAc3RhdGVzCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:deepslate_tile_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3dhbGwECQBuYW1lX2hhc2jz7N+PeuEXgQMKAG5ldHdvcmtfaWTqw4s4CgYAc3RhdGVzCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:polished_deepslate_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSBAgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV93YWxsBAkAbmFtZV9oYXNoHxjTdj9pevMDCgBuZXR3b3JrX2lkIvBYYwoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:deepslate_brick_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSJAgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja193YWxsBAkAbmFtZV9oYXNoEs3EQrjroyEDCgBuZXR3b3JrX2lkwlrCGwoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:mud_brick_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTgAgAACAQAbmFtZRgAbWluZWNyYWZ0Om11ZF9icmlja193YWxsBAkAbmFtZV9oYXNov9b98ATpUSwDCgBuZXR3b3JrX2lkH/1WZQoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:oak_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRVAAAACAQAbmFtZRMAbWluZWNyYWZ0Om9ha19mZW5jZQQJAG5hbWVfaGFzaGEmid7AaCWRAwoAbmV0d29ya19pZDvPEXcKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:spruce_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRCAwAACAQAbmFtZRYAbWluZWNyYWZ0OnNwcnVjZV9mZW5jZQQJAG5hbWVfaGFzaPQCm+aX1ZQeAwoAbmV0d29ya19pZD1QUEoKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:birch_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ/AwAACAQAbmFtZRUAbWluZWNyYWZ0OmJpcmNoX2ZlbmNlBAkAbmFtZV9oYXNo6CJ2ATpANfgDCgBuZXR3b3JrX2lkmCUV2QoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:jungle_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRBAwAACAQAbmFtZRYAbWluZWNyYWZ0Omp1bmdsZV9mZW5jZQQJAG5hbWVfaGFzaOX4cD9uAmsdAwoAbmV0d29ya19pZHz1VxkKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:acacia_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ+AwAACAQAbmFtZRYAbWluZWNyYWZ0OmFjYWNpYV9mZW5jZQQJAG5hbWVfaGFzaGjn+RlKVDH6AwoAbmV0d29ya19pZNVGubwKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:dark_oak_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRAAwAACAQAbmFtZRgAbWluZWNyYWZ0OmRhcmtfb2FrX2ZlbmNlBAkAbmFtZV9oYXNoGPj0gCgM0c0DCgBuZXR3b3JrX2lk2w+gEwoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:mangrove_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTqAgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hbmdyb3ZlX2ZlbmNlBAkAbmFtZV9oYXNowwAd7tPu9bsDCgBuZXR3b3JrX2lkKEcd0goGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:cherry_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQTAwAACAQAbmFtZRYAbWluZWNyYWZ0OmNoZXJyeV9mZW5jZQQJAG5hbWVfaGFzaFmtUfHfTxcxAwoAbmV0d29ya19pZPCBxAIKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:bamboo_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQCAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJhbWJvb19mZW5jZQQJAG5hbWVfaGFzaCKRbxfXsfkiAwoAbmV0d29ya19pZJNXKFcKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:nether_brick_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRxAAAACAQAbmFtZRwAbWluZWNyYWZ0Om5ldGhlcl9icmlja19mZW5jZQQJAG5hbWVfaGFzaA6030ngawxcAwoAbmV0d29ya19pZLnjLF4KBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:crimson_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT/AQAACAQAbmFtZRcAbWluZWNyYWZ0OmNyaW1zb25fZmVuY2UECQBuYW1lX2hhc2jhUhKv1HGj9AMKAG5ldHdvcmtfaWR3OH3OCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:warped_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQAAgAACAQAbmFtZRYAbWluZWNyYWZ0OndhcnBlZF9mZW5jZQQJAG5hbWVfaGFzaJfb3/YuKmOWAwoAbmV0d29ya19pZCpaGC8KBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRrAAAACAQAbmFtZRQAbWluZWNyYWZ0OmZlbmNlX2dhdGUECQBuYW1lX2hhc2hTxpjEDmRzAwMKAG5ldHdvcmtfaWR+T9kTCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:spruce_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS3AAAACAQAbmFtZRsAbWluZWNyYWZ0OnNwcnVjZV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoanTVB84HRbkDCgBuZXR3b3JrX2lkEnw5egoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:birch_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS4AAAACAQAbmFtZRoAbWluZWNyYWZ0OmJpcmNoX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2jmfPklI8azSwMKAG5ldHdvcmtfaWQL77/BCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:jungle_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS5AAAACAQAbmFtZRsAbWluZWNyYWZ0Omp1bmdsZV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNobYVQkfBomIcDCgBuZXR3b3JrX2lkA1zgtgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:acacia_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS7AAAACAQAbmFtZRsAbWluZWNyYWZ0OmFjYWNpYV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoZnrLUx/XSekDCgBuZXR3b3JrX2lkHg/kTgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:dark_oak_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS6AAAACAQAbmFtZR0AbWluZWNyYWZ0OmRhcmtfb2FrX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2j2PTvdJJHcVQMKAG5ldHdvcmtfaWTwjOCeCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:mangrove_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTrAgAACAQAbmFtZR0AbWluZWNyYWZ0Om1hbmdyb3ZlX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2i/kOhBKiI/dAMKAG5ldHdvcmtfaWSfweCSCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:cherry_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQUAwAACAQAbmFtZRsAbWluZWNyYWZ0OmNoZXJyeV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoKWLgCk0z+PsDCgBuZXR3b3JrX2lk/9bTZQoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:bamboo_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAwAACAQAbmFtZRsAbWluZWNyYWZ0OmJhbWJvb19mZW5jZV9nYXRlBAkAbmFtZV9oYXNopH1JrUgwdIADCgBuZXR3b3JrX2lkzIpPywoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:crimson_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQBAgAACAQAbmFtZRwAbWluZWNyYWZ0OmNyaW1zb25fZmVuY2VfZ2F0ZQQJAG5hbWVfaGFzaHE3Gfd0Z2d2AwoAbmV0d29ya19pZDQzVbEKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQsAaW5fd2FsbF9iaXQAAQgAb3Blbl9iaXQAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:warped_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQCAgAACAQAbmFtZRsAbWluZWNyYWZ0OndhcnBlZF9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoy0oIBjDIG4kDCgBuZXR3b3JrX2lkkf+/3QoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:normal_stone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSzAQAACAQAbmFtZR0AbWluZWNyYWZ0Om5vcm1hbF9zdG9uZV9zdGFpcnMECQBuYW1lX2hhc2hAEktZZOkGIwMKAG5ldHdvcmtfaWQeH1ALCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:stone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRDAAAACAQAbmFtZRYAbWluZWNyYWZ0OnN0b25lX3N0YWlycwQJAG5hbWVfaGFzaNRjqVC5GRVDAwoAbmV0d29ya19pZDcCv+MKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:mossy_cobblestone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSyAQAACAQAbmFtZSIAbWluZWNyYWZ0Om1vc3N5X2NvYmJsZXN0b25lX3N0YWlycwQJAG5hbWVfaGFzaMVSTq5z9n1RAwoAbmV0d29ya19pZFIfrhkKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:oak_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ1AAAACAQAbmFtZRQAbWluZWNyYWZ0Om9ha19zdGFpcnMECQBuYW1lX2hhc2jk/HFzdXy0FQMKAG5ldHdvcmtfaWQJjyzBCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:spruce_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSGAAAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9zdGFpcnMECQBuYW1lX2hhc2iznygw7uBPBQMKAG5ldHdvcmtfaWTv+is3CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:birch_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSHAAAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX3N0YWlycwQJAG5hbWVfaGFzaPfhbL619a3GAwoAbmV0d29ya19pZFyPlHAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:jungle_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSIAAAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9zdGFpcnMECQBuYW1lX2hhc2jodJsHUbOVxQMKAG5ldHdvcmtfaWR0z5d4CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:acacia_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSjAAAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9zdGFpcnMECQBuYW1lX2hhc2h3x1NmD43IqQMKAG5ldHdvcmtfaWS7Jwz6CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:dark_oak_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSkAAAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX3N0YWlycwQJAG5hbWVfaGFzaMfwkbYPbNmAAwoAbmV0d29ya19pZCmBYKAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:mangrove_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTnAgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX3N0YWlycwQJAG5hbWVfaGFzaNpUDY+uGMpyAwoAbmV0d29ya19pZChzUAsKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:cherry_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQcAwAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9zdGFpcnMECQBuYW1lX2hhc2jMtr0v9JY4zwMKAG5ldHdvcmtfaWRQwq31CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:bamboo_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT/AgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19zdGFpcnMECQBuYW1lX2hhc2jFOzWL8PalKwMKAG5ldHdvcmtfaWTVPh42CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:bamboo_mosaic_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQKAwAACAQAbmFtZR4AbWluZWNyYWZ0OmJhbWJvb19tb3NhaWNfc3RhaXJzBAkAbmFtZV9oYXNoNLPiveSHPaoDCgBuZXR3b3JrX2lk44PHjgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:stone_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRtAAAACAQAbmFtZRwAbWluZWNyYWZ0OnN0b25lX2JyaWNrX3N0YWlycwQJAG5hbWVfaGFzaN6tQViRo5cwAwoAbmV0d29ya19pZDMyMgIKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:mossy_stone_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSuAQAACAQAbmFtZSIAbWluZWNyYWZ0Om1vc3N5X3N0b25lX2JyaWNrX3N0YWlycwQJAG5hbWVfaGFzaIB/Zv5YBPuYAwoAbmV0d29ya19pZANTOsMKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:sandstone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSAAAAACAQAbmFtZRoAbWluZWNyYWZ0OnNhbmRzdG9uZV9zdGFpcnMECQBuYW1lX2hhc2hOyA0BoYUOPQMKAG5ldHdvcmtfaWSV/834CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:smooth_sandstone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSwAQAACAQAbmFtZSEAbWluZWNyYWZ0OnNtb290aF9zYW5kc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNoB+CuCd8Ruz8DCgBuZXR3b3JrX2lksR+m8QoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:red_sandstone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS0AAAACAQAbmFtZR4AbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNoPs0LpHPL24YDCgBuZXR3b3JrX2lkLYVt3woGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:smooth_red_sandstone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAQAACAQAbmFtZSUAbWluZWNyYWZ0OnNtb290aF9yZWRfc2FuZHN0b25lX3N0YWlycwQJAG5hbWVfaGFzaBvjtQv5pf+MAwoAbmV0d29ya19pZMHNND8KBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:granite_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAQAACAQAbmFtZRgAbWluZWNyYWZ0OmdyYW5pdGVfc3RhaXJzBAkAbmFtZV9oYXNoGzpvtoqKQjgDCgBuZXR3b3JrX2lkPkcB1goGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:polished_granite_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSrAQAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2dyYW5pdGVfc3RhaXJzBAkAbmFtZV9oYXNo3PvbSfEQklIDCgBuZXR3b3JrX2lkMmEm3AoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:diorite_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSpAQAACAQAbmFtZRgAbWluZWNyYWZ0OmRpb3JpdGVfc3RhaXJzBAkAbmFtZV9oYXNoi73T8VQuZmcDCgBuZXR3b3JrX2lk6i6nBQoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:polished_diorite_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSsAQAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2Rpb3JpdGVfc3RhaXJzBAkAbmFtZV9oYXNoFKRJd5Wk5L0DCgBuZXR3b3JrX2lkbt2ioAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:andesite_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSqAQAACAQAbmFtZRkAbWluZWNyYWZ0OmFuZGVzaXRlX3N0YWlycwQJAG5hbWVfaGFzaO5w2FKBw76EAwoAbmV0d29ya19pZKhXEgUKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:polished_andesite_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWStAQAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2FuZGVzaXRlX3N0YWlycwQJAG5hbWVfaGFzaNcZZ/zmLInIAwoAbmV0d29ya19pZJTHrlEKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRsAAAACAQAbmFtZRYAbWluZWNyYWZ0OmJyaWNrX3N0YWlycwQJAG5hbWVfaGFzaMyt+cRDk5O2AwoAbmV0d29ya19pZNeMh58KBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:nether_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRyAAAACAQAbmFtZR0AbWluZWNyYWZ0Om5ldGhlcl9icmlja19zdGFpcnMECQBuYW1lX2hhc2jRqIoOXgifBAMKAG5ldHdvcmtfaWQDiw5yCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:red_nether_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS3AQAACAQAbmFtZSEAbWluZWNyYWZ0OnJlZF9uZXRoZXJfYnJpY2tfc3RhaXJzBAkAbmFtZV9oYXNogQvosSbcj7kDCgBuZXR3b3JrX2lkx2IMtAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:end_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSxAQAACAQAbmFtZRoAbWluZWNyYWZ0OmVuZF9icmlja19zdGFpcnMECQBuYW1lX2hhc2hmlAk+QhsUsQMKAG5ldHdvcmtfaWTN7KFaCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:quartz_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWScAAAACAQAbmFtZRcAbWluZWNyYWZ0OnF1YXJ0el9zdGFpcnMECQBuYW1lX2hhc2hmvpvOqGi6egMKAG5ldHdvcmtfaWRmUTh7CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:smooth_quartz_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS4AQAACAQAbmFtZR4AbWluZWNyYWZ0OnNtb290aF9xdWFydHpfc3RhaXJzBAkAbmFtZV9oYXNoNZZ9rX0qZOsDCgBuZXR3b3JrX2lkzsgQyQoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:purpur_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTLAAAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnB1cl9zdGFpcnMECQBuYW1lX2hhc2ifwDxeezXD7gMKAG5ldHdvcmtfaWTT+rxiCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:prismarine_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQBAQAACAQAbmFtZRsAbWluZWNyYWZ0OnByaXNtYXJpbmVfc3RhaXJzBAkAbmFtZV9oYXNooTHSZ+IrYtcDCgBuZXR3b3JrX2lkxTJfeAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:dark_prismarine_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQCAQAACAQAbmFtZSAAbWluZWNyYWZ0OmRhcmtfcHJpc21hcmluZV9zdGFpcnMECQBuYW1lX2hhc2hIciLmam4o4AMKAG5ldHdvcmtfaWTVu7TCCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:prismarine_bricks_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAQAACAQAbmFtZSIAbWluZWNyYWZ0OnByaXNtYXJpbmVfYnJpY2tzX3N0YWlycwQJAG5hbWVfaGFzaNIjq1oBlZMMAwoAbmV0d29ya19pZGEFwLYKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:crimson_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT9AQAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fc3RhaXJzBAkAbmFtZV9oYXNoZJqIzCBpCq4DCgBuZXR3b3JrX2lktXE00AoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:warped_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT+AQAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9zdGFpcnMECQBuYW1lX2hhc2hOkY27jLD4RQMKAG5ldHdvcmtfaWQ+E5VrCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:blackstone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQTAgAACAQAbmFtZRsAbWluZWNyYWZ0OmJsYWNrc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNokdoUb76p9McDCgBuZXR3b3JrX2lk5fWI5goGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:polished_blackstone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQjAgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNolCFtFIE8MmADCgBuZXR3b3JrX2lkGTf7sgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:polished_blackstone_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQSAgAACAQAbmFtZSoAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfc3RhaXJzBAkAbmFtZV9oYXNonks6UlfpOmkDCgBuZXR3b3JrX2lkgYeOdAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAgAACAQAbmFtZRsAbWluZWNyYWZ0OmN1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoHfoAXYq5G3MDCgBuZXR3b3JrX2lkeetf7woGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:exposed_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAgAACAQAbmFtZSMAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcl9zdGFpcnMECQBuYW1lX2hhc2howneQGtZ9cgMKAG5ldHdvcmtfaWSg73zdCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:weathered_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAgAACAQAbmFtZSUAbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyX3N0YWlycwQJAG5hbWVfaGFzaP+R5loXxrVgAwoAbmV0d29ya19pZOnbRf4KBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:oxidized_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRkAgAACAQAbmFtZSQAbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNo6Jeoq5rsPxsDCgBuZXR3b3JrX2lkmRjDnQoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:waxed_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRlAgAACAQAbmFtZSEAbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoh07CQj0/SR8DCgBuZXR3b3JrX2lkmYqoqAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:waxed_exposed_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRmAgAACAQAbmFtZSkAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcl9zdGFpcnMECQBuYW1lX2hhc2guVct1ilmxTwMKAG5ldHdvcmtfaWQgCPROCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:waxed_weathered_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRnAgAACAQAbmFtZSsAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyX3N0YWlycwQJAG5hbWVfaGFzaPXC8Sz/phCpAwoAbmV0d29ya19pZHlwHVsKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:waxed_oxidized_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS/AgAACAQAbmFtZSoAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoaqGdkuhxVZUDCgBuZXR3b3JrX2lkYQXzzgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:cobbled_deepslate_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR8AgAACAQAbmFtZSIAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3N0YWlycwQJAG5hbWVfaGFzaPIfa+TpyJcIAwoAbmV0d29ya19pZJUvOYIKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:deepslate_tile_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3N0YWlycwQJAG5hbWVfaGFzaGFRFzB72mN2AwoAbmV0d29ya19pZJEOgIsKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:polished_deepslate_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSAAgAACAQAbmFtZSMAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV9zdGFpcnMECQBuYW1lX2hhc2iNCYxVik9sGAMKAG5ldHdvcmtfaWSRVPnYCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:deepslate_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSIAgAACAQAbmFtZSAAbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja19zdGFpcnMECQBuYW1lX2hhc2hIasOahEf83wMKAG5ldHdvcmtfaWQ1qEDCCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:mud_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTfAgAACAQAbmFtZRoAbWluZWNyYWZ0Om11ZF9icmlja19zdGFpcnMECQBuYW1lX2hhc2gt3qxK1NWajAMKAG5ldHdvcmtfaWSm9N3MCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:wooden_door" + }, + { + "id": "minecraft:spruce_door" + }, + { + "id": "minecraft:birch_door" + }, + { + "id": "minecraft:jungle_door" + }, + { + "id": "minecraft:acacia_door" + }, + { + "id": "minecraft:dark_oak_door" + }, + { + "id": "minecraft:mangrove_door" + }, + { + "id": "minecraft:cherry_door" + }, + { + "id": "minecraft:bamboo_door" + }, + { + "id": "minecraft:iron_door" + }, + { + "id": "minecraft:crimson_door" + }, + { + "id": "minecraft:warped_door" + }, + { + "id": "minecraft:trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRgAAAACAQAbmFtZRIAbWluZWNyYWZ0OnRyYXBkb29yBAkAbmFtZV9oYXNotYiAJGtN0xADCgBuZXR3b3JrX2lkyTAWkAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:spruce_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSUAQAACAQAbmFtZRkAbWluZWNyYWZ0OnNwcnVjZV90cmFwZG9vcgQJAG5hbWVfaGFzaOwlfbgBkUW4AwoAbmV0d29ya19pZPHy1K0KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:birch_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSRAQAACAQAbmFtZRgAbWluZWNyYWZ0OmJpcmNoX3RyYXBkb29yBAkAbmFtZV9oYXNoSLtLweOLJ7wDCgBuZXR3b3JrX2lkeJWDfgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:jungle_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSTAQAACAQAbmFtZRkAbWluZWNyYWZ0Omp1bmdsZV90cmFwZG9vcgQJAG5hbWVfaGFzaDP/TnM9wyCIAwoAbmV0d29ya19pZEy2fJoKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:acacia_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSQAQAACAQAbmFtZRkAbWluZWNyYWZ0OmFjYWNpYV90cmFwZG9vcgQJAG5hbWVfaGFzaMj8xi3vmEKOAwoAbmV0d29ya19pZOHj8E8KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:dark_oak_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSSAQAACAQAbmFtZRsAbWluZWNyYWZ0OmRhcmtfb2FrX3RyYXBkb29yBAkAbmFtZV9oYXNomB2GGJQ2aOMDCgBuZXR3b3JrX2lko5ZHTwoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:mangrove_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTvAgAACAQAbmFtZRsAbWluZWNyYWZ0Om1hbmdyb3ZlX3RyYXBkb29yBAkAbmFtZV9oYXNooV3kQsQUUmkDCgBuZXR3b3JrX2lkkF/mxAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:cherry_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQeAwAACAQAbmFtZRkAbWluZWNyYWZ0OmNoZXJyeV90cmFwZG9vcgQJAG5hbWVfaGFzaH/PefpfdHgtAwoAbmV0d29ya19pZOA7eNgKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:bamboo_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQHAwAACAQAbmFtZRkAbWluZWNyYWZ0OmJhbWJvb190cmFwZG9vcgQJAG5hbWVfaGFzaJrEOpsTwtKCAwoAbmV0d29ya19pZLvbPz8KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:iron_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSnAAAACAQAbmFtZRcAbWluZWNyYWZ0Omlyb25fdHJhcGRvb3IECQBuYW1lX2hhc2gwA+IumsEiGQMKAG5ldHdvcmtfaWTvSVl/CgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAEPAHVwc2lkZV9kb3duX2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:crimson_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT1AQAACAQAbmFtZRoAbWluZWNyYWZ0OmNyaW1zb25fdHJhcGRvb3IECQBuYW1lX2hhc2jHXufTnwUkYgMKAG5ldHdvcmtfaWQLjMYVCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAEPAHVwc2lkZV9kb3duX2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:warped_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT2AQAACAQAbmFtZRkAbWluZWNyYWZ0OndhcnBlZF90cmFwZG9vcgQJAG5hbWVfaGFzaA20wG/+vkd6AwoAbmV0d29ya19pZHKR/hYKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:iron_bars", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRlAAAACAQAbmFtZRMAbWluZWNyYWZ0Omlyb25fYmFycwQJAG5hbWVfaGFzaPuefWSNAe56AwoAbmV0d29ya19pZN2LB5IKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQUAAAACAQAbmFtZQ8AbWluZWNyYWZ0OmdsYXNzBAkAbmFtZV9oYXNowGJByfWff6gDCgBuZXR3b3JrX2lk0hdLNwoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:white_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTxAAAACAQAbmFtZR0AbWluZWNyYWZ0OndoaXRlX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2iHubqoMbu9fAMKAG5ldHdvcmtfaWRndBrUCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:light_gray_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSnAwAACAQAbmFtZSIAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaKKa+LrRsHQhAwoAbmV0d29ya19pZEv2giYKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:gray_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSmAwAACAQAbmFtZRwAbWluZWNyYWZ0OmdyYXlfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaIETy7Y/HZREAwoAbmV0d29ya19pZDomVrUKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:black_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSuAwAACAQAbmFtZR0AbWluZWNyYWZ0OmJsYWNrX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2iV6BCwpfDMmwMKAG5ldHdvcmtfaWSV7doJCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:brown_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSrAwAACAQAbmFtZR0AbWluZWNyYWZ0OmJyb3duX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2igsEiq5np8JgMKAG5ldHdvcmtfaWRMzE/lCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:red_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWStAwAACAQAbmFtZRsAbWluZWNyYWZ0OnJlZF9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNoCa2J12/lQoIDCgBuZXR3b3JrX2lk283lWAoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:orange_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSgAwAACAQAbmFtZR4AbWluZWNyYWZ0Om9yYW5nZV9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNozgjAuvzhxGsDCgBuZXR3b3JrX2lkW5CkhQoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:yellow_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSjAwAACAQAbmFtZR4AbWluZWNyYWZ0OnllbGxvd19zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNo7EbHMd5WVugDCgBuZXR3b3JrX2lkkdDyXQoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:lime_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSkAwAACAQAbmFtZRwAbWluZWNyYWZ0OmxpbWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaBtZA1nZtwcFAwoAbmV0d29ya19pZDxX85UKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:green_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSsAwAACAQAbmFtZR0AbWluZWNyYWZ0OmdyZWVuX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2h91ptDgbehWwMKAG5ldHdvcmtfaWTlDhnECgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:cyan_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAwAACAQAbmFtZRwAbWluZWNyYWZ0OmN5YW5fc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaBkIYQ8nQLqbAwoAbmV0d29ya19pZOL1lHsKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:light_blue_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSiAwAACAQAbmFtZSIAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaLt05n1G0fiSAwoAbmV0d29ya19pZNbwulIKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:blue_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSqAwAACAQAbmFtZRwAbWluZWNyYWZ0OmJsdWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaPhLocSfzduRAwoAbmV0d29ya19pZENsjFwKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:purple_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSpAwAACAQAbmFtZR4AbWluZWNyYWZ0OnB1cnBsZV9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNoJk0DhRO0szUDCgBuZXR3b3JrX2lkD98ZxgoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:magenta_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAwAACAQAbmFtZR8AbWluZWNyYWZ0Om1hZ2VudGFfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaFEDeFiJj3zSAwoAbmV0d29ya19pZG+iFRoKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:pink_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAwAACAQAbmFtZRwAbWluZWNyYWZ0OnBpbmtfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaDijTX87ywxhAwoAbmV0d29ya19pZKdEricKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:tinted_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRNAgAACAQAbmFtZRYAbWluZWNyYWZ0OnRpbnRlZF9nbGFzcwQJAG5hbWVfaGFzaAFZWSamk6KdAwoAbmV0d29ya19pZGSvWX8KBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRmAAAACAQAbmFtZRQAbWluZWNyYWZ0OmdsYXNzX3BhbmUECQBuYW1lX2hhc2gRSBHwNMQ4gQMKAG5ldHdvcmtfaWRGwixuCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:white_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSgAAAACAQAbmFtZSIAbWluZWNyYWZ0OndoaXRlX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaHgxQmgJVtRrAwoAbmV0d29ya19pZBEr/DYKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:light_gray_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSJAwAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNon0aQw9lNkSEDCgBuZXR3b3JrX2lk9dp5VgoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:gray_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSIAwAACAQAbmFtZSEAbWluZWNyYWZ0OmdyYXlfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNors74IIw+2MMDCgBuZXR3b3JrX2lkmrGO5woGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:black_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSQAwAACAQAbmFtZSIAbWluZWNyYWZ0OmJsYWNrX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaOK/5ZRRd+M1AwoAbmV0d29ya19pZDv++oQKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:brown_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSNAwAACAQAbmFtZSIAbWluZWNyYWZ0OmJyb3duX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaLHeGJyRFTIWAwoAbmV0d29ya19pZMz9L0wKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:red_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSPAwAACAQAbmFtZSAAbWluZWNyYWZ0OnJlZF9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2gGr4x6JheAywMKAG5ldHdvcmtfaWQBjCTmCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:orange_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSCAwAACAQAbmFtZSMAbWluZWNyYWZ0Om9yYW5nZV9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2hbHxPD2gEbEAMKAG5ldHdvcmtfaWSt/7a5CgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:yellow_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAwAACAQAbmFtZSMAbWluZWNyYWZ0OnllbGxvd19zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2g9tl4aOCyZBwMKAG5ldHdvcmtfaWTXRAS7CgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:lime_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSGAwAACAQAbmFtZSEAbWluZWNyYWZ0OmxpbWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNo3CtUyLwoGegDCgBuZXR3b3JrX2lkYJDnggoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:green_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSOAwAACAQAbmFtZSIAbWluZWNyYWZ0OmdyZWVuX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaJo6YP7IMy9SAwoAbmV0d29ya19pZHOnixoKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:cyan_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSKAwAACAQAbmFtZSEAbWluZWNyYWZ0OmN5YW5fc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoti97c6QrbLQDCgBuZXR3b3JrX2lkUqFUeQoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:light_blue_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAwAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNovDg/gQle104DCgBuZXR3b3JrX2lkFuy4MQoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:blue_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSMAwAACAQAbmFtZSEAbWluZWNyYWZ0OmJsdWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoGc57tiexbQMDCgBuZXR3b3JrX2lk1eBLUAoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:purple_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAwAACAQAbmFtZSMAbWluZWNyYWZ0OnB1cnBsZV9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2hDJHYdd0FdfQMKAG5ldHdvcmtfaWSNsdK5CgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:magenta_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAwAACAQAbmFtZSQAbWluZWNyYWZ0Om1hZ2VudGFfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNo3pcOw5bs5XoDCgBuZXR3b3JrX2lkVbOR7AoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:pink_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSHAwAACAQAbmFtZSEAbWluZWNyYWZ0OnBpbmtfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoWRhSACMWgswDCgBuZXR3b3JrX2lkIR92xwoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:ladder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRBAAAACAQAbmFtZRAAbWluZWNyYWZ0OmxhZGRlcgQJAG5hbWVfaGFzaKBhqheJVOz+AwoAbmV0d29ya19pZCgvzlsKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:scaffolding", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSkAQAACAQAbmFtZRUAbWluZWNyYWZ0OnNjYWZmb2xkaW5nBAkAbmFtZV9oYXNoYrkevrqcljwDCgBuZXR3b3JrX2lkD13mlAoGAHN0YXRlcwMJAHN0YWJpbGl0eQAAAAABDwBzdGFiaWxpdHlfY2hlY2sAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAAAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWTkNl0JCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQwAc21vb3RoX3N0b25lAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:stone_block_slab4", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkQJoxlgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNAUAc3RvbmUAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAAAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWRHh04KCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQsAY29iYmxlc3RvbmUAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkVRZB+woGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhEAbW9zc3lfY29iYmxlc3RvbmUAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:oak_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSeAAAACAQAbmFtZRIAbWluZWNyYWZ0Om9ha19zbGFiBAkAbmFtZV9oYXNoJp1Cp1M4jlwDCgBuZXR3b3JrX2lkZH6+owoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:spruce_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQjBAAACAQAbmFtZRUAbWluZWNyYWZ0OnNwcnVjZV9zbGFiBAkAbmFtZV9oYXNodQi70jB238cDCgBuZXR3b3JrX2lkrriOYQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:birch_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQkBAAACAQAbmFtZRQAbWluZWNyYWZ0OmJpcmNoX3NsYWIECQBuYW1lX2hhc2gZPpfMxoOsTAMKAG5ldHdvcmtfaWThR9jyCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:jungle_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQlBAAACAQAbmFtZRUAbWluZWNyYWZ0Omp1bmdsZV9zbGFiBAkAbmFtZV9oYXNo6gLs79NXak4DCgBuZXR3b3JrX2lk5ZiKgwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:acacia_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmBAAACAQAbmFtZRUAbWluZWNyYWZ0OmFjYWNpYV9zbGFiBAkAbmFtZV9oYXNomSdFmDnv4OUDCgBuZXR3b3JrX2lkHttaXAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:dark_oak_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQnBAAACAQAbmFtZRcAbWluZWNyYWZ0OmRhcmtfb2FrX3NsYWIECQBuYW1lX2hhc2hJjTohRFyhIQMKAG5ldHdvcmtfaWRMzDTyCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:mangrove_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWToAgAACAQAbmFtZRcAbWluZWNyYWZ0Om1hbmdyb3ZlX3NsYWIECQBuYW1lX2hhc2jYCcmhJPeNMwMKAG5ldHdvcmtfaWQx6U1yCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:cherry_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQaAwAACAQAbmFtZRUAbWluZWNyYWZ0OmNoZXJyeV9zbGFiBAkAbmFtZV9oYXNoTt0MmVn/mqoDCgBuZXR3b3JrX2lk2VVsZQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:bamboo_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQAAwAACAQAbmFtZRUAbWluZWNyYWZ0OmJhbWJvb19zbGFiBAkAbmFtZV9oYXNoo1xuFqINeLYDCgBuZXR3b3JrX2lkVC+0twoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:bamboo_mosaic_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQLAwAACAQAbmFtZRwAbWluZWNyYWZ0OmJhbWJvb19tb3NhaWNfc2xhYgQJAG5hbWVfaGFzaNbVRBZ/ChI3AwoAbmV0d29ya19pZOLZHFMKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAAAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWQSiInOCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQsAc3RvbmVfYnJpY2sAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:stone_block_slab4", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkoF89tgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNBEAbW9zc3lfc3RvbmVfYnJpY2sAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAAAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWSkoAE4CgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQkAc2FuZHN0b25lAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:stone_block_slab4", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkWfF7pgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNA0AY3V0X3NhbmRzdG9uZQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkbKRChAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAc21vb3RoX3NhbmRzdG9uZQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkBlrvqAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMg0AcmVkX3NhbmRzdG9uZQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:stone_block_slab4", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkRWFXuwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNBEAY3V0X3JlZF9zYW5kc3RvbmUAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkom8neQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxQAc21vb3RoX3JlZF9zYW5kc3RvbmUAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkd1ZaWgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMwcAZ3Jhbml0ZQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkISH4iwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxAAcG9saXNoZWRfZ3Jhbml0ZQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkqxEDMwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMwcAZGlvcml0ZQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkSYs86QoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxAAcG9saXNoZWRfZGlvcml0ZQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkq6BU6goGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMwgAYW5kZXNpdGUAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkTSXY8AoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxEAcG9saXNoZWRfYW5kZXNpdGUAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAAAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWQiYHKTCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQUAYnJpY2sAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAAAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWTk/0LfCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQwAbmV0aGVyX2JyaWNrAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lk/hXQ7AoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAcmVkX25ldGhlcl9icmljawADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkYJNxrwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMw8AZW5kX3N0b25lX2JyaWNrAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAAAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWRlj0/sCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQYAcXVhcnR6AAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:stone_block_slab4", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkMae+2goGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNA0Ac21vb3RoX3F1YXJ0egADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lk+kMHGAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMgYAcHVycHVyAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkKOSOMAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAcHJpc21hcmluZV9yb3VnaAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lk8igLCQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMg8AcHJpc21hcmluZV9kYXJrAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkSFbyEwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAcHJpc21hcmluZV9icmljawADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:crimson_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQHAgAACAQAbmFtZRYAbWluZWNyYWZ0OmNyaW1zb25fc2xhYgQJAG5hbWVfaGFzaKZ+EfP0ZYOZAwoAbmV0d29ya19pZAxRUWAKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:warped_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQIAgAACAQAbmFtZRUAbWluZWNyYWZ0OndhcnBlZF9zbGFiBAkAbmFtZV9oYXNo/AT0e/Z9W7UDCgBuZXR3b3JrX2lk1yq11AoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:blackstone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQZAgAACAQAbmFtZRkAbWluZWNyYWZ0OmJsYWNrc3RvbmVfc2xhYgQJAG5hbWVfaGFzaF/DD4ZUlNgtAwoAbmV0d29ya19pZGy1DjwKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:polished_blackstone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQkAgAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfc2xhYgQJAG5hbWVfaGFzaDYnuUs86EWfAwoAbmV0d29ya19pZJj2bXIKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:polished_blackstone_brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQbAgAACAQAbmFtZSgAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfc2xhYgQJAG5hbWVfaGFzaKySLqvHc4xXAwoAbmV0d29ya19pZOyWX94KBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRoAgAACAQAbmFtZRkAbWluZWNyYWZ0OmN1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaDsNpb2qs4iBAwoAbmV0d29ya19pZOTm2nsKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:exposed_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRpAgAACAQAbmFtZSEAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcl9zbGFiBAkAbmFtZV9oYXNoahQ5OwIQb7kDCgBuZXR3b3JrX2lkrUlZLwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:weathered_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRqAgAACAQAbmFtZSMAbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyX3NsYWIECQBuYW1lX2hhc2hBIuGIOVVXogMKAG5ldHdvcmtfaWQgnaDiCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:oxidized_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRrAgAACAQAbmFtZSIAbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaOptj9ycfpaDAwoAbmV0d29ya19pZMzFSRgKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:waxed_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRsAgAACAQAbmFtZR8AbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaAlx6DZOCTHzAwoAbmV0d29ya19pZFRBvDAKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:waxed_exposed_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRtAgAACAQAbmFtZScAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcl9zbGFiBAkAbmFtZV9oYXNo3KqS5OnhtRIDCgBuZXR3b3JrX2lkHTGcTgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:waxed_weathered_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRuAgAACAQAbmFtZSkAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyX3NsYWIECQBuYW1lX2hhc2gzZ1oX0HCFtwMKAG5ldHdvcmtfaWSgJR+XCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:waxed_oxidized_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTAAgAACAQAbmFtZSgAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaMjjTnLu1KcqAwoAbmV0d29ya19pZIxsnFYKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:cobbled_deepslate_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR7AgAACAQAbmFtZSAAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3NsYWIECQBuYW1lX2hhc2gwJIVWK1TM2QMKAG5ldHdvcmtfaWTYAoX5CgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:polished_deepslate_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR/AgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV9zbGFiBAkAbmFtZV9oYXNoC/Adiz8k6RYDCgBuZXR3b3JrX2lkuFYMAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:deepslate_tile_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3NsYWIECQBuYW1lX2hhc2hPydV6emzIXAMKAG5ldHdvcmtfaWQwlbFCCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:deepslate_brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSHAgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja19zbGFiBAkAbmFtZV9oYXNoSv62V7iw10UDCgBuZXR3b3JrX2lkWMoragoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:mud_brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTdAgAACAQAbmFtZRgAbWluZWNyYWZ0Om11ZF9icmlja19zbGFiBAkAbmFtZV9oYXNoq/tGBQWkv08DCgBuZXR3b3JrX2lkl4nnMwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:brick_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQtAAAACAQAbmFtZRUAbWluZWNyYWZ0OmJyaWNrX2Jsb2NrBAkAbmFtZV9oYXNo5Qc2E005S3oDCgBuZXR3b3JrX2lkqeGWRgoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:chiseled_nether_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQtAgAACAQAbmFtZSAAbWluZWNyYWZ0OmNoaXNlbGVkX25ldGhlcl9icmlja3MECQBuYW1lX2hhc2g31SBPTcUK1QMKAG5ldHdvcmtfaWS8TJ+TCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:cracked_nether_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQuAgAACAQAbmFtZR8AbWluZWNyYWZ0OmNyYWNrZWRfbmV0aGVyX2JyaWNrcwQJAG5hbWVfaGFzaAdC6eKzXT5tAwoAbmV0d29ya19pZIUSejwKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:quartz_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQvAgAACAQAbmFtZRcAbWluZWNyYWZ0OnF1YXJ0el9icmlja3MECQBuYW1lX2hhc2jSZO590dd8sAMKAG5ldHdvcmtfaWSc5xCLCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:stonebrick", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAAAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWQ5kni1CgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQcAZGVmYXVsdAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:stonebrick", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAAAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWTDw813CgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQUAbW9zc3kAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:stonebrick", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAAAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWSTvQGECgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQcAY3JhY2tlZAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:stonebrick", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAAAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWQIM0OwCgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQgAY2hpc2VsZWQAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:end_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTOAAAACAQAbmFtZRQAbWluZWNyYWZ0OmVuZF9icmlja3MECQBuYW1lX2hhc2hIUFfxNLZaFgMKAG5ldHdvcmtfaWQ/vDihCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:prismarine", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAAAACAQAbmFtZRQAbWluZWNyYWZ0OnByaXNtYXJpbmUECQBuYW1lX2hhc2jcnQCHi9CspQMKAG5ldHdvcmtfaWSH021WCgYAc3RhdGVzCBUAcHJpc21hcmluZV9ibG9ja190eXBlBgBicmlja3MAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:polished_blackstone_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQRAgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tzBAkAbmFtZV9oYXNoIHgsgIdzKXcDCgBuZXR3b3JrX2lkUw9b3woGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:cracked_polished_blackstone_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQXAgAACAQAbmFtZSwAbWluZWNyYWZ0OmNyYWNrZWRfcG9saXNoZWRfYmxhY2tzdG9uZV9icmlja3MECQBuYW1lX2hhc2jQIO1GQDk80AMKAG5ldHdvcmtfaWQ3UlRYCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:gilded_blackstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAgAACAQAbmFtZRsAbWluZWNyYWZ0OmdpbGRlZF9ibGFja3N0b25lBAkAbmFtZV9oYXNoNoWt1ocG0HEDCgBuZXR3b3JrX2lktL8gUwoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:chiseled_polished_blackstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQWAgAACAQAbmFtZSYAbWluZWNyYWZ0OmNoaXNlbGVkX3BvbGlzaGVkX2JsYWNrc3RvbmUECQBuYW1lX2hhc2gzFa+kEjCJgAMKAG5ldHdvcmtfaWR2NJX2CgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:deepslate_tiles", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSCAgAACAQAbmFtZRkAbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlcwQJAG5hbWVfaGFzaGcLLx3NXAFvAwoAbmV0d29ya19pZI/G/xYKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:cracked_deepslate_tiles", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSYAgAACAQAbmFtZSEAbWluZWNyYWZ0OmNyYWNrZWRfZGVlcHNsYXRlX3RpbGVzBAkAbmFtZV9oYXNo9zWgkFuMM1QDCgBuZXR3b3JrX2lkGwY6OgoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:deepslate_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSGAgAACAQAbmFtZRoAbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja3MECQBuYW1lX2hhc2gucvFmPdZxigMKAG5ldHdvcmtfaWSH4HDPCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:cracked_deepslate_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSZAgAACAQAbmFtZSIAbWluZWNyYWZ0OmNyYWNrZWRfZGVlcHNsYXRlX2JyaWNrcwQJAG5hbWVfaGFzaN40aqhh9WqHAwoAbmV0d29ya19pZO9GPBQKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:chiseled_deepslate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSKAgAACAQAbmFtZRwAbWluZWNyYWZ0OmNoaXNlbGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaEU7/uRG8HSBAwoAbmV0d29ya19pZEqmI0EKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:cobblestone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQEAAAACAQAbmFtZRUAbWluZWNyYWZ0OmNvYmJsZXN0b25lBAkAbmFtZV9oYXNoPoK7mGlSUz4DCgBuZXR3b3JrX2lkLm7RZwoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:mossy_cobblestone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQwAAAACAQAbmFtZRsAbWluZWNyYWZ0Om1vc3N5X2NvYmJsZXN0b25lBAkAbmFtZV9oYXNoGJ67FCbkChMDCgBuZXR3b3JrX2lk/pYs1AoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:cobbled_deepslate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR6AgAACAQAbmFtZRsAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlBAkAbmFtZV9oYXNoLUz9Y/ywmLwDCgBuZXR3b3JrX2lkNwzZ+AoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:smooth_stone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AQAACAQAbmFtZRYAbWluZWNyYWZ0OnNtb290aF9zdG9uZQQJAG5hbWVfaGFzaMwf87/JaTNvAwoAbmV0d29ya19pZLkZICEKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAAAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZB2wApMKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGUHAGRlZmF1bHQAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAAAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZB7E+eQKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGULAGhlaXJvZ2x5cGhzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAAAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZFQnDaEKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGUDAGN1dAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAAAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZPO4A3IKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGUGAHNtb290aAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:red_sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSzAAAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWRhNYiFCgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlBwBkZWZhdWx0AAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:red_sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSzAAAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWTqXJr1CgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlCwBoZWlyb2dseXBocwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:red_sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSzAAAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWTQRGkFCgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlAwBjdXQAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:red_sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSzAAAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWTvAHWDCgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlBgBzbW9vdGgAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:coal_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWStAAAACAQAbmFtZRQAbWluZWNyYWZ0OmNvYWxfYmxvY2sECQBuYW1lX2hhc2jH8QQP3t5PiAMKAG5ldHdvcmtfaWRo+sR+CgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:dried_kelp_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSKAQAACAQAbmFtZRoAbWluZWNyYWZ0OmRyaWVkX2tlbHBfYmxvY2sECQBuYW1lX2hhc2iRoucexkrl8wMKAG5ldHdvcmtfaWQQCCrvCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:gold_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQpAAAACAQAbmFtZRQAbWluZWNyYWZ0OmdvbGRfYmxvY2sECQBuYW1lX2hhc2iYLshvjtXzFwMKAG5ldHdvcmtfaWTDJGBcCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:iron_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQqAAAACAQAbmFtZRQAbWluZWNyYWZ0Omlyb25fYmxvY2sECQBuYW1lX2hhc2jYINmJQbvV/gMKAG5ldHdvcmtfaWRf7AbICgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:copper_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRTAgAACAQAbmFtZRYAbWluZWNyYWZ0OmNvcHBlcl9ibG9jawQJAG5hbWVfaGFzaDVxnehsGaZ1AwoAbmV0d29ya19pZIiUodwKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:exposed_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRUAgAACAQAbmFtZRgAbWluZWNyYWZ0OmV4cG9zZWRfY29wcGVyBAkAbmFtZV9oYXNoQH3Fukmu3CEDCgBuZXR3b3JrX2lk72jFIwoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:weathered_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRVAgAACAQAbmFtZRoAbWluZWNyYWZ0OndlYXRoZXJlZF9jb3BwZXIECQBuYW1lX2hhc2hJCQXbvobv+gMKAG5ldHdvcmtfaWQwM0lJCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:oxidized_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRWAgAACAQAbmFtZRkAbWluZWNyYWZ0Om94aWRpemVkX2NvcHBlcgQJAG5hbWVfaGFzaMDtJqR0G5Y7AwoAbmV0d29ya19pZGjN8bUKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:waxed_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRXAgAACAQAbmFtZRYAbWluZWNyYWZ0OndheGVkX2NvcHBlcgQJAG5hbWVfaGFzaPF+FG6Eh5fsAwoAbmV0d29ya19pZIjtz/0KBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:waxed_exposed_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRYAgAACAQAbmFtZR4AbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY29wcGVyBAkAbmFtZV9oYXNoig8IOc+SCikDCgBuZXR3b3JrX2lklz8yWQoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:waxed_weathered_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRZAgAACAQAbmFtZSAAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jb3BwZXIECQBuYW1lX2hhc2gjtPq8MOdvKgMKAG5ldHdvcmtfaWSQ9Ln9CgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:waxed_oxidized_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS9AgAACAQAbmFtZR8AbWluZWNyYWZ0OndheGVkX294aWRpemVkX2NvcHBlcgQJAG5hbWVfaGFzaMaORhsO+LzjAwoAbmV0d29ya19pZJhGfLEKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRaAgAACAQAbmFtZRQAbWluZWNyYWZ0OmN1dF9jb3BwZXIECQBuYW1lX2hhc2hAfN3NGax3eAMKAG5ldHdvcmtfaWTnFBtYCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:exposed_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRbAgAACAQAbmFtZRwAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcgQJAG5hbWVfaGFzaA85G3yv/w6pAwoAbmV0d29ya19pZMQhr0QKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:weathered_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRcAgAACAQAbmFtZR4AbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyBAkAbmFtZV9oYXNoVgRV0fBaz88DCgBuZXR3b3JrX2lk/0cYugoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:oxidized_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRdAgAACAQAbmFtZR0AbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2iP8WmFWOkriwMKAG5ldHdvcmtfaWQPdce7CgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:waxed_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWReAgAACAQAbmFtZRoAbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2jumiwOZIqv2AMKAG5ldHdvcmtfaWQvuxx9CgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:waxed_exposed_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRfAgAACAQAbmFtZSIAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcgQJAG5hbWVfaGFzaPE/OfK6IoVMAwoAbmV0d29ya19pZHy5HkcKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:waxed_weathered_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRgAgAACAQAbmFtZSQAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyBAkAbmFtZV9oYXNoCA1xDp11bnwDCgBuZXR3b3JrX2lkDyEDVQoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:waxed_oxidized_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS+AgAACAQAbmFtZSMAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2i1pZAsZYHLDAMKAG5ldHdvcmtfaWQ/wSkCCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:emerald_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAAAACAQAbmFtZRcAbWluZWNyYWZ0OmVtZXJhbGRfYmxvY2sECQBuYW1lX2hhc2hK6QunqJznNAMKAG5ldHdvcmtfaWRk5+otCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:diamond_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ5AAAACAQAbmFtZRcAbWluZWNyYWZ0OmRpYW1vbmRfYmxvY2sECQBuYW1lX2hhc2iGKrxuvkytFQMKAG5ldHdvcmtfaWQQeQZXCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:lapis_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQWAAAACAQAbmFtZRUAbWluZWNyYWZ0OmxhcGlzX2Jsb2NrBAkAbmFtZV9oYXNoDZ44xdb2zVoDCgBuZXR3b3JrX2lktVy0BAoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:raw_iron_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTCAgAACAQAbmFtZRgAbWluZWNyYWZ0OnJhd19pcm9uX2Jsb2NrBAkAbmFtZV9oYXNo9XyzNIQXxvwDCgBuZXR3b3JrX2lknms1QAoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:raw_copper_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTDAgAACAQAbmFtZRoAbWluZWNyYWZ0OnJhd19jb3BwZXJfYmxvY2sECQBuYW1lX2hhc2hw1KG0TNUGgwMKAG5ldHdvcmtfaWS1vGo/CgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:raw_gold_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTEAgAACAQAbmFtZRgAbWluZWNyYWZ0OnJhd19nb2xkX2Jsb2NrBAkAbmFtZV9oYXNo6YuwuLwfOBwDCgBuZXR3b3JrX2lkLiQ5gQoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:quartz_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAAAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZEupC1AKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQcAZGVmYXVsdAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:quartz_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAAAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZM97+l0KBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQUAbGluZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:quartz_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAAAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZCbTfssKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQgAY2hpc2VsZWQICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:quartz_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAAAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZJss8V0KBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQYAc21vb3RoCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:prismarine", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAAAACAQAbmFtZRQAbWluZWNyYWZ0OnByaXNtYXJpbmUECQBuYW1lX2hhc2jcnQCHi9CspQMKAG5ldHdvcmtfaWRFIsoGCgYAc3RhdGVzCBUAcHJpc21hcmluZV9ibG9ja190eXBlBwBkZWZhdWx0AAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:prismarine", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAAAACAQAbmFtZRQAbWluZWNyYWZ0OnByaXNtYXJpbmUECQBuYW1lX2hhc2jcnQCHi9CspQMKAG5ldHdvcmtfaWTDNWOvCgYAc3RhdGVzCBUAcHJpc21hcmluZV9ibG9ja190eXBlBABkYXJrAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:slime", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAAAACAQAbmFtZQ8AbWluZWNyYWZ0OnNsaW1lBAkAbmFtZV9oYXNoHJiEEJx+JlkDCgBuZXR3b3JrX2lkfgfVzAoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:honey_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTbAQAACAQAbmFtZRUAbWluZWNyYWZ0OmhvbmV5X2Jsb2NrBAkAbmFtZV9oYXNo9zLYSUlelywDCgBuZXR3b3JrX2lko+dyWgoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:honeycomb_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTcAQAACAQAbmFtZRkAbWluZWNyYWZ0OmhvbmV5Y29tYl9ibG9jawQJAG5hbWVfaGFzaASIPuOCYd1oAwoAbmV0d29ya19pZKys4n4KBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:hay_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSqAAAACAQAbmFtZRMAbWluZWNyYWZ0OmhheV9ibG9jawQJAG5hbWVfaGFzaIB2VxKxX8EpAwoAbmV0d29ya19pZKuQSloKBgBzdGF0ZXMDCgBkZXByZWNhdGVkAAAAAAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:bone_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTYAAAACAQAbmFtZRQAbWluZWNyYWZ0OmJvbmVfYmxvY2sECQBuYW1lX2hhc2i4ZX576W9AWgMKAG5ldHdvcmtfaWTWGacQCgYAc3RhdGVzAwoAZGVwcmVjYXRlZAAAAAAICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:nether_brick", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRwAAAACAQAbmFtZRYAbWluZWNyYWZ0Om5ldGhlcl9icmljawQJAG5hbWVfaGFzaMxcRiheU+nXAwoAbmV0d29ya19pZMkmzloKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:red_nether_brick", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTXAAAACAQAbmFtZRoAbWluZWNyYWZ0OnJlZF9uZXRoZXJfYnJpY2sECQBuYW1lX2hhc2j8pRO4LfoECAMKAG5ldHdvcmtfaWRpdF0YCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:netherite_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQNAgAACAQAbmFtZRkAbWluZWNyYWZ0Om5ldGhlcml0ZV9ibG9jawQJAG5hbWVfaGFzaMghh6Zib/ZKAwoAbmV0d29ya19pZIz0mq0KBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:lodestone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTdAQAACAQAbmFtZRMAbWluZWNyYWZ0OmxvZGVzdG9uZQQJAG5hbWVfaGFzaJ2gmHOTlXv8AwoAbmV0d29ya19pZEfgB4wKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:white_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQjAAAACAQAbmFtZRQAbWluZWNyYWZ0OndoaXRlX3dvb2wECQBuYW1lX2hhc2jRWB7vaIEDiQMKAG5ldHdvcmtfaWSO8paQCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:light_gray_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQnAwAACAQAbmFtZRkAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfd29vbAQJAG5hbWVfaGFzaOpdQ1a2v4b3AwoAbmV0d29ya19pZIqZCYEKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:gray_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQoAwAACAQAbmFtZRMAbWluZWNyYWZ0OmdyYXlfd29vbAQJAG5hbWVfaGFzaLsc1Lp1xdIOAwoAbmV0d29ya19pZFUs+HgKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:black_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQpAwAACAQAbmFtZRQAbWluZWNyYWZ0OmJsYWNrX3dvb2wECQBuYW1lX2hhc2hP2HC6o0X4HAMKAG5ldHdvcmtfaWRUbORcCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:brown_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQqAwAACAQAbmFtZRQAbWluZWNyYWZ0OmJyb3duX3dvb2wECQBuYW1lX2hhc2ig5IW89PrREwMKAG5ldHdvcmtfaWRjT9j8CgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:red_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQrAwAACAQAbmFtZRIAbWluZWNyYWZ0OnJlZF93b29sBAkAbmFtZV9oYXNoY4TBDq+mFgUDCgBuZXR3b3JrX2lktn9lcAoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:orange_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAwAACAQAbmFtZRUAbWluZWNyYWZ0Om9yYW5nZV93b29sBAkAbmFtZV9oYXNoFstfrTZfSCgDCgBuZXR3b3JrX2lk+rqywwoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:yellow_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQtAwAACAQAbmFtZRUAbWluZWNyYWZ0OnllbGxvd193b29sBAkAbmFtZV9oYXNoTFyus2RHegcDCgBuZXR3b3JrX2lkkKBhXAoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:lime_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQuAwAACAQAbmFtZRMAbWluZWNyYWZ0OmxpbWVfd29vbAQJAG5hbWVfaGFzaNVnnzKiMxmeAwoAbmV0d29ya19pZG9b32kKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:green_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQvAwAACAQAbmFtZRQAbWluZWNyYWZ0OmdyZWVuX3dvb2wECQBuYW1lX2hhc2i3mElRYHIcSQMKAG5ldHdvcmtfaWSssprwCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:cyan_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQwAwAACAQAbmFtZRMAbWluZWNyYWZ0OmN5YW5fd29vbAQJAG5hbWVfaGFzaBNDfvHn8dqFAwoAbmV0d29ya19pZK0hAbgKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:light_blue_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQxAwAACAQAbmFtZRkAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfd29vbAQJAG5hbWVfaGFzaLWFAUfyxFPNAwoAbmV0d29ya19pZL2oEugKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:blue_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQyAwAACAQAbmFtZRMAbWluZWNyYWZ0OmJsdWVfd29vbAQJAG5hbWVfaGFzaLjHyxxbTWCLAwoAbmV0d29ya19pZPaLdFQKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:purple_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQzAwAACAQAbmFtZRUAbWluZWNyYWZ0OnB1cnBsZV93b29sBAkAbmFtZV9oYXNojvFtqzjAf/4DCgBuZXR3b3JrX2lklqASNQoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:magenta_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ0AwAACAQAbmFtZRYAbWluZWNyYWZ0Om1hZ2VudGFfd29vbAQJAG5hbWVfaGFzaGuOHvf+Pd4yAwoAbmV0d29ya19pZI4UoDQKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:pink_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ1AwAACAQAbmFtZRMAbWluZWNyYWZ0OnBpbmtfd29vbAQJAG5hbWVfaGFzaPiVA2pFeoFLAwoAbmV0d29ya19pZOZRO6oKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:white_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSrAAAACAQAbmFtZRYAbWluZWNyYWZ0OndoaXRlX2NhcnBldAQJAG5hbWVfaGFzaNeMHTI1fWPXAwoAbmV0d29ya19pZEahDFcKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:light_gray_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRbAwAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY2FycGV0BAkAbmFtZV9oYXNoHPw6ArBAsP0DCgBuZXR3b3JrX2lkQoAeUAoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:gray_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRaAwAACAQAbmFtZRUAbWluZWNyYWZ0OmdyYXlfY2FycGV0BAkAbmFtZV9oYXNoZVR0OI+1VRADCgBuZXR3b3JrX2lkETF4WwoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:black_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJsYWNrX2NhcnBldAQJAG5hbWVfaGFzaOk7LP9NptyhAwoAbmV0d29ya19pZFjmXtIKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:brown_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRfAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJyb3duX2NhcnBldAQJAG5hbWVfaGFzaNaXFyOsAvIvAwoAbmV0d29ya19pZHPjFuoKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:red_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAwAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9jYXJwZXQECQBuYW1lX2hhc2i9eSKBf6SO3wMKAG5ldHdvcmtfaWQuhI/KCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:orange_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRUAwAACAQAbmFtZRcAbWluZWNyYWZ0Om9yYW5nZV9jYXJwZXQECQBuYW1lX2hhc2hIUkO4HlAdygMKAG5ldHdvcmtfaWSyKV9OCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:yellow_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRXAwAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19jYXJwZXQECQBuYW1lX2hhc2hSDKX3scCamwMKAG5ldHdvcmtfaWT8nq+ECgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:lime_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRYAwAACAQAbmFtZRUAbWluZWNyYWZ0OmxpbWVfY2FycGV0BAkAbmFtZV9oYXNo+6KFOpzsib4DCgBuZXR3b3JrX2lkT+DS4woGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:green_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRgAwAACAQAbmFtZRYAbWluZWNyYWZ0OmdyZWVuX2NhcnBldAQJAG5hbWVfaGFzaCHPMP9ltqFJAwoAbmV0d29ya19pZBgwAvAKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:cyan_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRcAwAACAQAbmFtZRUAbWluZWNyYWZ0OmN5YW5fY2FycGV0BAkAbmFtZV9oYXNobXf62dQBJj8DCgBuZXR3b3JrX2lkKVppLgoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:light_blue_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRWAwAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY2FycGV0BAkAbmFtZV9oYXNo20l4oktdZ3sDCgBuZXR3b3JrX2lkjdeMiwoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:blue_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWReAwAACAQAbmFtZRUAbWluZWNyYWZ0OmJsdWVfY2FycGV0BAkAbmFtZV9oYXNo3p3lsW0eQwsDCgBuZXR3b3JrX2lkAovdPQoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:purple_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRdAwAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnBsZV9jYXJwZXQECQBuYW1lX2hhc2jwIA9pW/qp7QMKAG5ldHdvcmtfaWTqJqhjCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:magenta_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRVAwAACAQAbmFtZRgAbWluZWNyYWZ0Om1hZ2VudGFfY2FycGV0BAkAbmFtZV9oYXNoFXT36YNNZhMDCgBuZXR3b3JrX2lk+tqsGAoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:pink_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRZAwAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfY2FycGV0BAkAbmFtZV9oYXNoHll72oqk+OoDCgBuZXR3b3JrX2lkrnBYDwoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:white_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTtAAAACAQAbmFtZR8AbWluZWNyYWZ0OndoaXRlX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaFUk9iXVjwV8AwoAbmV0d29ya19pZJPZY8AKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:light_gray_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTLAwAACAQAbmFtZSQAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNo7EUk30hmUtYDCgBuZXR3b3JrX2lkh8jVIwoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:gray_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTKAwAACAQAbmFtZR4AbWluZWNyYWZ0OmdyYXlfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoW77af6WihdwDCgBuZXR3b3JrX2lkSsqC1woGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:black_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTSAwAACAQAbmFtZR8AbWluZWNyYWZ0OmJsYWNrX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaAfWYp0xtgcfAwoAbmV0d29ya19pZMWTC8EKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:brown_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTPAwAACAQAbmFtZR8AbWluZWNyYWZ0OmJyb3duX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaB74EeiLO46XAwoAbmV0d29ya19pZEDHKqwKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:red_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTRAwAACAQAbmFtZR0AbWluZWNyYWZ0OnJlZF9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2gjFut6Z/VH1gMKAG5ldHdvcmtfaWSvcmwYCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:orange_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTEAwAACAQAbmFtZSAAbWluZWNyYWZ0Om9yYW5nZV9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2gADDj2IJiw+gMKAG5ldHdvcmtfaWTHph0FCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:yellow_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTHAwAACAQAbmFtZSAAbWluZWNyYWZ0OnllbGxvd19jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2iy6qKNn3ob5wMKAG5ldHdvcmtfaWQZAI39CgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:lime_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTIAwAACAQAbmFtZR4AbWluZWNyYWZ0OmxpbWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNo4dYIPslbXPUDCgBuZXR3b3JrX2lk2O8X0AoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:green_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTQAwAACAQAbmFtZR8AbWluZWNyYWZ0OmdyZWVuX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaM/c9x2aJh3HAwoAbmV0d29ya19pZA0VfBMKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:cyan_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTMAwAACAQAbmFtZR4AbWluZWNyYWZ0OmN5YW5fY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNok+xKAe7XXjoDCgBuZXR3b3JrX2lkmkn6uwoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:light_blue_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTGAwAACAQAbmFtZSQAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNogScpIQceyAEDCgBuZXR3b3JrX2lkOmVSbgoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:blue_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTOAwAACAQAbmFtZR4AbWluZWNyYWZ0OmJsdWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoFp7mmeL86r0DCgBuZXR3b3JrX2lkS3b3RQoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:purple_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTNAwAACAQAbmFtZSAAbWluZWNyYWZ0OnB1cnBsZV9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2iYcVU04hoStwMKAG5ldHdvcmtfaWQXimEjCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:magenta_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTFAwAACAQAbmFtZSEAbWluZWNyYWZ0Om1hZ2VudGFfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoy/70q6VPsWgDCgBuZXR3b3JrX2lkf9mxQwoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:pink_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAwAACAQAbmFtZR4AbWluZWNyYWZ0OnBpbmtfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoVikSAf8DwV0DCgBuZXR3b3JrX2lku2MivwoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:white_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTsAAAACAQAbmFtZRgAbWluZWNyYWZ0OndoaXRlX2NvbmNyZXRlBAkAbmFtZV9oYXNo6zAp7lsLlvkDCgBuZXR3b3JrX2lk3MAYQAoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:light_gray_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR6AwAACAQAbmFtZR0AbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY29uY3JldGUECQBuYW1lX2hhc2hEtet5wuDIKAMKAG5ldHdvcmtfaWQISs02CgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:gray_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR5AwAACAQAbmFtZRcAbWluZWNyYWZ0OmdyYXlfY29uY3JldGUECQBuYW1lX2hhc2j92INnb0a83AMKAG5ldHdvcmtfaWQj8RHwCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:black_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSBAwAACAQAbmFtZRgAbWluZWNyYWZ0OmJsYWNrX2NvbmNyZXRlBAkAbmFtZV9oYXNo2X7NDIQmZ70DCgBuZXR3b3JrX2lk2uiVDQoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:brown_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR+AwAACAQAbmFtZRgAbWluZWNyYWZ0OmJyb3duX2NvbmNyZXRlBAkAbmFtZV9oYXNoeka02BwXf6oDCgBuZXR3b3JrX2lkYf+xDQoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:red_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSAAwAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZF9jb25jcmV0ZQQJAG5hbWVfaGFzaPWmNowLGubqAwoAbmV0d29ya19pZKwyx58KBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:orange_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRzAwAACAQAbmFtZRkAbWluZWNyYWZ0Om9yYW5nZV9jb25jcmV0ZQQJAG5hbWVfaGFzaAgE8XmaAi6+AwoAbmV0d29ya19pZMDQNz8KBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:yellow_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR2AwAACAQAbmFtZRkAbWluZWNyYWZ0OnllbGxvd19jb25jcmV0ZQQJAG5hbWVfaGFzaE6ONfJPBd0+AwoAbmV0d29ya19pZMarutwKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:lime_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR3AwAACAQAbmFtZRcAbWluZWNyYWZ0OmxpbWVfY29uY3JldGUECQBuYW1lX2hhc2gnd8JW6wmJcAMKAG5ldHdvcmtfaWTd47aoCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:green_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR/AwAACAQAbmFtZRgAbWluZWNyYWZ0OmdyZWVuX2NvbmNyZXRlBAkAbmFtZV9oYXNokbFxRKchQZkDCgBuZXR3b3JrX2lkmhZWUgoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:cyan_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR7AwAACAQAbmFtZRcAbWluZWNyYWZ0OmN5YW5fY29uY3JldGUECQBuYW1lX2hhc2hFRrWJ33qj1wMKAG5ldHdvcmtfaWQbi5b8CgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:light_blue_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR1AwAACAQAbmFtZR0AbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY29uY3JldGUECQBuYW1lX2hhc2gHAe0kl0SE4AMKAG5ldHdvcmtfaWRL/GbSCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:blue_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR9AwAACAQAbmFtZRcAbWluZWNyYWZ0OmJsdWVfY29uY3JldGUECQBuYW1lX2hhc2hiay301nnj1wMKAG5ldHdvcmtfaWRMvFXNCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:purple_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR8AwAACAQAbmFtZRkAbWluZWNyYWZ0OnB1cnBsZV9jb25jcmV0ZQQJAG5hbWVfaGFzaHBHflsPIwdXAwoAbmV0d29ya19pZCyKA5gKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:magenta_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR0AwAACAQAbmFtZRoAbWluZWNyYWZ0Om1hZ2VudGFfY29uY3JldGUECQBuYW1lX2hhc2gN7LuB/OvdZAMKAG5ldHdvcmtfaWTc6ZOdCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:pink_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR4AwAACAQAbmFtZRcAbWluZWNyYWZ0OnBpbmtfY29uY3JldGUECQBuYW1lX2hhc2ii2G5F0u3SOAMKAG5ldHdvcmtfaWSszGgrCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:clay", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRSAAAACAQAbmFtZQ4AbWluZWNyYWZ0OmNsYXkECQBuYW1lX2hhc2j/S6sKXRcpzwMKAG5ldHdvcmtfaWRmsb8nCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:hardened_clay", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSsAAAACAQAbmFtZRcAbWluZWNyYWZ0OmhhcmRlbmVkX2NsYXkECQBuYW1lX2hhc2jrnRwCJ0krJAMKAG5ldHdvcmtfaWRBCOrrCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:white_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSfAAAACAQAbmFtZRoAbWluZWNyYWZ0OndoaXRlX3RlcnJhY290dGEECQBuYW1lX2hhc2j3RSdgmnAIewMKAG5ldHdvcmtfaWSimKw+CgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:light_gray_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTaAwAACAQAbmFtZR8AbWluZWNyYWZ0OmxpZ2h0X2dyYXlfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAz1Ri3wIxomAwoAbmV0d29ya19pZH5qgOcKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:gray_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTZAwAACAQAbmFtZRkAbWluZWNyYWZ0OmdyYXlfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAXdSLAaNZ9vAwoAbmV0d29ya19pZM1QDV0KBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:black_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWThAwAACAQAbmFtZRoAbWluZWNyYWZ0OmJsYWNrX3RlcnJhY290dGEECQBuYW1lX2hhc2jxssdv5vlbpgMKAG5ldHdvcmtfaWRE3Ru/CgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:brown_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTeAwAACAQAbmFtZRoAbWluZWNyYWZ0OmJyb3duX3RlcnJhY290dGEECQBuYW1lX2hhc2gG4kPenmOF9gMKAG5ldHdvcmtfaWQ/i0iNCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:red_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTgAwAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNo7fX56HXFejEDCgBuZXR3b3JrX2lk8tTF8QoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:orange_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTTAwAACAQAbmFtZRsAbWluZWNyYWZ0Om9yYW5nZV90ZXJyYWNvdHRhBAkAbmFtZV9oYXNo0Hjmql3sruMDCgBuZXR3b3JrX2lklmqmkAoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:yellow_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTWAwAACAQAbmFtZRsAbWluZWNyYWZ0OnllbGxvd190ZXJyYWNvdHRhBAkAbmFtZV9oYXNoqkyKKrmA3VcDCgBuZXR3b3JrX2lkaM/orAoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:lime_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTXAwAACAQAbmFtZRkAbWluZWNyYWZ0OmxpbWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaANjADFOF9v7AwoAbmV0d29ya19pZJt0XsgKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:green_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTfAwAACAQAbmFtZRoAbWluZWNyYWZ0OmdyZWVuX3RlcnJhY290dGEECQBuYW1lX2hhc2j5Ybq36yYwRQMKAG5ldHdvcmtfaWQ8kGdHCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:cyan_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTbAwAACAQAbmFtZRkAbWluZWNyYWZ0OmN5YW5fdGVycmFjb3R0YQQJAG5hbWVfaGFzaN09COzMuHwAAwoAbmV0d29ya19pZIWPCzoKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:light_blue_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTVAwAACAQAbmFtZR8AbWluZWNyYWZ0OmxpZ2h0X2JsdWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaOMytez7cOZiAwoAbmV0d29ya19pZFHK1UsKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:blue_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTdAwAACAQAbmFtZRkAbWluZWNyYWZ0OmJsdWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaF6inyTK5RpAAwoAbmV0d29ya19pZF5mVZIKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:purple_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTcAwAACAQAbmFtZRsAbWluZWNyYWZ0OnB1cnBsZV90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoKF7YG61yTbEDCgBuZXR3b3JrX2lkhtRDlwoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:magenta_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTUAwAACAQAbmFtZRwAbWluZWNyYWZ0Om1hZ2VudGFfdGVycmFjb3R0YQQJAG5hbWVfaGFzaLWvtpAVtztyAwoAbmV0d29ya19pZN5SoakKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:pink_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTYAwAACAQAbmFtZRkAbWluZWNyYWZ0OnBpbmtfdGVycmFjb3R0YQQJAG5hbWVfaGFzaJ7mzvyzSQZTAwoAbmV0d29ya19pZDJWe4YKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:white_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTcAAAACAQAbmFtZSEAbWluZWNyYWZ0OndoaXRlX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoiVzCdoHAJo0DCgBuZXR3b3JrX2lkIlj9AAoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:silver_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTkAAAACAQAbmFtZSIAbWluZWNyYWZ0OnNpbHZlcl9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAVsA0CnhzA4AwoAbmV0d29ya19pZPnxtJEKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:gray_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTjAAAACAQAbmFtZSAAbWluZWNyYWZ0OmdyYXlfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2jvLZt9u/lF/AMKAG5ldHdvcmtfaWQVU8eFCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:black_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTrAAAACAQAbmFtZSEAbWluZWNyYWZ0OmJsYWNrX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoe8I4xAXbO5UDCgBuZXR3b3JrX2lk2Icb9AoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:brown_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWToAAAACAQAbmFtZSEAbWluZWNyYWZ0OmJyb3duX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoSiNZOobbpjoDCgBuZXR3b3JrX2lkJy0jwgoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:red_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTqAAAACAQAbmFtZR8AbWluZWNyYWZ0OnJlZF9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaBdWFGLmCLFVAwoAbmV0d29ya19pZMYBJSEKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:orange_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTdAAAACAQAbmFtZSIAbWluZWNyYWZ0Om9yYW5nZV9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaMyJMrnPr7szAwoAbmV0d29ya19pZN6+7TUKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:yellow_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTgAAAACAQAbmFtZSIAbWluZWNyYWZ0OnllbGxvd19nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaN6NaIhf6m0uAwoAbmV0d29ya19pZKRHXeoKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:lime_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWThAAAACAQAbmFtZSAAbWluZWNyYWZ0OmxpbWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2iF3E68/rB2EAMKAG5ldHdvcmtfaWSP7qQWCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:green_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTpAAAACAQAbmFtZSEAbWluZWNyYWZ0OmdyZWVuX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNow5mo8aQDFboDCgBuZXR3b3JrX2lkoF11kgoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:cyan_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTlAAAACAQAbmFtZSAAbWluZWNyYWZ0OmN5YW5fZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2gnNB+cCFRJhwMKAG5ldHdvcmtfaWT9buMtCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:light_blue_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTfAAAACAQAbmFtZSYAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2gladnCDBKCigMKAG5ldHdvcmtfaWS5CszFCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:blue_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTnAAAACAQAbmFtZSAAbWluZWNyYWZ0OmJsdWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2giOZK+2nB1igMKAG5ldHdvcmtfaWR+e22CCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:purple_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTbAAAACAQAbmFtZSIAbWluZWNyYWZ0OnB1cnBsZV9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaIQU03txeAfHAwoAbmV0d29ya19pZLKbSE4KBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:magenta_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTeAAAACAQAbmFtZSMAbWluZWNyYWZ0Om1hZ2VudGFfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2i/SNqDJbfjMgMKAG5ldHdvcmtfaWQKf9UvCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:pink_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTiAAAACAQAbmFtZSAAbWluZWNyYWZ0OnBpbmtfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2hik8DVt4g+twMKAG5ldHdvcmtfaWTKzav2CgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:purpur_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAAAACAQAbmFtZRYAbWluZWNyYWZ0OnB1cnB1cl9ibG9jawQJAG5hbWVfaGFzaAgLwnUZGlzsAwoAbmV0d29ya19pZLD8ox4KBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQcAZGVmYXVsdAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:purpur_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAAAACAQAbmFtZRYAbWluZWNyYWZ0OnB1cnB1cl9ibG9jawQJAG5hbWVfaGFzaAgLwnUZGlzsAwoAbmV0d29ya19pZPSAFFsKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQUAbGluZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:packed_mud", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTcAgAACAQAbmFtZRQAbWluZWNyYWZ0OnBhY2tlZF9tdWQECQBuYW1lX2hhc2gHOMa121h4FgMKAG5ldHdvcmtfaWTUb6LyCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:mud_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTaAgAACAQAbmFtZRQAbWluZWNyYWZ0Om11ZF9icmlja3MECQBuYW1lX2hhc2iDL/SVl/PewQMKAG5ldHdvcmtfaWSkBjaDCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:nether_wart_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTWAAAACAQAbmFtZRsAbWluZWNyYWZ0Om5ldGhlcl93YXJ0X2Jsb2NrBAkAbmFtZV9oYXNo9XGS4GNnlV4DCgBuZXR3b3JrX2lkh3apIgoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:warped_wart_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTiAQAACAQAbmFtZRsAbWluZWNyYWZ0OndhcnBlZF93YXJ0X2Jsb2NrBAkAbmFtZV9oYXNo9IqDS9yUPJoDCgBuZXR3b3JrX2lkMpKAbAoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:shroomlight", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTlAQAACAQAbmFtZRUAbWluZWNyYWZ0OnNocm9vbWxpZ2h0BAkAbmFtZV9oYXNoZHCHcHX/HYADCgBuZXR3b3JrX2lkLG2JiwoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:crimson_nylium", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTnAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fbnlsaXVtBAkAbmFtZV9oYXNoOr6DJYW2bFYDCgBuZXR3b3JrX2lkuWpRDgoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:warped_nylium", + "block_state_b64": "CgAAAwgAYmxvY2tfaWToAQAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9ueWxpdW0ECQBuYW1lX2hhc2g0Zf89cfr3rwMKAG5ldHdvcmtfaWSu/kekCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:netherrack", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRXAAAACAQAbmFtZRQAbWluZWNyYWZ0Om5ldGhlcnJhY2sECQBuYW1lX2hhc2i/r5ZyRsvPyQMKAG5ldHdvcmtfaWTAiTOACgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:basalt", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTpAQAACAQAbmFtZRAAbWluZWNyYWZ0OmJhc2FsdAQJAG5hbWVfaGFzaH+UQO2yWodiAwoAbmV0d29ya19pZBPNSV4KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:polished_basalt", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTqAQAACAQAbmFtZRkAbWluZWNyYWZ0OnBvbGlzaGVkX2Jhc2FsdAQJAG5hbWVfaGFzaMS+L0gMnRcBAwoAbmV0d29ya19pZF+/mHwKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:smooth_basalt", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR4AgAACAQAbmFtZRcAbWluZWNyYWZ0OnNtb290aF9iYXNhbHQECQBuYW1lX2hhc2jKPUdz89kuNAMKAG5ldHdvcmtfaWTkb/oVCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:soul_soil", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTrAQAACAQAbmFtZRMAbWluZWNyYWZ0OnNvdWxfc29pbAQJAG5hbWVfaGFzaC1/87ccutuTAwoAbmV0d29ya19pZKc63SMKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:dirt", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAAAACAQAbmFtZQ4AbWluZWNyYWZ0OmRpcnQECQBuYW1lX2hhc2hXp6jnXAe+kQMKAG5ldHdvcmtfaWQmkQtoCgYAc3RhdGVzCAkAZGlydF90eXBlBgBub3JtYWwAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:dirt", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAAAACAQAbmFtZQ4AbWluZWNyYWZ0OmRpcnQECQBuYW1lX2hhc2hXp6jnXAe+kQMKAG5ldHdvcmtfaWQId9pLCgYAc3RhdGVzCAkAZGlydF90eXBlBgBjb2Fyc2UAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:farmland", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ8AAAACAQAbmFtZRIAbWluZWNyYWZ0OmZhcm1sYW5kBAkAbmFtZV9oYXNoxyQ5ag7LolADCgBuZXR3b3JrX2lkX618FQoGAHN0YXRlcwMSAG1vaXN0dXJpemVkX2Ftb3VudAAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:grass_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQCAAAACAQAbmFtZRUAbWluZWNyYWZ0OmdyYXNzX2Jsb2NrBAkAbmFtZV9oYXNojPyGp3/CSZwDCgBuZXR3b3JrX2lktCgx3goGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:grass_path", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTGAAAACAQAbmFtZRQAbWluZWNyYWZ0OmdyYXNzX3BhdGgECQBuYW1lX2hhc2i0/KZV8Qsy+gMKAG5ldHdvcmtfaWT7CcdzCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:podzol", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTzAAAACAQAbmFtZRAAbWluZWNyYWZ0OnBvZHpvbAQJAG5hbWVfaGFzaBzqokRjH4Z1AwoAbmV0d29ya19pZPPS/GUKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:mycelium", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRuAAAACAQAbmFtZRIAbWluZWNyYWZ0Om15Y2VsaXVtBAkAbmFtZV9oYXNojTN09cKickIDCgBuZXR3b3JrX2lkLNPxXQoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:mud", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTYAgAACAQAbmFtZQ0AbWluZWNyYWZ0Om11ZAQJAG5hbWVfaGFzaPb/3P+uLy+9AwoAbmV0d29ya19pZPIUlUkKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:stone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQBAAAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lkIQ4xgAoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:iron_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQPAAAACAQAbmFtZRIAbWluZWNyYWZ0Omlyb25fb3JlBAkAbmFtZV9oYXNoS7BYtLnfx3gDCgBuZXR3b3JrX2lk3loneQoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:gold_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQOAAAACAQAbmFtZRIAbWluZWNyYWZ0OmdvbGRfb3JlBAkAbmFtZV9oYXNoC5Y+DUGXLC4DCgBuZXR3b3JrX2lkNhvMfwoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:diamond_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ4AAAACAQAbmFtZRUAbWluZWNyYWZ0OmRpYW1vbmRfb3JlBAkAbmFtZV9oYXNokUOJ2wZZrGQDCgBuZXR3b3JrX2lk/dChVAoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:lapis_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQVAAAACAQAbmFtZRMAbWluZWNyYWZ0OmxhcGlzX29yZQQJAG5hbWVfaGFzaMrmrUrSzb7qAwoAbmV0d29ya19pZMg+qK4KBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:redstone_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRJAAAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZHN0b25lX29yZQQJAG5hbWVfaGFzaFHVnp8Wc4JbAwoAbmV0d29ya19pZKDYvQoKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:coal_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQQAAAACAQAbmFtZRIAbWluZWNyYWZ0OmNvYWxfb3JlBAkAbmFtZV9oYXNo1OjA+Iuy51oDCgBuZXR3b3JrX2lk+R/aKAoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:copper_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ2AgAACAQAbmFtZRQAbWluZWNyYWZ0OmNvcHBlcl9vcmUECQBuYW1lX2hhc2iSZduSntOzOwMKAG5ldHdvcmtfaWQtIuCnCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:emerald_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSBAAAACAQAbmFtZRUAbWluZWNyYWZ0OmVtZXJhbGRfb3JlBAkAbmFtZV9oYXNoJTovr+VgINsDCgBuZXR3b3JrX2lknbkqCgoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:quartz_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSZAAAACAQAbmFtZRQAbWluZWNyYWZ0OnF1YXJ0el9vcmUECQBuYW1lX2hhc2g0yNHLMK9TaQMKAG5ldHdvcmtfaWSzN7nzCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:nether_gold_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQfAgAACAQAbmFtZRkAbWluZWNyYWZ0Om5ldGhlcl9nb2xkX29yZQQJAG5hbWVfaGFzaEJZ7segIBgBAwoAbmV0d29ya19pZNI9pDgKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:ancient_debris", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQOAgAACAQAbmFtZRgAbWluZWNyYWZ0OmFuY2llbnRfZGVicmlzBAkAbmFtZV9oYXNoNrbxMc9AwKcDCgBuZXR3b3JrX2lkrSNjEAoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:deepslate_iron_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSQAgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9pcm9uX29yZQQJAG5hbWVfaGFzaB/fDL9pgvXXAwoAbmV0d29ya19pZFA0bz4KBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:deepslate_gold_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSRAgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9nb2xkX29yZQQJAG5hbWVfaGFzaF9G7WYhKFinAwoAbmV0d29ya19pZHQTfBUKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:deepslate_diamond_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSUAgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV9kaWFtb25kX29yZQQJAG5hbWVfaGFzaEUH5USh+iD3AwoAbmV0d29ya19pZHP6VzAKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:deepslate_lapis_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSPAgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV9sYXBpc19vcmUECQBuYW1lX2hhc2j+yFxU/KZs1gMKAG5ldHdvcmtfaWRKINzICgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:deepslate_redstone_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSSAgAACAQAbmFtZSAAbWluZWNyYWZ0OmRlZXBzbGF0ZV9yZWRzdG9uZV9vcmUECQBuYW1lX2hhc2iVgM3wWWD6ugMKAG5ldHdvcmtfaWReBdYRCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:deepslate_emerald_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSWAgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV9lbWVyYWxkX29yZQQJAG5hbWVfaGFzaNlfo5HTwS6wAwoAbmV0d29ya19pZNeie6sKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:deepslate_coal_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSVAgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9jb2FsX29yZQQJAG5hbWVfaGFzaIjikmcbRrPPAwoAbmV0d29ya19pZD9TiygKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:deepslate_copper_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSXAgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9jb3BwZXJfb3JlBAkAbmFtZV9oYXNottjV4Ev5LAQDCgBuZXR3b3JrX2lkP23rgQoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:gravel", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQNAAAACAQAbmFtZRAAbWluZWNyYWZ0OmdyYXZlbAQJAG5hbWVfaGFzaOFxz8XJd2r/AwoAbmV0d29ya19pZBpfI1sKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:granite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRNAwAACAQAbmFtZREAbWluZWNyYWZ0OmdyYW5pdGUECQBuYW1lX2hhc2iq+Dur2pw4AwMKAG5ldHdvcmtfaWT2NMfJCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:diorite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRPAwAACAQAbmFtZREAbWluZWNyYWZ0OmRpb3JpdGUECQBuYW1lX2hhc2iaFsq2iinZBQMKAG5ldHdvcmtfaWQqGE6XCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:andesite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRRAwAACAQAbmFtZRIAbWluZWNyYWZ0OmFuZGVzaXRlBAkAbmFtZV9oYXNosaLIEnQQoSYDCgBuZXR3b3JrX2lkEApRZAoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:blackstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQQAgAACAQAbmFtZRQAbWluZWNyYWZ0OmJsYWNrc3RvbmUECQBuYW1lX2hhc2iMFYziD80D6QMKAG5ldHdvcmtfaWSrUryHCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:deepslate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR5AgAACAQAbmFtZRMAbWluZWNyYWZ0OmRlZXBzbGF0ZQQJAG5hbWVfaGFzaKX5pAblxz8TAwoAbmV0d29ya19pZOJoQjsKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:polished_granite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWROAwAACAQAbmFtZRoAbWluZWNyYWZ0OnBvbGlzaGVkX2dyYW5pdGUECQBuYW1lX2hhc2iLiEfys8pFIAMKAG5ldHdvcmtfaWTCxxcHCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:polished_diorite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRQAwAACAQAbmFtZRoAbWluZWNyYWZ0OnBvbGlzaGVkX2Rpb3JpdGUECQBuYW1lX2hhc2hTxY4fKmNmlAMKAG5ldHdvcmtfaWTmtjdRCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:polished_andesite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRSAwAACAQAbmFtZRsAbWluZWNyYWZ0OnBvbGlzaGVkX2FuZGVzaXRlBAkAbmFtZV9oYXNovl28uFk4HuQDCgBuZXR3b3JrX2lklFjuCwoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:polished_blackstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQiAgAACAQAbmFtZR0AbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmUECQBuYW1lX2hhc2jT9fHCl6vWQQMKAG5ldHdvcmtfaWR/Ho6oCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:polished_deepslate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR+AgAACAQAbmFtZRwAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaHC1edoaWF3uAwoAbmV0d29ya19pZCPeQsEKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:sand", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQMAAAACAQAbmFtZQ4AbWluZWNyYWZ0OnNhbmQECQBuYW1lX2hhc2i6lthXXbAyWAMKAG5ldHdvcmtfaWTekU/mCgYAc3RhdGVzCAkAc2FuZF90eXBlBgBub3JtYWwAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:sand", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQMAAAACAQAbmFtZQ4AbWluZWNyYWZ0OnNhbmQECQBuYW1lX2hhc2i6lthXXbAyWAMKAG5ldHdvcmtfaWSTgcqmCgYAc3RhdGVzCAkAc2FuZF90eXBlAwByZWQAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:cactus", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRRAAAACAQAbmFtZRAAbWluZWNyYWZ0OmNhY3R1cwQJAG5hbWVfaGFzaCG9zL0N4wvGAwoAbmV0d29ya19pZDeCERAKBgBzdGF0ZXMDAwBhZ2UAAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:oak_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQRAAAACAQAbmFtZREAbWluZWNyYWZ0Om9ha19sb2cECQBuYW1lX2hhc2ho6TS+K7PZFQMKAG5ldHdvcmtfaWQjfjoxCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:stripped_oak_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQJAQAACAQAbmFtZRoAbWluZWNyYWZ0OnN0cmlwcGVkX29ha19sb2cECQBuYW1lX2hhc2h8dqh+OOHU4wMKAG5ldHdvcmtfaWSYKjdrCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:spruce_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ4AwAACAQAbmFtZRQAbWluZWNyYWZ0OnNwcnVjZV9sb2cECQBuYW1lX2hhc2hZ03qaLoF3WgMKAG5ldHdvcmtfaWRlFD8eCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:stripped_spruce_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQEAQAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX3NwcnVjZV9sb2cECQBuYW1lX2hhc2iNrhKjS5IyrgMKAG5ldHdvcmtfaWRQcEC3CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:birch_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ5AwAACAQAbmFtZRMAbWluZWNyYWZ0OmJpcmNoX2xvZwQJAG5hbWVfaGFzaBUzT3NxsZAnAwoAbmV0d29ya19pZBKN3VQKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:stripped_birch_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQFAQAACAQAbmFtZRwAbWluZWNyYWZ0OnN0cmlwcGVkX2JpcmNoX2xvZwQJAG5hbWVfaGFzaCFKS4AeuSidAwoAbmV0d29ya19pZN0IONIKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:jungle_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ6AwAACAQAbmFtZRQAbWluZWNyYWZ0Omp1bmdsZV9sb2cECQBuYW1lX2hhc2gkwW0KNulqDgMKAG5ldHdvcmtfaWQaziU/CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:stripped_jungle_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAQAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2p1bmdsZV9sb2cECQBuYW1lX2hhc2hAwMsgOk02JAMKAG5ldHdvcmtfaWQvls0eCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:acacia_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSiAAAACAQAbmFtZRQAbWluZWNyYWZ0OmFjYWNpYV9sb2cECQBuYW1lX2hhc2iV48VpYhjoYQMKAG5ldHdvcmtfaWRxEqe0CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:stripped_acacia_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQHAQAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2FjYWNpYV9sb2cECQBuYW1lX2hhc2hJb0lQqnEqlgMKAG5ldHdvcmtfaWRg3IdRCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:dark_oak_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ7AwAACAQAbmFtZRYAbWluZWNyYWZ0OmRhcmtfb2FrX2xvZwQJAG5hbWVfaGFzaIWfVRd0XUo3AwoAbmV0d29ya19pZPMM7LYKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:stripped_dark_oak_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQIAQAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2Rhcmtfb2FrX2xvZwQJAG5hbWVfaGFzaPFTdxRdPwkOAwoAbmV0d29ya19pZDIzenIKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:mangrove_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTjAgAACAQAbmFtZRYAbWluZWNyYWZ0Om1hbmdyb3ZlX2xvZwQJAG5hbWVfaGFzaHZe6DzPZBobAwoAbmV0d29ya19pZG6DuYkKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:stripped_mangrove_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTkAgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX21hbmdyb3ZlX2xvZwQJAG5hbWVfaGFzaLqIBo4hwA//AwoAbmV0d29ya19pZPtRn7UKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:cherry_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQXAwAACAQAbmFtZRQAbWluZWNyYWZ0OmNoZXJyeV9sb2cECQBuYW1lX2hhc2hwFlaioppB1wMKAG5ldHdvcmtfaWS2sdXECgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:stripped_cherry_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQWAwAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2NoZXJyeV9sb2cECQBuYW1lX2hhc2i85H6G+WhXaAMKAG5ldHdvcmtfaWRjzoglCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:crimson_stem", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTgAQAACAQAbmFtZRYAbWluZWNyYWZ0OmNyaW1zb25fc3RlbQQJAG5hbWVfaGFzaM0FzfL0UTKZAwoAbmV0d29ya19pZKvzID0KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:stripped_crimson_stem", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTvAQAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2NyaW1zb25fc3RlbQQJAG5hbWVfaGFzaDlA6nood57EAwoAbmV0d29ya19pZHrIqjIKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:warped_stem", + "block_state_b64": "CgAAAwgAYmxvY2tfaWThAQAACAQAbmFtZRUAbWluZWNyYWZ0OndhcnBlZF9zdGVtBAkAbmFtZV9oYXNon7cKfPZxdrUDCgBuZXR3b3JrX2lkerWyMwoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:stripped_warped_stem", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTwAQAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX3dhcnBlZF9zdGVtBAkAbmFtZV9oYXNoEw+y0dDPSd8DCgBuZXR3b3JrX2lkIQ9vBAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:oak_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTTAQAACAQAbmFtZRIAbWluZWNyYWZ0Om9ha193b29kBAkAbmFtZV9oYXNoqQIkuVPyJX0DCgBuZXR3b3JrX2lku2G1YAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:spruce_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQtBAAACAQAbmFtZRUAbWluZWNyYWZ0OnNwcnVjZV93b29kBAkAbmFtZV9oYXNoTrIJ5TAQ+OgDCgBuZXR3b3JrX2lkaXLxCwoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:birch_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQuBAAACAQAbmFtZRQAbWluZWNyYWZ0OmJpcmNoX3dvb2QECQBuYW1lX2hhc2iqVjG4xt0cKQMKAG5ldHdvcmtfaWS06c5VCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:jungle_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQvBAAACAQAbmFtZRUAbWluZWNyYWZ0Omp1bmdsZV93b29kBAkAbmFtZV9oYXNo9bYW29ORWCoDCgBuZXR3b3JrX2lkyFyKLQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:acacia_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQwBAAACAQAbmFtZRUAbWluZWNyYWZ0OmFjYWNpYV93b29kBAkAbmFtZV9oYXNoKkDfgzlJUcIDCgBuZXR3b3JrX2lkuTWlcgoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:dark_oak_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQxBAAACAQAbmFtZRcAbWluZWNyYWZ0OmRhcmtfb2FrX3dvb2QECQBuYW1lX2hhc2jaKv4ORLadAAMKAG5ldHdvcmtfaWSDrNQ8CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:stripped_oak_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQyBAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0cmlwcGVkX29ha193b29kBAkAbmFtZV9oYXNovW6KCv+VZnsDCgBuZXR3b3JrX2lkkhWGegoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:stripped_spruce_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQzBAAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX3NwcnVjZV93b29kBAkAbmFtZV9oYXNoMnuUk4Xo6icDCgBuZXR3b3JrX2lkes2ydAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:stripped_birch_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ0BAAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2JpcmNoX3dvb2QECQBuYW1lX2hhc2hm88R604TKbAMKAG5ldHdvcmtfaWRleEMJCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:stripped_jungle_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ1BAAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX2p1bmdsZV93b29kBAkAbmFtZV9oYXNoUVs6KsZQRBoDCgBuZXR3b3JrX2lk92k8HQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:stripped_acacia_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ2BAAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX2FjYWNpYV93b29kBAkAbmFtZV9oYXNo/kOPN2bCJhUDCgBuZXR3b3JrX2lktl6LwQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:stripped_dark_oak_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ3BAAACAQAbmFtZSAAbWluZWNyYWZ0OnN0cmlwcGVkX2Rhcmtfb2FrX3dvb2QECQBuYW1lX2hhc2h2jFDfKVFgfAMKAG5ldHdvcmtfaWTgZQ5VCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:mangrove_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTwAgAACAQAbmFtZRcAbWluZWNyYWZ0Om1hbmdyb3ZlX3dvb2QECQBuYW1lX2hhc2iXVxG0JG2fVAMKAG5ldHdvcmtfaWTok1JCCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:stripped_mangrove_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTxAgAACAQAbmFtZSAAbWluZWNyYWZ0OnN0cmlwcGVkX21hbmdyb3ZlX3dvb2QECQBuYW1lX2hhc2h7CkbaBF7/WAMKAG5ldHdvcmtfaWQLAX88CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:cherry_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQhAwAACAQAbmFtZRUAbWluZWNyYWZ0OmNoZXJyeV93b29kBAkAbmFtZV9oYXNoAW8srlmpBM8DCgBuZXR3b3JrX2lkEALMfAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AQwAc3RyaXBwZWRfYml0AAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:stripped_cherry_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQgAwAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX2NoZXJyeV93b29kBAkAbmFtZV9oYXNo/e7KXv+CB38DCgBuZXR3b3JrX2lkg5aVtQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:crimson_hyphae", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQqAgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25faHlwaGFlBAkAbmFtZV9oYXNouRmKmfSqEWADCgBuZXR3b3JrX2lk+Tm5rQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:stripped_crimson_hyphae", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQrAgAACAQAbmFtZSEAbWluZWNyYWZ0OnN0cmlwcGVkX2NyaW1zb25faHlwaGFlBAkAbmFtZV9oYXNoFffwmABq4LUDCgBuZXR3b3JrX2lkZAlUbgoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:warped_hyphae", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQpAgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9oeXBoYWUECQBuYW1lX2hhc2hn8plQUr6pmQMKAG5ldHdvcmtfaWRU2AIBCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:stripped_warped_hyphae", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAgAACAQAbmFtZSAAbWluZWNyYWZ0OnN0cmlwcGVkX3dhcnBlZF9oeXBoYWUECQBuYW1lX2hhc2irKq+HYPSgjQMKAG5ldHdvcmtfaWSbrOPDCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:bamboo_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQOAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJhbWJvb19ibG9jawQJAG5hbWVfaGFzaAbDeur6stIBAwoAbmV0d29ya19pZCJAwn0KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:stripped_bamboo_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQPAwAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2JhbWJvb19ibG9jawQJAG5hbWVfaGFzaJpwytpZOZM9AwoAbmV0d29ya19pZKuRbNEKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:oak_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQSAAAACAQAbmFtZRQAbWluZWNyYWZ0Om9ha19sZWF2ZXMECQBuYW1lX2hhc2h6O4xGqA2oKgMKAG5ldHdvcmtfaWT98c59CgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:spruce_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQfBAAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9sZWF2ZXMECQBuYW1lX2hhc2i9x1CtNAuqZwMKAG5ldHdvcmtfaWSzF7pTCgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:birch_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQgBAAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX2xlYXZlcwQJAG5hbWVfaGFzaBlAGHaoaLZSAwoAbmV0d29ya19pZOjtvWcKBgBzdGF0ZXMBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:jungle_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQhBAAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9sZWF2ZXMECQBuYW1lX2hhc2iW1uAH07zGhgMKAG5ldHdvcmtfaWSA5KX0CgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:acacia_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAAAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9sZWF2ZXMECQBuYW1lX2hhc2iZJf8dAgDRNQMKAG5ldHdvcmtfaWQ/G7VuCgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:dark_oak_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQiBAAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX2xlYXZlcwQJAG5hbWVfaGFzaCk7rDipWFSjAwoAbmV0d29ya19pZJ2AkbYKBgBzdGF0ZXMBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:mangrove_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTXAgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX2xlYXZlcwQJAG5hbWVfaGFzaKyI/dWvhEG8AwoAbmV0d29ya19pZPQxCZ8KBgBzdGF0ZXMBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:cherry_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQjAwAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9sZWF2ZXMECQBuYW1lX2hhc2giTs9ChhYBlQMKAG5ldHdvcmtfaWR8bPpwCgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:azalea_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRDAgAACAQAbmFtZRcAbWluZWNyYWZ0OmF6YWxlYV9sZWF2ZXMECQBuYW1lX2hhc2iXFhD57wFS7AMKAG5ldHdvcmtfaWTNB/9ECgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:azalea_leaves_flowered", + "block_state_b64": "CgAAAwgAYmxvY2tfaWREAgAACAQAbmFtZSAAbWluZWNyYWZ0OmF6YWxlYV9sZWF2ZXNfZmxvd2VyZWQECQBuYW1lX2hhc2gs8jxlS/pMrwMKAG5ldHdvcmtfaWQ7W4PyCgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:oak_sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAAAACAQAbmFtZRUAbWluZWNyYWZ0Om9ha19zYXBsaW5nBAkAbmFtZV9oYXNoogXcT9QfjiUDCgBuZXR3b3JrX2lkG22C+AoGAHN0YXRlcwEHAGFnZV9iaXQAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:spruce_sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ4BAAACAQAbmFtZRgAbWluZWNyYWZ0OnNwcnVjZV9zYXBsaW5nBAkAbmFtZV9oYXNoe8hz4uYP0FcDCgBuZXR3b3JrX2lkUQmhaQoGAHN0YXRlcwEHAGFnZV9iaXQAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:birch_sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ5BAAACAQAbmFtZRcAbWluZWNyYWZ0OmJpcmNoX3NhcGxpbmcECQBuYW1lX2hhc2h348iJQ/tK4wMKAG5ldHdvcmtfaWQ2Uh53CgYAc3RhdGVzAQcAYWdlX2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:jungle_sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ6BAAACAQAbmFtZRgAbWluZWNyYWZ0Omp1bmdsZV9zYXBsaW5nBAkAbmFtZV9oYXNo7tyTOdSrxaADCgBuZXR3b3JrX2lkXmBAdAoGAHN0YXRlcwEHAGFnZV9iaXQAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:acacia_sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ7BAAACAQAbmFtZRgAbWluZWNyYWZ0OmFjYWNpYV9zYXBsaW5nBAkAbmFtZV9oYXNo99sg15uoX7ADCgBuZXR3b3JrX2lkPXX1KgoGAHN0YXRlcwEHAGFnZV9iaXQAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:dark_oak_sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ8BAAACAQAbmFtZRoAbWluZWNyYWZ0OmRhcmtfb2FrX3NhcGxpbmcECQBuYW1lX2hhc2jnVzFplW7cHgMKAG5ldHdvcmtfaWTD4giHCgYAc3RhdGVzAQcAYWdlX2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:mangrove_propagule", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTZAgAACAQAbmFtZRwAbWluZWNyYWZ0Om1hbmdyb3ZlX3Byb3BhZ3VsZQQJAG5hbWVfaGFzaJGeox6hkfLFAwoAbmV0d29ya19pZAIpvpYKBgBzdGF0ZXMBBwBoYW5naW5nAAMPAHByb3BhZ3VsZV9zdGFnZQAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:cherry_sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQiAwAACAQAbmFtZRgAbWluZWNyYWZ0OmNoZXJyeV9zYXBsaW5nBAkAbmFtZV9oYXNoGrPpNMf1LtcDCgBuZXR3b3JrX2lkypakXQoGAHN0YXRlcwEHAGFnZV9iaXQAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:bee_nest", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTZAQAACAQAbmFtZRIAbWluZWNyYWZ0OmJlZV9uZXN0BAkAbmFtZV9oYXNo2R2WBxUHEZIDCgBuZXR3b3JrX2lkiXWLEAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAADCwBob25leV9sZXZlbAAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:wheat_seeds" + }, + { + "id": "minecraft:pumpkin_seeds" + }, + { + "id": "minecraft:melon_seeds" + }, + { + "id": "minecraft:beetroot_seeds" + }, + { + "id": "minecraft:torchflower_seeds" + }, + { + "id": "minecraft:pitcher_pod" + }, + { + "id": "minecraft:wheat" + }, + { + "id": "minecraft:beetroot" + }, + { + "id": "minecraft:potato" + }, + { + "id": "minecraft:poisonous_potato" + }, + { + "id": "minecraft:carrot" + }, + { + "id": "minecraft:golden_carrot" + }, + { + "id": "minecraft:apple" + }, + { + "id": "minecraft:golden_apple" + }, + { + "id": "minecraft:enchanted_golden_apple" + }, + { + "id": "minecraft:melon_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRnAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1lbG9uX2Jsb2NrBAkAbmFtZV9oYXNoXxSm0iYpAx8DCgBuZXR3b3JrX2lkC9rqygoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:melon_slice" + }, + { + "id": "minecraft:glistering_melon_slice" + }, + { + "id": "minecraft:sweet_berries" + }, + { + "id": "minecraft:glow_berries" + }, + { + "id": "minecraft:pumpkin", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRWAAAACAQAbmFtZREAbWluZWNyYWZ0OnB1bXBraW4ECQBuYW1lX2hhc2gc8A3jaSzWbgMKAG5ldHdvcmtfaWRFGA+xCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:carved_pumpkin", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSaAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNhcnZlZF9wdW1wa2luBAkAbmFtZV9oYXNoPu1T0MJuG90DCgBuZXR3b3JrX2lkXNNn5QoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:lit_pumpkin", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRbAAAACAQAbmFtZRUAbWluZWNyYWZ0OmxpdF9wdW1wa2luBAkAbmFtZV9oYXNo7gWtEm2uPL0DCgBuZXR3b3JrX2lki8sU4AoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:honeycomb" + }, + { + "id": "minecraft:tallgrass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQfAAAACAQAbmFtZRMAbWluZWNyYWZ0OnRhbGxncmFzcwQJAG5hbWVfaGFzaC3PXpAXXYswAwoAbmV0d29ya19pZOh33DMKBgBzdGF0ZXMIDwB0YWxsX2dyYXNzX3R5cGUEAGZlcm4AAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:double_plant", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAAAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZMx1sfgKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQQAZmVybgEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:tallgrass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQfAAAACAQAbmFtZRMAbWluZWNyYWZ0OnRhbGxncmFzcwQJAG5hbWVfaGFzaC3PXpAXXYswAwoAbmV0d29ya19pZErptfIKBgBzdGF0ZXMIDwB0YWxsX2dyYXNzX3R5cGUEAHRhbGwAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:double_plant", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAAAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZAbadmIKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQUAZ3Jhc3MBDwB1cHBlcl9ibG9ja19iaXQAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:nether_sprouts" + }, + { + "id": "minecraft:fire_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRGAwAACAQAbmFtZRQAbWluZWNyYWZ0OmZpcmVfY29yYWwECQBuYW1lX2hhc2hOHyyECVQVJwMKAG5ldHdvcmtfaWS9vF0UCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:brain_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWREAwAACAQAbmFtZRUAbWluZWNyYWZ0OmJyYWluX2NvcmFsBAkAbmFtZV9oYXNoRiWlLCwA2ycDCgBuZXR3b3JrX2lkrjAuhgoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:bubble_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRFAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJ1YmJsZV9jb3JhbAQJAG5hbWVfaGFzaJz6rWnl+v2qAwoAbmV0d29ya19pZImIWy0KBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:tube_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSCAQAACAQAbmFtZRQAbWluZWNyYWZ0OnR1YmVfY29yYWwECQBuYW1lX2hhc2iYa8oO/tgk7wMKAG5ldHdvcmtfaWRTfND5CgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:horn_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRHAwAACAQAbmFtZRQAbWluZWNyYWZ0Omhvcm5fY29yYWwECQBuYW1lX2hhc2iZnRHjZbnLPgMKAG5ldHdvcmtfaWR+GGp8CgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:dead_fire_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRLAwAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfZmlyZV9jb3JhbAQJAG5hbWVfaGFzaEPU6tFy/latAwoAbmV0d29ya19pZNMa7V4KBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:dead_brain_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRJAwAACAQAbmFtZRoAbWluZWNyYWZ0OmRlYWRfYnJhaW5fY29yYWwECQBuYW1lX2hhc2j5L6QJCISvzwMKAG5ldHdvcmtfaWQkKzeiCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:dead_bubble_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRKAwAACAQAbmFtZRsAbWluZWNyYWZ0OmRlYWRfYnViYmxlX2NvcmFsBAkAbmFtZV9oYXNoSTOZ/8wpeNYDCgBuZXR3b3JrX2lka6w9DAoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:dead_tube_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRIAwAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfdHViZV9jb3JhbAQJAG5hbWVfaGFzaJGjNWhlaIJeAwoAbmV0d29ya19pZO3Z0ygKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:dead_horn_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRMAwAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfaG9ybl9jb3JhbAQJAG5hbWVfaGFzaJBkz3qt+g2cAwoAbmV0d29ya19pZBAN+eYKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:fire_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRJBAAACAQAbmFtZRgAbWluZWNyYWZ0OmZpcmVfY29yYWxfZmFuBAkAbmFtZV9oYXNosOTxYYxsDLgDCgBuZXR3b3JrX2lkFKxbEgoGAHN0YXRlcwMTAGNvcmFsX2Zhbl9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:brain_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRHBAAACAQAbmFtZRkAbWluZWNyYWZ0OmJyYWluX2NvcmFsX2ZhbgQJAG5hbWVfaGFzaAi5uHizSNcqAwoAbmV0d29ya19pZFtLjNwKBgBzdGF0ZXMDEwBjb3JhbF9mYW5fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:bubble_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRIBAAACAQAbmFtZRoAbWluZWNyYWZ0OmJ1YmJsZV9jb3JhbF9mYW4ECQBuYW1lX2hhc2hy/rX2on17DgMKAG5ldHdvcmtfaWQof60VCgYAc3RhdGVzAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:tube_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAQAACAQAbmFtZRgAbWluZWNyYWZ0OnR1YmVfY29yYWxfZmFuBAkAbmFtZV9oYXNo9pbJbo+PphIDCgBuZXR3b3JrX2lkenDTYgoGAHN0YXRlcwMTAGNvcmFsX2Zhbl9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:horn_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRKBAAACAQAbmFtZRgAbWluZWNyYWZ0Omhvcm5fY29yYWxfZmFuBAkAbmFtZV9oYXNoA+ri6NPDkbUDCgBuZXR3b3JrX2lkezoHNwoGAHN0YXRlcwMTAGNvcmFsX2Zhbl9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:dead_fire_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRNBAAACAQAbmFtZR0AbWluZWNyYWZ0OmRlYWRfZmlyZV9jb3JhbF9mYW4ECQBuYW1lX2hhc2hpQO02NDxPvwMKAG5ldHdvcmtfaWTaOJgLCgYAc3RhdGVzAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:dead_brain_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRLBAAACAQAbmFtZR4AbWluZWNyYWZ0OmRlYWRfYnJhaW5fY29yYWxfZmFuBAkAbmFtZV9oYXNoI9/+Z4YqMhIDCgBuZXR3b3JrX2lkqYXxYgoGAHN0YXRlcwMTAGNvcmFsX2Zhbl9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:dead_bubble_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRMBAAACAQAbmFtZR8AbWluZWNyYWZ0OmRlYWRfYnViYmxlX2NvcmFsX2ZhbgQJAG5hbWVfaGFzaBNECtIM6VIOAwoAbmV0d29ya19pZLrNtBEKBgBzdGF0ZXMDEwBjb3JhbF9mYW5fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:dead_tube_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAQAACAQAbmFtZR0AbWluZWNyYWZ0OmRlYWRfdHViZV9jb3JhbF9mYW4ECQBuYW1lX2hhc2hbBBM9jFKWvQMKAG5ldHdvcmtfaWSkJKUWCgYAc3RhdGVzAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:dead_horn_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWROBAAACAQAbmFtZR0AbWluZWNyYWZ0OmRlYWRfaG9ybl9jb3JhbF9mYW4ECQBuYW1lX2hhc2hObElFrHfPygMKAG5ldHdvcmtfaWQ1ZxvmCgYAc3RhdGVzAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:crimson_roots", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTeAQAACAQAbmFtZRcAbWluZWNyYWZ0OmNyaW1zb25fcm9vdHMECQBuYW1lX2hhc2j1fWgQLViv5QMKAG5ldHdvcmtfaWRLh5DXCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:warped_roots", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTfAQAACAQAbmFtZRYAbWluZWNyYWZ0OndhcnBlZF9yb290cwQJAG5hbWVfaGFzaBc3WvbJOLlkAwoAbmV0d29ya19pZNLgDnAKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:yellow_flower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQlAAAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19mbG93ZXIECQBuYW1lX2hhc2jWbU1pF0OUGAMKAG5ldHdvcmtfaWQgO3hpCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:poppy", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZQ8AbWluZWNyYWZ0OnBvcHB5BAkAbmFtZV9oYXNocMF8pITMbkcDCgBuZXR3b3JrX2lk8im6ywoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:blue_orchid", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ9BAAACAQAbmFtZRUAbWluZWNyYWZ0OmJsdWVfb3JjaGlkBAkAbmFtZV9oYXNoBjz2MsgB21EDCgBuZXR3b3JrX2lk/iLsSwoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:allium", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ+BAAACAQAbmFtZRAAbWluZWNyYWZ0OmFsbGl1bQQJAG5hbWVfaGFzaDCGQBHNDTkcAwoAbmV0d29ya19pZD9Dgr0KBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:azure_bluet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ/BAAACAQAbmFtZRUAbWluZWNyYWZ0OmF6dXJlX2JsdWV0BAkAbmFtZV9oYXNo9N5egqMT2QcDCgBuZXR3b3JrX2lkwIgDnwoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:red_tulip", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRABAAACAQAbmFtZRMAbWluZWNyYWZ0OnJlZF90dWxpcAQJAG5hbWVfaGFzaAjMi9Rd+6rhAwoAbmV0d29ya19pZAZCnt8KBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:orange_tulip", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRBBAAACAQAbmFtZRYAbWluZWNyYWZ0Om9yYW5nZV90dWxpcAQJAG5hbWVfaGFzaP+NjxMBZ8vAAwoAbmV0d29ya19pZPYatsMKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:white_tulip", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRCBAAACAQAbmFtZRUAbWluZWNyYWZ0OndoaXRlX3R1bGlwBAkAbmFtZV9oYXNo5vbU4VRPh3ADCgBuZXR3b3JrX2lkok+4rQoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:pink_tulip", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRDBAAACAQAbmFtZRQAbWluZWNyYWZ0OnBpbmtfdHVsaXAECQBuYW1lX2hhc2hxDHZa6OaNXAMKAG5ldHdvcmtfaWTiOT+VCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:oxeye_daisy", + "block_state_b64": "CgAAAwgAYmxvY2tfaWREBAAACAQAbmFtZRUAbWluZWNyYWZ0Om94ZXllX2RhaXN5BAkAbmFtZV9oYXNoXwxsqNQTN9gDCgBuZXR3b3JrX2lkw7R7dwoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:cornflower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRFBAAACAQAbmFtZRQAbWluZWNyYWZ0OmNvcm5mbG93ZXIECQBuYW1lX2hhc2gnhyC3EeqHgAMKAG5ldHdvcmtfaWR4VrvACgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:lily_of_the_valley", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRGBAAACAQAbmFtZRwAbWluZWNyYWZ0OmxpbHlfb2ZfdGhlX3ZhbGxleQQJAG5hbWVfaGFzaI64TJSf9mgQAwoAbmV0d29ya19pZFE9+nwKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:double_plant", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAAAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZOemRt4KBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQkAc3VuZmxvd2VyAQ8AdXBwZXJfYmxvY2tfYml0AAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:double_plant", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAAAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZOFugoEKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQcAc3lyaW5nYQEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:double_plant", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAAAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZN4O+/gKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQQAcm9zZQEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:double_plant", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAAAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZI3w4GMKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQcAcGFlb25pYQEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:pitcher_plant", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAwAACAQAbmFtZRcAbWluZWNyYWZ0OnBpdGNoZXJfcGxhbnQECQBuYW1lX2hhc2hRJHzsbDH+SQMKAG5ldHdvcmtfaWRnY76VCgYAc3RhdGVzAQ8AdXBwZXJfYmxvY2tfYml0AAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:pink_petals", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQkAwAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfcGV0YWxzBAkAbmFtZV9oYXNo6DQwN9SwV3QDCgBuZXR3b3JrX2lkNWneGgoGAHN0YXRlcwMGAGdyb3d0aAAAAAAIHABtaW5lY3JhZnQ6Y2FyZGluYWxfZGlyZWN0aW9uBQBzb3V0aAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:wither_rose", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTXAQAACAQAbmFtZRUAbWluZWNyYWZ0OndpdGhlcl9yb3NlBAkAbmFtZV9oYXNoaSKxl3I516gDCgBuZXR3b3JrX2lkATXLPwoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:torchflower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ3AwAACAQAbmFtZRUAbWluZWNyYWZ0OnRvcmNoZmxvd2VyBAkAbmFtZV9oYXNoL+mHtElwbqQDCgBuZXR3b3JrX2lkI34O+AoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:white_dye" + }, + { + "id": "minecraft:light_gray_dye" + }, + { + "id": "minecraft:gray_dye" + }, + { + "id": "minecraft:black_dye" + }, + { + "id": "minecraft:brown_dye" + }, + { + "id": "minecraft:red_dye" + }, + { + "id": "minecraft:orange_dye" + }, + { + "id": "minecraft:yellow_dye" + }, + { + "id": "minecraft:lime_dye" + }, + { + "id": "minecraft:green_dye" + }, + { + "id": "minecraft:cyan_dye" + }, + { + "id": "minecraft:light_blue_dye" + }, + { + "id": "minecraft:blue_dye" + }, + { + "id": "minecraft:purple_dye" + }, + { + "id": "minecraft:magenta_dye" + }, + { + "id": "minecraft:pink_dye" + }, + { + "id": "minecraft:ink_sac" + }, + { + "id": "minecraft:glow_ink_sac" + }, + { + "id": "minecraft:cocoa_beans" + }, + { + "id": "minecraft:lapis_lazuli" + }, + { + "id": "minecraft:bone_meal" + }, + { + "id": "minecraft:vine", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRqAAAACAQAbmFtZQ4AbWluZWNyYWZ0OnZpbmUECQBuYW1lX2hhc2j0Sj8/XeXOLAMKAG5ldHdvcmtfaWSUkDtbCgYAc3RhdGVzAxMAdmluZV9kaXJlY3Rpb25fYml0cwAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:weeping_vines", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTmAQAACAQAbmFtZRcAbWluZWNyYWZ0OndlZXBpbmdfdmluZXMECQBuYW1lX2hhc2jrLgLHkQygiwMKAG5ldHdvcmtfaWQ8NHSJCgYAc3RhdGVzAxEAd2VlcGluZ192aW5lc19hZ2UAAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:twisting_vines", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQeAgAACAQAbmFtZRgAbWluZWNyYWZ0OnR3aXN0aW5nX3ZpbmVzBAkAbmFtZV9oYXNoDYR5QgVUQJADCgBuZXR3b3JrX2lk5kYVIQoGAHN0YXRlcwMSAHR3aXN0aW5nX3ZpbmVzX2FnZQAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:waterlily", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRvAAAACAQAbmFtZRMAbWluZWNyYWZ0OndhdGVybGlseQQJAG5hbWVfaGFzaEHgC4c1SXg0AwoAbmV0d29ya19pZOOerp8KBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:seagrass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSBAQAACAQAbmFtZRIAbWluZWNyYWZ0OnNlYWdyYXNzBAkAbmFtZV9oYXNoHSBFtoHdWxIDCgBuZXR3b3JrX2lkd3lhEAoGAHN0YXRlcwgOAHNlYV9ncmFzc190eXBlBwBkZWZhdWx0AAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:kelp" + }, + { + "id": "minecraft:deadbush", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQgAAAACAQAbmFtZRIAbWluZWNyYWZ0OmRlYWRidXNoBAkAbmFtZV9oYXNoPFODe4IScnYDCgBuZXR3b3JrX2lkVfnl+goGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:bamboo", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSiAQAACAQAbmFtZRAAbWluZWNyYWZ0OmJhbWJvbwQJAG5hbWVfaGFzaBgpGmyzhedCAwoAbmV0d29ya19pZIZv1nYKBgBzdGF0ZXMBBwBhZ2VfYml0AAgQAGJhbWJvb19sZWFmX3NpemUJAG5vX2xlYXZlcwgWAGJhbWJvb19zdGFsa190aGlja25lc3MEAHRoaW4AAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:snow", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRQAAAACAQAbmFtZQ4AbWluZWNyYWZ0OnNub3cECQBuYW1lX2hhc2gVHr5XXdETWAMKAG5ldHdvcmtfaWQ0zCeHCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:ice", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRPAAAACAQAbmFtZQ0AbWluZWNyYWZ0OmljZQQJAG5hbWVfaGFzaNF26f+uUT29AwoAbmV0d29ya19pZOUMaQYKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:packed_ice", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSuAAAACAQAbmFtZRQAbWluZWNyYWZ0OnBhY2tlZF9pY2UECQBuYW1lX2hhc2hk4bu123ZrFgMKAG5ldHdvcmtfaWTr/ooaCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:blue_ice", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQKAQAACAQAbmFtZRIAbWluZWNyYWZ0OmJsdWVfaWNlBAkAbmFtZV9oYXNo+EKxYgFhKcgDCgBuZXR3b3JrX2lkxfsA8goGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:snow_layer", + "block_state_b64": "CgAAAwgAYmxvY2tfaWROAAAACAQAbmFtZRQAbWluZWNyYWZ0OnNub3dfbGF5ZXIECQBuYW1lX2hhc2hXka6atMYUCQMKAG5ldHdvcmtfaWRCrIPcCgYAc3RhdGVzAQsAY292ZXJlZF9iaXQAAwYAaGVpZ2h0AAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:pointed_dripstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQzAgAACAQAbmFtZRsAbWluZWNyYWZ0OnBvaW50ZWRfZHJpcHN0b25lBAkAbmFtZV9oYXNoJMISzmHQgt8DCgBuZXR3b3JrX2lkbWrtYgoGAHN0YXRlcwgTAGRyaXBzdG9uZV90aGlja25lc3MDAHRpcAEHAGhhbmdpbmcBAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:dripstone_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ8AgAACAQAbmFtZRkAbWluZWNyYWZ0OmRyaXBzdG9uZV9ibG9jawQJAG5hbWVfaGFzaIIXnEqY77YsAwoAbmV0d29ya19pZMZi2kwKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:moss_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWROAgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vc3NfY2FycGV0BAkAbmFtZV9oYXNo/NEDxRPTshYDCgBuZXR3b3JrX2lkaGG3QwoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:moss_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ/AgAACAQAbmFtZRQAbWluZWNyYWZ0Om1vc3NfYmxvY2sECQBuYW1lX2hhc2iovcsPUYX2tgMKAG5ldHdvcmtfaWT3JSbfCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:dirt_with_roots", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ9AgAACAQAbmFtZRkAbWluZWNyYWZ0OmRpcnRfd2l0aF9yb290cwQJAG5hbWVfaGFzaLCNDYPviDCIAwoAbmV0d29ya19pZNCkwzoKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:hanging_roots", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ+AgAACAQAbmFtZRcAbWluZWNyYWZ0Omhhbmdpbmdfcm9vdHMECQBuYW1lX2hhc2jaXn+Y5UZpDAMKAG5ldHdvcmtfaWRU4c2vCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:mangrove_roots", + "block_state_b64": "CgAAAwgAYmxvY2tfaWThAgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hbmdyb3ZlX3Jvb3RzBAkAbmFtZV9oYXNoa786PzQGZ6kDCgBuZXR3b3JrX2lklA0AHgoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:muddy_mangrove_roots", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTiAgAACAQAbmFtZR4AbWluZWNyYWZ0Om11ZGR5X21hbmdyb3ZlX3Jvb3RzBAkAbmFtZV9oYXNo9YApdHpo1RkDCgBuZXR3b3JrX2lkH0Oc4woGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:big_dripleaf", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRCAgAACAQAbmFtZRYAbWluZWNyYWZ0OmJpZ19kcmlwbGVhZgQJAG5hbWVfaGFzaGBEhXjo6qSdAwoAbmV0d29ya19pZMETsb8KBgBzdGF0ZXMBEQBiaWdfZHJpcGxlYWZfaGVhZAEIEQBiaWdfZHJpcGxlYWZfdGlsdAQAbm9uZQgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:small_dripleaf_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRPAgAACAQAbmFtZR4AbWluZWNyYWZ0OnNtYWxsX2RyaXBsZWFmX2Jsb2NrBAkAbmFtZV9oYXNojxRAgXP9uWADCgBuZXR3b3JrX2lkozbVPwoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24EAGVhc3QBDwB1cHBlcl9ibG9ja19iaXQBAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:spore_blossom", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRAAgAACAQAbmFtZRcAbWluZWNyYWZ0OnNwb3JlX2Jsb3Nzb20ECQBuYW1lX2hhc2il3U72Gbco2gMKAG5ldHdvcmtfaWSbbbgcCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:azalea", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRQAgAACAQAbmFtZRAAbWluZWNyYWZ0OmF6YWxlYQQJAG5hbWVfaGFzaNyUl+BW9JrBAwoAbmV0d29ya19pZO/XZtQKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:flowering_azalea", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRRAgAACAQAbmFtZRoAbWluZWNyYWZ0OmZsb3dlcmluZ19hemFsZWEECQBuYW1lX2hhc2ie9r33wz8kiwMKAG5ldHdvcmtfaWQ3ij0VCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:glow_lichen", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSaAgAACAQAbmFtZRUAbWluZWNyYWZ0Omdsb3dfbGljaGVuBAkAbmFtZV9oYXNobyPUrIYlo44DCgBuZXR3b3JrX2lkCh8lSAoGAHN0YXRlcwMZAG11bHRpX2ZhY2VfZGlyZWN0aW9uX2JpdHM/AAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:amethyst_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRGAgAACAQAbmFtZRgAbWluZWNyYWZ0OmFtZXRoeXN0X2Jsb2NrBAkAbmFtZV9oYXNob+JK1iiAthcDCgBuZXR3b3JrX2lk8HtpzgoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:budding_amethyst", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRHAgAACAQAbmFtZRoAbWluZWNyYWZ0OmJ1ZGRpbmdfYW1ldGh5c3QECQBuYW1lX2hhc2gJvAwfI14fxgMKAG5ldHdvcmtfaWTQYqfACgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:amethyst_cluster", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRIAgAACAQAbmFtZRoAbWluZWNyYWZ0OmFtZXRoeXN0X2NsdXN0ZXIECQBuYW1lX2hhc2jK82S88Jgm8wMKAG5ldHdvcmtfaWSCPMPGCgYAc3RhdGVzCBQAbWluZWNyYWZ0OmJsb2NrX2ZhY2UCAHVwAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:large_amethyst_bud", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRJAgAACAQAbmFtZRwAbWluZWNyYWZ0OmxhcmdlX2FtZXRoeXN0X2J1ZAQJAG5hbWVfaGFzaAHhdpWD+sd5AwoAbmV0d29ya19pZKkQxOcKBgBzdGF0ZXMIFABtaW5lY3JhZnQ6YmxvY2tfZmFjZQIAdXAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:medium_amethyst_bud", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRKAgAACAQAbmFtZR0AbWluZWNyYWZ0Om1lZGl1bV9hbWV0aHlzdF9idWQECQBuYW1lX2hhc2g5lBGtC0DzZQMKAG5ldHdvcmtfaWSYiP4gCgYAc3RhdGVzCBQAbWluZWNyYWZ0OmJsb2NrX2ZhY2UCAHVwAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:small_amethyst_bud", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRLAgAACAQAbmFtZRwAbWluZWNyYWZ0OnNtYWxsX2FtZXRoeXN0X2J1ZAQJAG5hbWVfaGFzaEnb4+q9PO4YAwoAbmV0d29ya19pZGWzxrQKBgBzdGF0ZXMIFABtaW5lY3JhZnQ6YmxvY2tfZmFjZQIAdXAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:tuff", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRMAgAACAQAbmFtZQ4AbWluZWNyYWZ0OnR1ZmYECQBuYW1lX2hhc2h1Rwc1XYsBGwMKAG5ldHdvcmtfaWRwQGn0CgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:calcite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRFAgAACAQAbmFtZREAbWluZWNyYWZ0OmNhbGNpdGUECQBuYW1lX2hhc2ixKLu8ZIdzDQMKAG5ldHdvcmtfaWQlSbJDCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:chicken" + }, + { + "id": "minecraft:porkchop" + }, + { + "id": "minecraft:beef" + }, + { + "id": "minecraft:mutton" + }, + { + "id": "minecraft:rabbit" + }, + { + "id": "minecraft:cod" + }, + { + "id": "minecraft:salmon" + }, + { + "id": "minecraft:tropical_fish" + }, + { + "id": "minecraft:pufferfish" + }, + { + "id": "minecraft:brown_mushroom", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQnAAAACAQAbmFtZRgAbWluZWNyYWZ0OmJyb3duX211c2hyb29tBAkAbmFtZV9oYXNonYw/FO78WDoDCgBuZXR3b3JrX2lkLh1OXAoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:red_mushroom", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQoAAAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZF9tdXNocm9vbQQJAG5hbWVfaGFzaPpzJua7669xAwoAbmV0d29ya19pZCvWPYkKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:crimson_fungus", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTjAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fZnVuZ3VzBAkAbmFtZV9oYXNolIcCUuFM2u0DCgBuZXR3b3JrX2lkD2NN0QoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:warped_fungus", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTkAQAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9mdW5ndXMECQBuYW1lX2hhc2gq8bSnRVTAFgMKAG5ldHdvcmtfaWTkwS+rCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:brown_mushroom_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAAAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkdOMhDAoGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cw4AAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:red_mushroom_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRkAAAACAQAbmFtZRwAbWluZWNyYWZ0OnJlZF9tdXNocm9vbV9ibG9jawQJAG5hbWVfaGFzaJTTyJbth9M9AwoAbmV0d29ya19pZM+AyboKBgBzdGF0ZXMDEgBodWdlX211c2hyb29tX2JpdHMOAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:brown_mushroom_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAAAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkbdt3CAoGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cw8AAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:brown_mushroom_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAAAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkSrMl9goGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cwAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:egg" + }, + { + "id": "minecraft:sugar_cane" + }, + { + "id": "minecraft:sugar" + }, + { + "id": "minecraft:rotten_flesh" + }, + { + "id": "minecraft:bone" + }, + { + "id": "minecraft:web", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQeAAAACAQAbmFtZQ0AbWluZWNyYWZ0OndlYgQJAG5hbWVfaGFzaA4GKQCvG4i9AwoAbmV0d29ya19pZApt+jgKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:spider_eye" + }, + { + "id": "minecraft:mob_spawner", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ0AAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vYl9zcGF3bmVyBAkAbmFtZV9oYXNoNwGrCV/Fkh8DCgBuZXR3b3JrX2lkM1wTmgoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:end_portal_frame", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR4AAAACAQAbmFtZRoAbWluZWNyYWZ0OmVuZF9wb3J0YWxfZnJhbWUECQBuYW1lX2hhc2gqofyUIjGOpQMKAG5ldHdvcmtfaWRbGHf8CgYAc3RhdGVzARIAZW5kX3BvcnRhbF9leWVfYml0AAgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:monster_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkqXH7RgoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGUFAHN0b25lAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:monster_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkeIBb6QoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGULAGNvYmJsZXN0b25lAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:monster_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkDZ2cFQoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGULAHN0b25lX2JyaWNrAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:monster_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkOR/cTAoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGURAG1vc3N5X3N0b25lX2JyaWNrAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:monster_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkqdwlHAoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGUTAGNyYWNrZWRfc3RvbmVfYnJpY2sAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:monster_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkFqqPggoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGUUAGNoaXNlbGVkX3N0b25lX2JyaWNrAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:infested_deepslate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTFAgAACAQAbmFtZRwAbWluZWNyYWZ0OmluZmVzdGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaICF2VYccxF1AwoAbmV0d29ya19pZDa/624KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:dragon_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR6AAAACAQAbmFtZRQAbWluZWNyYWZ0OmRyYWdvbl9lZ2cECQBuYW1lX2hhc2inMzXrV+/e1wMKAG5ldHdvcmtfaWTgO1yRCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:turtle_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSeAQAACAQAbmFtZRQAbWluZWNyYWZ0OnR1cnRsZV9lZ2cECQBuYW1lX2hhc2iwSRcxOJIJ9gMKAG5ldHdvcmtfaWSIRNUhCgYAc3RhdGVzCA0AY3JhY2tlZF9zdGF0ZQkAbm9fY3JhY2tzCBAAdHVydGxlX2VnZ19jb3VudAcAb25lX2VnZwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:sniffer_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRTAwAACAQAbmFtZRUAbWluZWNyYWZ0OnNuaWZmZXJfZWdnBAkAbmFtZV9oYXNoY1lozc8lPcYDCgBuZXR3b3JrX2lk7yb/2QoGAHN0YXRlcwgNAGNyYWNrZWRfc3RhdGUJAG5vX2NyYWNrcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:frog_spawn", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTTAgAACAQAbmFtZRQAbWluZWNyYWZ0OmZyb2dfc3Bhd24ECQBuYW1lX2hhc2iWmd7idp3ZZwMKAG5ldHdvcmtfaWRFzJudCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:pearlescent_froglight", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTUAgAACAQAbmFtZR8AbWluZWNyYWZ0OnBlYXJsZXNjZW50X2Zyb2dsaWdodAQJAG5hbWVfaGFzaKkcFRyycYGyAwoAbmV0d29ya19pZJqYakAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:verdant_froglight", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTVAgAACAQAbmFtZRsAbWluZWNyYWZ0OnZlcmRhbnRfZnJvZ2xpZ2h0BAkAbmFtZV9oYXNoA+eXuTBohrQDCgBuZXR3b3JrX2lkDIVnsQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:ochre_froglight", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTWAgAACAQAbmFtZRkAbWluZWNyYWZ0Om9jaHJlX2Zyb2dsaWdodAQJAG5hbWVfaGFzaMY59kjPe+c3AwoAbmV0d29ya19pZO2TD50KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:chicken_spawn_egg" + }, + { + "id": "minecraft:bee_spawn_egg" + }, + { + "id": "minecraft:cow_spawn_egg" + }, + { + "id": "minecraft:pig_spawn_egg" + }, + { + "id": "minecraft:sheep_spawn_egg" + }, + { + "id": "minecraft:wolf_spawn_egg" + }, + { + "id": "minecraft:polar_bear_spawn_egg" + }, + { + "id": "minecraft:ocelot_spawn_egg" + }, + { + "id": "minecraft:cat_spawn_egg" + }, + { + "id": "minecraft:mooshroom_spawn_egg" + }, + { + "id": "minecraft:bat_spawn_egg" + }, + { + "id": "minecraft:parrot_spawn_egg" + }, + { + "id": "minecraft:rabbit_spawn_egg" + }, + { + "id": "minecraft:llama_spawn_egg" + }, + { + "id": "minecraft:horse_spawn_egg" + }, + { + "id": "minecraft:donkey_spawn_egg" + }, + { + "id": "minecraft:mule_spawn_egg" + }, + { + "id": "minecraft:skeleton_horse_spawn_egg" + }, + { + "id": "minecraft:zombie_horse_spawn_egg" + }, + { + "id": "minecraft:tropical_fish_spawn_egg" + }, + { + "id": "minecraft:cod_spawn_egg" + }, + { + "id": "minecraft:pufferfish_spawn_egg" + }, + { + "id": "minecraft:salmon_spawn_egg" + }, + { + "id": "minecraft:dolphin_spawn_egg" + }, + { + "id": "minecraft:turtle_spawn_egg" + }, + { + "id": "minecraft:panda_spawn_egg" + }, + { + "id": "minecraft:fox_spawn_egg" + }, + { + "id": "minecraft:creeper_spawn_egg" + }, + { + "id": "minecraft:enderman_spawn_egg" + }, + { + "id": "minecraft:silverfish_spawn_egg" + }, + { + "id": "minecraft:skeleton_spawn_egg" + }, + { + "id": "minecraft:wither_skeleton_spawn_egg" + }, + { + "id": "minecraft:stray_spawn_egg" + }, + { + "id": "minecraft:slime_spawn_egg" + }, + { + "id": "minecraft:spider_spawn_egg" + }, + { + "id": "minecraft:zombie_spawn_egg" + }, + { + "id": "minecraft:zombie_pigman_spawn_egg" + }, + { + "id": "minecraft:husk_spawn_egg" + }, + { + "id": "minecraft:drowned_spawn_egg" + }, + { + "id": "minecraft:squid_spawn_egg" + }, + { + "id": "minecraft:glow_squid_spawn_egg" + }, + { + "id": "minecraft:cave_spider_spawn_egg" + }, + { + "id": "minecraft:witch_spawn_egg" + }, + { + "id": "minecraft:guardian_spawn_egg" + }, + { + "id": "minecraft:elder_guardian_spawn_egg" + }, + { + "id": "minecraft:endermite_spawn_egg" + }, + { + "id": "minecraft:magma_cube_spawn_egg" + }, + { + "id": "minecraft:strider_spawn_egg" + }, + { + "id": "minecraft:hoglin_spawn_egg" + }, + { + "id": "minecraft:piglin_spawn_egg" + }, + { + "id": "minecraft:zoglin_spawn_egg" + }, + { + "id": "minecraft:piglin_brute_spawn_egg" + }, + { + "id": "minecraft:goat_spawn_egg" + }, + { + "id": "minecraft:axolotl_spawn_egg" + }, + { + "id": "minecraft:warden_spawn_egg" + }, + { + "id": "minecraft:allay_spawn_egg" + }, + { + "id": "minecraft:frog_spawn_egg" + }, + { + "id": "minecraft:tadpole_spawn_egg" + }, + { + "id": "minecraft:trader_llama_spawn_egg" + }, + { + "id": "minecraft:camel_spawn_egg" + }, + { + "id": "minecraft:ghast_spawn_egg" + }, + { + "id": "minecraft:blaze_spawn_egg" + }, + { + "id": "minecraft:shulker_spawn_egg" + }, + { + "id": "minecraft:vindicator_spawn_egg" + }, + { + "id": "minecraft:evoker_spawn_egg" + }, + { + "id": "minecraft:vex_spawn_egg" + }, + { + "id": "minecraft:villager_spawn_egg" + }, + { + "id": "minecraft:wandering_trader_spawn_egg" + }, + { + "id": "minecraft:zombie_villager_spawn_egg" + }, + { + "id": "minecraft:phantom_spawn_egg" + }, + { + "id": "minecraft:pillager_spawn_egg" + }, + { + "id": "minecraft:ravager_spawn_egg" + }, + { + "id": "minecraft:iron_golem_spawn_egg" + }, + { + "id": "minecraft:snow_golem_spawn_egg" + }, + { + "id": "minecraft:sniffer_spawn_egg" + }, + { + "id": "minecraft:armadillo_spawn_egg" + }, + { + "id": "minecraft:obsidian", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQxAAAACAQAbmFtZRIAbWluZWNyYWZ0Om9ic2lkaWFuBAkAbmFtZV9oYXNoiz4qrb8QjyEDCgBuZXR3b3JrX2lkuqnPpQoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:crying_obsidian", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQgAgAACAQAbmFtZRkAbWluZWNyYWZ0OmNyeWluZ19vYnNpZGlhbgQJAG5hbWVfaGFzaKT0JlA7Z1K+AwoAbmV0d29ya19pZCjbPV4KBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:bedrock", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQHAAAACAQAbmFtZREAbWluZWNyYWZ0OmJlZHJvY2sECQBuYW1lX2hhc2hWfFrh4LVtxwMKAG5ldHdvcmtfaWT7fKz1CgYAc3RhdGVzAQ4AaW5maW5pYnVybl9iaXQAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:soul_sand", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRYAAAACAQAbmFtZRMAbWluZWNyYWZ0OnNvdWxfc2FuZAQJAG5hbWVfaGFzaMaf+bccu+KTAwoAbmV0d29ya19pZBQSHrMKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:magma", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTVAAAACAQAbmFtZQ8AbWluZWNyYWZ0Om1hZ21hBAkAbmFtZV9oYXNoqyTjKaIsWfYDCgBuZXR3b3JrX2lkyfWAZgoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:nether_wart" + }, + { + "id": "minecraft:end_stone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR5AAAACAQAbmFtZRMAbWluZWNyYWZ0OmVuZF9zdG9uZQQJAG5hbWVfaGFzaH1J9jA39GJNAwoAbmV0d29ya19pZFeFQ7UKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:chorus_flower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTIAAAACAQAbmFtZRcAbWluZWNyYWZ0OmNob3J1c19mbG93ZXIECQBuYW1lX2hhc2iMpSodli5uawMKAG5ldHdvcmtfaWRnd1ZWCgYAc3RhdGVzAwMAYWdlAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:chorus_plant", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTwAAAACAQAbmFtZRYAbWluZWNyYWZ0OmNob3J1c19wbGFudAQJAG5hbWVfaGFzaJhSrmNGKwaMAwoAbmV0d29ya19pZA3uVqMKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:chorus_fruit" + }, + { + "id": "minecraft:popped_chorus_fruit" + }, + { + "id": "minecraft:sponge", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQTAAAACAQAbmFtZRAAbWluZWNyYWZ0OnNwb25nZQQJAG5hbWVfaGFzaLrd2ScYRDMiAwoAbmV0d29ya19pZF01rO0KBgBzdGF0ZXMICwBzcG9uZ2VfdHlwZQMAZHJ5AAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:sponge", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQTAAAACAQAbmFtZRAAbWluZWNyYWZ0OnNwb25nZQQJAG5hbWVfaGFzaLrd2ScYRDMiAwoAbmV0d29ya19pZPiOc4QKBgBzdGF0ZXMICwBzcG9uZ2VfdHlwZQMAd2V0AAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkGnlaAwoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABibHVlAQgAZGVhZF9iaXQAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkSnHuagoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABwaW5rAQgAZGVhZF9iaXQAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkmkHyegoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgBwdXJwbGUBCABkZWFkX2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkdpUDxgoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yAwByZWQBCABkZWFkX2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkYNWvYgoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgB5ZWxsb3cBCABkZWFkX2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkZSxBQgoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABibHVlAQgAZGVhZF9iaXQBAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lklSTVqQoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABwaW5rAQgAZGVhZF9iaXQBAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lk5fTYuQoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgBwdXJwbGUBCABkZWFkX2JpdAEAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkwUjqBAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yAwByZWQBCABkZWFkX2JpdAEAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkq4iWoQoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgB5ZWxsb3cBCABkZWFkX2JpdAEAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:sculk", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAgAACAQAbmFtZQ8AbWluZWNyYWZ0OnNjdWxrBAkAbmFtZV9oYXNo2Lq7T5yQF8kDCgBuZXR3b3JrX2lkyqUPPgoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:sculk_vein", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTKAgAACAQAbmFtZRQAbWluZWNyYWZ0OnNjdWxrX3ZlaW4ECQBuYW1lX2hhc2gJUdhVooV4zwMKAG5ldHdvcmtfaWSUfn1XCgYAc3RhdGVzAxkAbXVsdGlfZmFjZV9kaXJlY3Rpb25fYml0cwAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:sculk_catalyst", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTLAgAACAQAbmFtZRgAbWluZWNyYWZ0OnNjdWxrX2NhdGFseXN0BAkAbmFtZV9oYXNo+gCpbrCHST4DCgBuZXR3b3JrX2lkMJ2n/woGAHN0YXRlcwEFAGJsb29tAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:sculk_shrieker", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTMAgAACAQAbmFtZRgAbWluZWNyYWZ0OnNjdWxrX3Nocmlla2VyBAkAbmFtZV9oYXNo5OXtyObniQ4DCgBuZXR3b3JrX2lkxapoNAoGAHN0YXRlcwEGAGFjdGl2ZQABCgBjYW5fc3VtbW9uAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:sculk_sensor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQyAgAACAQAbmFtZRYAbWluZWNyYWZ0OnNjdWxrX3NlbnNvcgQJAG5hbWVfaGFzaCkmHreeTgNnAwoAbmV0d29ya19pZLj2WPcKBgBzdGF0ZXMDEgBzY3Vsa19zZW5zb3JfcGhhc2UAAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:calibrated_sculk_sensor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRDAwAACAQAbmFtZSEAbWluZWNyYWZ0OmNhbGlicmF0ZWRfc2N1bGtfc2Vuc29yBAkAbmFtZV9oYXNoffAcXXN/iJUDCgBuZXR3b3JrX2lkwOx3QQoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAxIAc2N1bGtfc2Vuc29yX3BoYXNlAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:reinforced_deepslate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTRAgAACAQAbmFtZR4AbWluZWNyYWZ0OnJlaW5mb3JjZWRfZGVlcHNsYXRlBAkAbmFtZV9oYXNoldDmj91EapQDCgBuZXR3b3JrX2lkHIt+aQoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:leather_helmet" + }, + { + "id": "minecraft:chainmail_helmet" + }, + { + "id": "minecraft:iron_helmet" + }, + { + "id": "minecraft:golden_helmet" + }, + { + "id": "minecraft:diamond_helmet" + }, + { + "id": "minecraft:netherite_helmet" + }, + { + "id": "minecraft:leather_chestplate" + }, + { + "id": "minecraft:chainmail_chestplate" + }, + { + "id": "minecraft:iron_chestplate" + }, + { + "id": "minecraft:golden_chestplate" + }, + { + "id": "minecraft:diamond_chestplate" + }, + { + "id": "minecraft:netherite_chestplate" + }, + { + "id": "minecraft:leather_leggings" + }, + { + "id": "minecraft:chainmail_leggings" + }, + { + "id": "minecraft:iron_leggings" + }, + { + "id": "minecraft:golden_leggings" + }, + { + "id": "minecraft:diamond_leggings" + }, + { + "id": "minecraft:netherite_leggings" + }, + { + "id": "minecraft:leather_boots" + }, + { + "id": "minecraft:chainmail_boots" + }, + { + "id": "minecraft:iron_boots" + }, + { + "id": "minecraft:golden_boots" + }, + { + "id": "minecraft:diamond_boots" + }, + { + "id": "minecraft:netherite_boots" + }, + { + "id": "minecraft:wooden_sword" + }, + { + "id": "minecraft:stone_sword" + }, + { + "id": "minecraft:iron_sword" + }, + { + "id": "minecraft:golden_sword" + }, + { + "id": "minecraft:diamond_sword" + }, + { + "id": "minecraft:netherite_sword" + }, + { + "id": "minecraft:wooden_axe" + }, + { + "id": "minecraft:stone_axe" + }, + { + "id": "minecraft:iron_axe" + }, + { + "id": "minecraft:golden_axe" + }, + { + "id": "minecraft:diamond_axe" + }, + { + "id": "minecraft:netherite_axe" + }, + { + "id": "minecraft:wooden_pickaxe" + }, + { + "id": "minecraft:stone_pickaxe" + }, + { + "id": "minecraft:iron_pickaxe" + }, + { + "id": "minecraft:golden_pickaxe" + }, + { + "id": "minecraft:diamond_pickaxe" + }, + { + "id": "minecraft:netherite_pickaxe" + }, + { + "id": "minecraft:wooden_shovel" + }, + { + "id": "minecraft:stone_shovel" + }, + { + "id": "minecraft:iron_shovel" + }, + { + "id": "minecraft:golden_shovel" + }, + { + "id": "minecraft:diamond_shovel" + }, + { + "id": "minecraft:netherite_shovel" + }, + { + "id": "minecraft:wooden_hoe" + }, + { + "id": "minecraft:stone_hoe" + }, + { + "id": "minecraft:iron_hoe" + }, + { + "id": "minecraft:golden_hoe" + }, + { + "id": "minecraft:diamond_hoe" + }, + { + "id": "minecraft:netherite_hoe" + }, + { + "id": "minecraft:bow" + }, + { + "id": "minecraft:crossbow" + }, + { + "id": "minecraft:arrow" + }, + { + "id": "minecraft:arrow", + "damage": 6 + }, + { + "id": "minecraft:arrow", + "damage": 7 + }, + { + "id": "minecraft:arrow", + "damage": 8 + }, + { + "id": "minecraft:arrow", + "damage": 9 + }, + { + "id": "minecraft:arrow", + "damage": 10 + }, + { + "id": "minecraft:arrow", + "damage": 11 + }, + { + "id": "minecraft:arrow", + "damage": 12 + }, + { + "id": "minecraft:arrow", + "damage": 13 + }, + { + "id": "minecraft:arrow", + "damage": 14 + }, + { + "id": "minecraft:arrow", + "damage": 15 + }, + { + "id": "minecraft:arrow", + "damage": 16 + }, + { + "id": "minecraft:arrow", + "damage": 17 + }, + { + "id": "minecraft:arrow", + "damage": 18 + }, + { + "id": "minecraft:arrow", + "damage": 19 + }, + { + "id": "minecraft:arrow", + "damage": 20 + }, + { + "id": "minecraft:arrow", + "damage": 21 + }, + { + "id": "minecraft:arrow", + "damage": 22 + }, + { + "id": "minecraft:arrow", + "damage": 23 + }, + { + "id": "minecraft:arrow", + "damage": 24 + }, + { + "id": "minecraft:arrow", + "damage": 25 + }, + { + "id": "minecraft:arrow", + "damage": 26 + }, + { + "id": "minecraft:arrow", + "damage": 27 + }, + { + "id": "minecraft:arrow", + "damage": 28 + }, + { + "id": "minecraft:arrow", + "damage": 29 + }, + { + "id": "minecraft:arrow", + "damage": 30 + }, + { + "id": "minecraft:arrow", + "damage": 31 + }, + { + "id": "minecraft:arrow", + "damage": 32 + }, + { + "id": "minecraft:arrow", + "damage": 33 + }, + { + "id": "minecraft:arrow", + "damage": 34 + }, + { + "id": "minecraft:arrow", + "damage": 35 + }, + { + "id": "minecraft:arrow", + "damage": 36 + }, + { + "id": "minecraft:arrow", + "damage": 37 + }, + { + "id": "minecraft:arrow", + "damage": 38 + }, + { + "id": "minecraft:arrow", + "damage": 39 + }, + { + "id": "minecraft:arrow", + "damage": 40 + }, + { + "id": "minecraft:arrow", + "damage": 41 + }, + { + "id": "minecraft:arrow", + "damage": 42 + }, + { + "id": "minecraft:arrow", + "damage": 43 + }, + { + "id": "minecraft:shield" + }, + { + "id": "minecraft:cooked_chicken" + }, + { + "id": "minecraft:cooked_porkchop" + }, + { + "id": "minecraft:cooked_beef" + }, + { + "id": "minecraft:cooked_mutton" + }, + { + "id": "minecraft:cooked_rabbit" + }, + { + "id": "minecraft:cooked_cod" + }, + { + "id": "minecraft:cooked_salmon" + }, + { + "id": "minecraft:bread" + }, + { + "id": "minecraft:mushroom_stew" + }, + { + "id": "minecraft:beetroot_soup" + }, + { + "id": "minecraft:rabbit_stew" + }, + { + "id": "minecraft:baked_potato" + }, + { + "id": "minecraft:cookie" + }, + { + "id": "minecraft:pumpkin_pie" + }, + { + "id": "minecraft:cake" + }, + { + "id": "minecraft:dried_kelp" + }, + { + "id": "minecraft:fishing_rod" + }, + { + "id": "minecraft:carrot_on_a_stick" + }, + { + "id": "minecraft:warped_fungus_on_a_stick" + }, + { + "id": "minecraft:snowball" + }, + { + "id": "minecraft:shears" + }, + { + "id": "minecraft:flint_and_steel" + }, + { + "id": "minecraft:lead" + }, + { + "id": "minecraft:clock" + }, + { + "id": "minecraft:compass" + }, + { + "id": "minecraft:recovery_compass" + }, + { + "id": "minecraft:goat_horn" + }, + { + "id": "minecraft:goat_horn", + "damage": 1 + }, + { + "id": "minecraft:goat_horn", + "damage": 2 + }, + { + "id": "minecraft:goat_horn", + "damage": 3 + }, + { + "id": "minecraft:goat_horn", + "damage": 4 + }, + { + "id": "minecraft:goat_horn", + "damage": 5 + }, + { + "id": "minecraft:goat_horn", + "damage": 6 + }, + { + "id": "minecraft:goat_horn", + "damage": 7 + }, + { + "id": "minecraft:empty_map" + }, + { + "id": "minecraft:empty_map", + "damage": 2 + }, + { + "id": "minecraft:saddle" + }, + { + "id": "minecraft:leather_horse_armor" + }, + { + "id": "minecraft:iron_horse_armor" + }, + { + "id": "minecraft:golden_horse_armor" + }, + { + "id": "minecraft:diamond_horse_armor" + }, + { + "id": "minecraft:wolf_armor" + }, + { + "id": "minecraft:trident" + }, + { + "id": "minecraft:turtle_helmet" + }, + { + "id": "minecraft:elytra" + }, + { + "id": "minecraft:totem_of_undying" + }, + { + "id": "minecraft:glass_bottle" + }, + { + "id": "minecraft:experience_bottle" + }, + { + "id": "minecraft:potion" + }, + { + "id": "minecraft:potion", + "damage": 1 + }, + { + "id": "minecraft:potion", + "damage": 2 + }, + { + "id": "minecraft:potion", + "damage": 3 + }, + { + "id": "minecraft:potion", + "damage": 4 + }, + { + "id": "minecraft:potion", + "damage": 5 + }, + { + "id": "minecraft:potion", + "damage": 6 + }, + { + "id": "minecraft:potion", + "damage": 7 + }, + { + "id": "minecraft:potion", + "damage": 8 + }, + { + "id": "minecraft:potion", + "damage": 9 + }, + { + "id": "minecraft:potion", + "damage": 10 + }, + { + "id": "minecraft:potion", + "damage": 11 + }, + { + "id": "minecraft:potion", + "damage": 12 + }, + { + "id": "minecraft:potion", + "damage": 13 + }, + { + "id": "minecraft:potion", + "damage": 14 + }, + { + "id": "minecraft:potion", + "damage": 15 + }, + { + "id": "minecraft:potion", + "damage": 16 + }, + { + "id": "minecraft:potion", + "damage": 17 + }, + { + "id": "minecraft:potion", + "damage": 18 + }, + { + "id": "minecraft:potion", + "damage": 19 + }, + { + "id": "minecraft:potion", + "damage": 20 + }, + { + "id": "minecraft:potion", + "damage": 21 + }, + { + "id": "minecraft:potion", + "damage": 22 + }, + { + "id": "minecraft:potion", + "damage": 23 + }, + { + "id": "minecraft:potion", + "damage": 24 + }, + { + "id": "minecraft:potion", + "damage": 25 + }, + { + "id": "minecraft:potion", + "damage": 26 + }, + { + "id": "minecraft:potion", + "damage": 27 + }, + { + "id": "minecraft:potion", + "damage": 28 + }, + { + "id": "minecraft:potion", + "damage": 29 + }, + { + "id": "minecraft:potion", + "damage": 30 + }, + { + "id": "minecraft:potion", + "damage": 31 + }, + { + "id": "minecraft:potion", + "damage": 32 + }, + { + "id": "minecraft:potion", + "damage": 33 + }, + { + "id": "minecraft:potion", + "damage": 34 + }, + { + "id": "minecraft:potion", + "damage": 35 + }, + { + "id": "minecraft:potion", + "damage": 36 + }, + { + "id": "minecraft:potion", + "damage": 37 + }, + { + "id": "minecraft:potion", + "damage": 38 + }, + { + "id": "minecraft:potion", + "damage": 39 + }, + { + "id": "minecraft:potion", + "damage": 40 + }, + { + "id": "minecraft:potion", + "damage": 41 + }, + { + "id": "minecraft:potion", + "damage": 42 + }, + { + "id": "minecraft:splash_potion" + }, + { + "id": "minecraft:splash_potion", + "damage": 1 + }, + { + "id": "minecraft:splash_potion", + "damage": 2 + }, + { + "id": "minecraft:splash_potion", + "damage": 3 + }, + { + "id": "minecraft:splash_potion", + "damage": 4 + }, + { + "id": "minecraft:splash_potion", + "damage": 5 + }, + { + "id": "minecraft:splash_potion", + "damage": 6 + }, + { + "id": "minecraft:splash_potion", + "damage": 7 + }, + { + "id": "minecraft:splash_potion", + "damage": 8 + }, + { + "id": "minecraft:splash_potion", + "damage": 9 + }, + { + "id": "minecraft:splash_potion", + "damage": 10 + }, + { + "id": "minecraft:splash_potion", + "damage": 11 + }, + { + "id": "minecraft:splash_potion", + "damage": 12 + }, + { + "id": "minecraft:splash_potion", + "damage": 13 + }, + { + "id": "minecraft:splash_potion", + "damage": 14 + }, + { + "id": "minecraft:splash_potion", + "damage": 15 + }, + { + "id": "minecraft:splash_potion", + "damage": 16 + }, + { + "id": "minecraft:splash_potion", + "damage": 17 + }, + { + "id": "minecraft:splash_potion", + "damage": 18 + }, + { + "id": "minecraft:splash_potion", + "damage": 19 + }, + { + "id": "minecraft:splash_potion", + "damage": 20 + }, + { + "id": "minecraft:splash_potion", + "damage": 21 + }, + { + "id": "minecraft:splash_potion", + "damage": 22 + }, + { + "id": "minecraft:splash_potion", + "damage": 23 + }, + { + "id": "minecraft:splash_potion", + "damage": 24 + }, + { + "id": "minecraft:splash_potion", + "damage": 25 + }, + { + "id": "minecraft:splash_potion", + "damage": 26 + }, + { + "id": "minecraft:splash_potion", + "damage": 27 + }, + { + "id": "minecraft:splash_potion", + "damage": 28 + }, + { + "id": "minecraft:splash_potion", + "damage": 29 + }, + { + "id": "minecraft:splash_potion", + "damage": 30 + }, + { + "id": "minecraft:splash_potion", + "damage": 31 + }, + { + "id": "minecraft:splash_potion", + "damage": 32 + }, + { + "id": "minecraft:splash_potion", + "damage": 33 + }, + { + "id": "minecraft:splash_potion", + "damage": 34 + }, + { + "id": "minecraft:splash_potion", + "damage": 35 + }, + { + "id": "minecraft:splash_potion", + "damage": 36 + }, + { + "id": "minecraft:splash_potion", + "damage": 37 + }, + { + "id": "minecraft:splash_potion", + "damage": 38 + }, + { + "id": "minecraft:splash_potion", + "damage": 39 + }, + { + "id": "minecraft:splash_potion", + "damage": 40 + }, + { + "id": "minecraft:splash_potion", + "damage": 41 + }, + { + "id": "minecraft:splash_potion", + "damage": 42 + }, + { + "id": "minecraft:lingering_potion" + }, + { + "id": "minecraft:lingering_potion", + "damage": 1 + }, + { + "id": "minecraft:lingering_potion", + "damage": 2 + }, + { + "id": "minecraft:lingering_potion", + "damage": 3 + }, + { + "id": "minecraft:lingering_potion", + "damage": 4 + }, + { + "id": "minecraft:lingering_potion", + "damage": 5 + }, + { + "id": "minecraft:lingering_potion", + "damage": 6 + }, + { + "id": "minecraft:lingering_potion", + "damage": 7 + }, + { + "id": "minecraft:lingering_potion", + "damage": 8 + }, + { + "id": "minecraft:lingering_potion", + "damage": 9 + }, + { + "id": "minecraft:lingering_potion", + "damage": 10 + }, + { + "id": "minecraft:lingering_potion", + "damage": 11 + }, + { + "id": "minecraft:lingering_potion", + "damage": 12 + }, + { + "id": "minecraft:lingering_potion", + "damage": 13 + }, + { + "id": "minecraft:lingering_potion", + "damage": 14 + }, + { + "id": "minecraft:lingering_potion", + "damage": 15 + }, + { + "id": "minecraft:lingering_potion", + "damage": 16 + }, + { + "id": "minecraft:lingering_potion", + "damage": 17 + }, + { + "id": "minecraft:lingering_potion", + "damage": 18 + }, + { + "id": "minecraft:lingering_potion", + "damage": 19 + }, + { + "id": "minecraft:lingering_potion", + "damage": 20 + }, + { + "id": "minecraft:lingering_potion", + "damage": 21 + }, + { + "id": "minecraft:lingering_potion", + "damage": 22 + }, + { + "id": "minecraft:lingering_potion", + "damage": 23 + }, + { + "id": "minecraft:lingering_potion", + "damage": 24 + }, + { + "id": "minecraft:lingering_potion", + "damage": 25 + }, + { + "id": "minecraft:lingering_potion", + "damage": 26 + }, + { + "id": "minecraft:lingering_potion", + "damage": 27 + }, + { + "id": "minecraft:lingering_potion", + "damage": 28 + }, + { + "id": "minecraft:lingering_potion", + "damage": 29 + }, + { + "id": "minecraft:lingering_potion", + "damage": 30 + }, + { + "id": "minecraft:lingering_potion", + "damage": 31 + }, + { + "id": "minecraft:lingering_potion", + "damage": 32 + }, + { + "id": "minecraft:lingering_potion", + "damage": 33 + }, + { + "id": "minecraft:lingering_potion", + "damage": 34 + }, + { + "id": "minecraft:lingering_potion", + "damage": 35 + }, + { + "id": "minecraft:lingering_potion", + "damage": 36 + }, + { + "id": "minecraft:lingering_potion", + "damage": 37 + }, + { + "id": "minecraft:lingering_potion", + "damage": 38 + }, + { + "id": "minecraft:lingering_potion", + "damage": 39 + }, + { + "id": "minecraft:lingering_potion", + "damage": 40 + }, + { + "id": "minecraft:lingering_potion", + "damage": 41 + }, + { + "id": "minecraft:lingering_potion", + "damage": 42 + }, + { + "id": "minecraft:spyglass" + }, + { + "id": "minecraft:brush" + }, + { + "id": "minecraft:stick" + }, + { + "id": "minecraft:bed" + }, + { + "id": "minecraft:bed", + "damage": 8 + }, + { + "id": "minecraft:bed", + "damage": 7 + }, + { + "id": "minecraft:bed", + "damage": 15 + }, + { + "id": "minecraft:bed", + "damage": 12 + }, + { + "id": "minecraft:bed", + "damage": 14 + }, + { + "id": "minecraft:bed", + "damage": 1 + }, + { + "id": "minecraft:bed", + "damage": 4 + }, + { + "id": "minecraft:bed", + "damage": 5 + }, + { + "id": "minecraft:bed", + "damage": 13 + }, + { + "id": "minecraft:bed", + "damage": 9 + }, + { + "id": "minecraft:bed", + "damage": 3 + }, + { + "id": "minecraft:bed", + "damage": 11 + }, + { + "id": "minecraft:bed", + "damage": 10 + }, + { + "id": "minecraft:bed", + "damage": 2 + }, + { + "id": "minecraft:bed", + "damage": 6 + }, + { + "id": "minecraft:torch", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQyAAAACAQAbmFtZQ8AbWluZWNyYWZ0OnRvcmNoBAkAbmFtZV9oYXNoagn7rmDBzisDCgBuZXR3b3JrX2lk+BwwuQoGAHN0YXRlcwgWAHRvcmNoX2ZhY2luZ19kaXJlY3Rpb24HAHVua25vd24AAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:soul_torch", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQLAgAACAQAbmFtZRQAbWluZWNyYWZ0OnNvdWxfdG9yY2gECQBuYW1lX2hhc2huixOT04BRdQMKAG5ldHdvcmtfaWShbFILCgYAc3RhdGVzCBYAdG9yY2hfZmFjaW5nX2RpcmVjdGlvbgcAdW5rbm93bgADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:sea_pickle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAQAACAQAbmFtZRQAbWluZWNyYWZ0OnNlYV9waWNrbGUECQBuYW1lX2hhc2iONEfZJB+glgMKAG5ldHdvcmtfaWSINWQyCgYAc3RhdGVzAw0AY2x1c3Rlcl9jb3VudAAAAAABCABkZWFkX2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:lantern", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTPAQAACAQAbmFtZREAbWluZWNyYWZ0OmxhbnRlcm4ECQBuYW1lX2hhc2hMw44VI2HWygMKAG5ldHdvcmtfaWRkjQvzCgYAc3RhdGVzAQcAaGFuZ2luZwAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:soul_lantern", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQMAgAACAQAbmFtZRYAbWluZWNyYWZ0OnNvdWxfbGFudGVybgQJAG5hbWVfaGFzaGjIpjxk9z+RAwoAbmV0d29ya19pZGfoP8cKBgBzdGF0ZXMBBwBoYW5naW5nAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAgAACAQAbmFtZRAAbWluZWNyYWZ0OmNhbmRsZQQJAG5hbWVfaGFzaHPd+MsNdWTfAwoAbmV0d29ya19pZHsBMA0KBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:white_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWScAgAACAQAbmFtZRYAbWluZWNyYWZ0OndoaXRlX2NhbmRsZQQJAG5hbWVfaGFzaN1EG5Q1mHiEAwoAbmV0d29ya19pZKN1mmgKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:orange_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSdAgAACAQAbmFtZRcAbWluZWNyYWZ0Om9yYW5nZV9jYW5kbGUECQBuYW1lX2hhc2jySEVWHgUIHQMKAG5ldHdvcmtfaWSfVz82CgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:magenta_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSeAgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hZ2VudGFfY2FuZGxlBAkAbmFtZV9oYXNoG0u6YIOoBSEDCgBuZXR3b3JrX2lk9xGNkQoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:light_blue_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSfAgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY2FuZGxlBAkAbmFtZV9oYXNocXGeK0zgrG0DCgBuZXR3b3JrX2lk2m1y8goGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:yellow_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSgAgAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19jYW5kbGUECQBuYW1lX2hhc2i00dtusU3CqQMKAG5ldHdvcmtfaWR9LTmpCgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:lime_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAgAACAQAbmFtZRUAbWluZWNyYWZ0OmxpbWVfY2FuZGxlBAkAbmFtZV9oYXNokcmrw5xvz7ADCgBuZXR3b3JrX2lkIAUu6QoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:pink_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSiAgAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfY2FuZGxlBAkAbmFtZV9oYXNoQJdEY4sZ0dwDCgBuZXR3b3JrX2lk23Rn5AoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:gray_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSjAgAACAQAbmFtZRUAbWluZWNyYWZ0OmdyYXlfY2FuZGxlBAkAbmFtZV9oYXNoS5poSo9wBDEDCgBuZXR3b3JrX2lk3trRCAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:light_gray_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSkAgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY2FuZGxlBAkAbmFtZV9oYXNo9ruTZLBNMasDCgBuZXR3b3JrX2lkb6DOegoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:cyan_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAgAACAQAbmFtZRUAbWluZWNyYWZ0OmN5YW5fY2FuZGxlBAkAbmFtZV9oYXNoc/M8PNVcjOwDCgBuZXR3b3JrX2lkZoIQOQoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:purple_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSmAgAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnBsZV9jYW5kbGUECQBuYW1lX2hhc2jaI3xUW0/myQMKAG5ldHdvcmtfaWSnLI2BCgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:blue_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSnAgAACAQAbmFtZRUAbWluZWNyYWZ0OmJsdWVfY2FuZGxlBAkAbmFtZV9oYXNoAASSPW6TgQADCgBuZXR3b3JrX2lkrxrjQAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:brown_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAgAACAQAbmFtZRYAbWluZWNyYWZ0OmJyb3duX2NhbmRsZQQJAG5hbWVfaGFzaDia0l6s1+WYAwoAbmV0d29ya19pZKSkBXYKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:green_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSpAgAACAQAbmFtZRYAbWluZWNyYWZ0OmdyZWVuX2NhbmRsZQQJAG5hbWVfaGFzaLeFPO1l+fIoAwoAbmV0d29ya19pZBkznDsKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:red_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSqAgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9jYW5kbGUECQBuYW1lX2hhc2jjAQpGf59ZdwMKAG5ldHdvcmtfaWRbb88GCgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:black_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSrAgAACAQAbmFtZRYAbWluZWNyYWZ0OmJsYWNrX2NhbmRsZQQJAG5hbWVfaGFzaB+wRDpOqREKAwoAbmV0d29ya19pZNnOnuEKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:crafting_table", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ6AAAACAQAbmFtZRgAbWluZWNyYWZ0OmNyYWZ0aW5nX3RhYmxlBAkAbmFtZV9oYXNoe76VAmjvbpYDCgBuZXR3b3JrX2lkwCxwaAoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:cartography_table", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTHAQAACAQAbmFtZRsAbWluZWNyYWZ0OmNhcnRvZ3JhcGh5X3RhYmxlBAkAbmFtZV9oYXNomaWiiD/znP8DCgBuZXR3b3JrX2lkI6FzMwoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:fletching_table", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTIAQAACAQAbmFtZRkAbWluZWNyYWZ0OmZsZXRjaGluZ190YWJsZQQJAG5hbWVfaGFzaPFibh8unKyUAwoAbmV0d29ya19pZJ2mW0oKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:smithing_table", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAQAACAQAbmFtZRgAbWluZWNyYWZ0OnNtaXRoaW5nX3RhYmxlBAkAbmFtZV9oYXNo4tFES2xOXEYDCgBuZXR3b3JrX2lkXWMBzQoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:beehive", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTaAQAACAQAbmFtZREAbWluZWNyYWZ0OmJlZWhpdmUECQBuYW1lX2hhc2hCcqn12UbNpwMKAG5ldHdvcmtfaWR/idcaCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAMLAGhvbmV5X2xldmVsAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:suspicious_sand", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQQAwAACAQAbmFtZRkAbWluZWNyYWZ0OnN1c3BpY2lvdXNfc2FuZAQJAG5hbWVfaGFzaL67QsuvLP00AwoAbmV0d29ya19pZKnkaIAKBgBzdGF0ZXMDEABicnVzaGVkX3Byb2dyZXNzAAAAAAEHAGhhbmdpbmcBAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:suspicious_gravel", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ8AwAACAQAbmFtZRsAbWluZWNyYWZ0OnN1c3BpY2lvdXNfZ3JhdmVsBAkAbmFtZV9oYXNoJSVbGNk7C3oDCgBuZXR3b3JrX2lkvIEJAAoGAHN0YXRlcwMQAGJydXNoZWRfcHJvZ3Jlc3MAAAAAAQcAaGFuZ2luZwEAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:campfire" + }, + { + "id": "minecraft:soul_campfire" + }, + { + "id": "minecraft:furnace", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ9AAAACAQAbmFtZREAbWluZWNyYWZ0OmZ1cm5hY2UECQBuYW1lX2hhc2ioOQrludYY8wMKAG5ldHdvcmtfaWRZxnDOCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:blast_furnace", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTDAQAACAQAbmFtZRcAbWluZWNyYWZ0OmJsYXN0X2Z1cm5hY2UECQBuYW1lX2hhc2ivDbnjkpGm5QMKAG5ldHdvcmtfaWTcEbV/CgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:smoker", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTFAQAACAQAbmFtZRAAbWluZWNyYWZ0OnNtb2tlcgQJAG5hbWVfaGFzaJd1rDMkRWomAwoAbmV0d29ya19pZGWswMwKBgBzdGF0ZXMIHABtaW5lY3JhZnQ6Y2FyZGluYWxfZGlyZWN0aW9uBQBzb3V0aAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:respawn_anchor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQPAgAACAQAbmFtZRgAbWluZWNyYWZ0OnJlc3Bhd25fYW5jaG9yBAkAbmFtZV9oYXNoZOdcjW05qigDCgBuZXR3b3JrX2lkmhMcaQoGAHN0YXRlcwMVAHJlc3Bhd25fYW5jaG9yX2NoYXJnZQAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:brewing_stand" + }, + { + "id": "minecraft:anvil", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSRAAAACAQAbmFtZQ8AbWluZWNyYWZ0OmFudmlsBAkAbmFtZV9oYXNoNqB3fgcUCbwDCgBuZXR3b3JrX2lk8Z3VowoGAHN0YXRlcwgGAGRhbWFnZQkAdW5kYW1hZ2VkCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:anvil", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSRAAAACAQAbmFtZQ8AbWluZWNyYWZ0OmFudmlsBAkAbmFtZV9oYXNoNqB3fgcUCbwDCgBuZXR3b3JrX2lkpiv8BAoGAHN0YXRlcwgGAGRhbWFnZRAAc2xpZ2h0bHlfZGFtYWdlZAgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:anvil", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSRAAAACAQAbmFtZQ8AbWluZWNyYWZ0OmFudmlsBAkAbmFtZV9oYXNoNqB3fgcUCbwDCgBuZXR3b3JrX2lkFu+pdwoGAHN0YXRlcwgGAGRhbWFnZQwAdmVyeV9kYW1hZ2VkCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:grindstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTCAQAACAQAbmFtZRQAbWluZWNyYWZ0OmdyaW5kc3RvbmUECQBuYW1lX2hhc2id56zc0nk99wMKAG5ldHdvcmtfaWS4Es07CgYAc3RhdGVzCAoAYXR0YWNobWVudAgAc3RhbmRpbmcDCQBkaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:enchanting_table", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR0AAAACAQAbmFtZRoAbWluZWNyYWZ0OmVuY2hhbnRpbmdfdGFibGUECQBuYW1lX2hhc2jgIx24VLvMvwMKAG5ldHdvcmtfaWRliFFJCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:bookshelf", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQvAAAACAQAbmFtZRMAbWluZWNyYWZ0OmJvb2tzaGVsZgQJAG5hbWVfaGFzaDU04DrgJCS9AwoAbmV0d29ya19pZBcWwIwKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:chiseled_bookshelf", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQNAwAACAQAbmFtZRwAbWluZWNyYWZ0OmNoaXNlbGVkX2Jvb2tzaGVsZgQJAG5hbWVfaGFzaNXDBnsIsywYAwoAbmV0d29ya19pZIprt5IKBgBzdGF0ZXMDDABib29rc19zdG9yZWQAAAAAAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:lectern", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTBAQAACAQAbmFtZREAbWluZWNyYWZ0OmxlY3Rlcm4ECQBuYW1lX2hhc2j5Z4Mmi/1QxAMKAG5ldHdvcmtfaWR4JfDHCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgBCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:cauldron" + }, + { + "id": "minecraft:composter", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTUAQAACAQAbmFtZRMAbWluZWNyYWZ0OmNvbXBvc3RlcgQJAG5hbWVfaGFzaPAADHptzeWJAwoAbmV0d29ya19pZHIL6i4KBgBzdGF0ZXMDFABjb21wb3N0ZXJfZmlsbF9sZXZlbAAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:chest", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ2AAAACAQAbmFtZQ8AbWluZWNyYWZ0OmNoZXN0BAkAbmFtZV9oYXNog9ozMxlcA88DCgBuZXR3b3JrX2lkDkOFvAoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAG5vcnRoAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:trapped_chest", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSSAAAACAQAbmFtZRcAbWluZWNyYWZ0OnRyYXBwZWRfY2hlc3QECQBuYW1lX2hhc2g2qpF9stsEjgMKAG5ldHdvcmtfaWTjJWYxCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAbm9ydGgAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:ender_chest", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSCAAAACAQAbmFtZRUAbWluZWNyYWZ0OmVuZGVyX2NoZXN0BAkAbmFtZV9oYXNohEZzOFdg0WUDCgBuZXR3b3JrX2lkx4jiSQoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAG5vcnRoAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:barrel", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTKAQAACAQAbmFtZRAAbWluZWNyYWZ0OmJhcnJlbAQJAG5hbWVfaGFzaHDkRPGymiRqAwoAbmV0d29ya19pZPnxzgsKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:undyed_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTNAAAACAQAbmFtZRwAbWluZWNyYWZ0OnVuZHllZF9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaOC9mypm/MlBAwoAbmV0d29ya19pZJ8rxp0KBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:white_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTaAAAACAQAbmFtZRsAbWluZWNyYWZ0OndoaXRlX3NodWxrZXJfYm94BAkAbmFtZV9oYXNosK79m1rPUBwDCgBuZXR3b3JrX2lkjrET6goGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:light_gray_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRrAwAACAQAbmFtZSAAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2iBe5zq7PxHmgMKAG5ldHdvcmtfaWSCVJv0CgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:gray_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRqAwAACAQAbmFtZRoAbWluZWNyYWZ0OmdyYXlfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2ga2s8ctjHUhgMKAG5ldHdvcmtfaWS3WMsWCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:black_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRyAwAACAQAbmFtZRsAbWluZWNyYWZ0OmJsYWNrX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoPm03OZphrp8DCgBuZXR3b3JrX2lkXHztNAoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:brown_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRvAwAACAQAbmFtZRsAbWluZWNyYWZ0OmJyb3duX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoT3DD6qAL9cADCgBuZXR3b3JrX2lkaXxpYQoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:red_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRxAwAACAQAbmFtZRkAbWluZWNyYWZ0OnJlZF9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaMIlKSCzqSZoAwoAbmV0d29ya19pZNrf+icKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:orange_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRkAwAACAQAbmFtZRwAbWluZWNyYWZ0Om9yYW5nZV9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaG2MAXU67wGrAwoAbmV0d29ya19pZGoO05gKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:yellow_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRnAwAACAQAbmFtZRwAbWluZWNyYWZ0OnllbGxvd19zaHVsa2VyX2JveAQJAG5hbWVfaGFzaIsLwQHYjcIEAwoAbmV0d29ya19pZBCBSiYKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:lime_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRoAwAACAQAbmFtZRoAbWluZWNyYWZ0OmxpbWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2hUwBkg+faUGAMKAG5ldHdvcmtfaWRJeKqqCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:green_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRwAwAACAQAbmFtZRsAbWluZWNyYWZ0OmdyZWVuX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoZgUeT3LupLUDCgBuZXR3b3JrX2lkzJiohQoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:cyan_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRsAwAACAQAbmFtZRoAbWluZWNyYWZ0OmN5YW5fc2h1bGtlcl9ib3gECQBuYW1lX2hhc2gSfbjteXg5yAMKAG5ldHdvcmtfaWTHeliECgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:light_blue_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRmAwAACAQAbmFtZSAAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2h0VFCX0qsRxQMKAG5ldHdvcmtfaWQXD8U0CgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:blue_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRuAwAACAQAbmFtZRoAbWluZWNyYWZ0OmJsdWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2hn9gS0XIe6rAMKAG5ldHdvcmtfaWTO4PJaCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:purple_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRtAwAACAQAbmFtZRwAbWluZWNyYWZ0OnB1cnBsZV9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaEV/lkNPxRDdAwoAbmV0d29ya19pZFK25GAKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:magenta_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRlAwAACAQAbmFtZR0AbWluZWNyYWZ0Om1hZ2VudGFfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2iqWM7IJHxcFgMKAG5ldHdvcmtfaWTyyudTCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:pink_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRpAwAACAQAbmFtZRoAbWluZWNyYWZ0OnBpbmtfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2in1tkJ1GNcZgMKAG5ldHdvcmtfaWQOEGXjCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:armor_stand" + }, + { + "id": "minecraft:noteblock", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQZAAAACAQAbmFtZRMAbWluZWNyYWZ0Om5vdGVibG9jawQJAG5hbWVfaGFzaHPA8dBBH0UaAwoAbmV0d29ya19pZH1U5QkKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:jukebox", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRUAAAACAQAbmFtZREAbWluZWNyYWZ0Omp1a2Vib3gECQBuYW1lX2hhc2ieAIPExf/ZfgMKAG5ldHdvcmtfaWSmR7JfCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:music_disc_13" + }, + { + "id": "minecraft:music_disc_cat" + }, + { + "id": "minecraft:music_disc_blocks" + }, + { + "id": "minecraft:music_disc_chirp" + }, + { + "id": "minecraft:music_disc_far" + }, + { + "id": "minecraft:music_disc_mall" + }, + { + "id": "minecraft:music_disc_mellohi" + }, + { + "id": "minecraft:music_disc_stal" + }, + { + "id": "minecraft:music_disc_strad" + }, + { + "id": "minecraft:music_disc_ward" + }, + { + "id": "minecraft:music_disc_11" + }, + { + "id": "minecraft:music_disc_wait" + }, + { + "id": "minecraft:music_disc_otherside" + }, + { + "id": "minecraft:music_disc_5" + }, + { + "id": "minecraft:music_disc_pigstep" + }, + { + "id": "minecraft:music_disc_relic" + }, + { + "id": "minecraft:disc_fragment_5" + }, + { + "id": "minecraft:glowstone_dust" + }, + { + "id": "minecraft:glowstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRZAAAACAQAbmFtZRMAbWluZWNyYWZ0Omdsb3dzdG9uZQQJAG5hbWVfaGFzaFYqXNkefIlPAwoAbmV0d29ya19pZGT7WYYKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:redstone_lamp", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR7AAAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZHN0b25lX2xhbXAECQBuYW1lX2hhc2hJ9V80caPvEgMKAG5ldHdvcmtfaWRvNPwnCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:sea_lantern", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSpAAAACAQAbmFtZRUAbWluZWNyYWZ0OnNlYV9sYW50ZXJuBAkAbmFtZV9oYXNoLPsv1TX9M+QDCgBuZXR3b3JrX2lk1PPVyAoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:oak_sign" + }, + { + "id": "minecraft:spruce_sign" + }, + { + "id": "minecraft:birch_sign" + }, + { + "id": "minecraft:jungle_sign" + }, + { + "id": "minecraft:acacia_sign" + }, + { + "id": "minecraft:dark_oak_sign" + }, + { + "id": "minecraft:mangrove_sign" + }, + { + "id": "minecraft:cherry_sign" + }, + { + "id": "minecraft:bamboo_sign" + }, + { + "id": "minecraft:crimson_sign" + }, + { + "id": "minecraft:warped_sign" + }, + { + "id": "minecraft:oak_hanging_sign" + }, + { + "id": "minecraft:spruce_hanging_sign" + }, + { + "id": "minecraft:birch_hanging_sign" + }, + { + "id": "minecraft:jungle_hanging_sign" + }, + { + "id": "minecraft:acacia_hanging_sign" + }, + { + "id": "minecraft:dark_oak_hanging_sign" + }, + { + "id": "minecraft:mangrove_hanging_sign" + }, + { + "id": "minecraft:cherry_hanging_sign" + }, + { + "id": "minecraft:bamboo_hanging_sign" + }, + { + "id": "minecraft:crimson_hanging_sign" + }, + { + "id": "minecraft:warped_hanging_sign" + }, + { + "id": "minecraft:painting" + }, + { + "id": "minecraft:frame" + }, + { + "id": "minecraft:glow_frame" + }, + { + "id": "minecraft:honey_bottle" + }, + { + "id": "minecraft:flower_pot" + }, + { + "id": "minecraft:bowl" + }, + { + "id": "minecraft:bucket" + }, + { + "id": "minecraft:milk_bucket" + }, + { + "id": "minecraft:water_bucket" + }, + { + "id": "minecraft:lava_bucket" + }, + { + "id": "minecraft:cod_bucket" + }, + { + "id": "minecraft:salmon_bucket" + }, + { + "id": "minecraft:tropical_fish_bucket" + }, + { + "id": "minecraft:pufferfish_bucket" + }, + { + "id": "minecraft:powder_snow_bucket" + }, + { + "id": "minecraft:axolotl_bucket" + }, + { + "id": "minecraft:tadpole_bucket" + }, + { + "id": "minecraft:skull", + "damage": 3 + }, + { + "id": "minecraft:skull", + "damage": 2 + }, + { + "id": "minecraft:skull", + "damage": 4 + }, + { + "id": "minecraft:skull", + "damage": 5 + }, + { + "id": "minecraft:skull" + }, + { + "id": "minecraft:skull", + "damage": 1 + }, + { + "id": "minecraft:skull", + "damage": 6 + }, + { + "id": "minecraft:beacon", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSKAAAACAQAbmFtZRAAbWluZWNyYWZ0OmJlYWNvbgQJAG5hbWVfaGFzaACwhhfSkdkHAwoAbmV0d29ya19pZF8jfiEKBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:bell", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTNAQAACAQAbmFtZQ4AbWluZWNyYWZ0OmJlbGwECQBuYW1lX2hhc2iPqsgDXRcsxAMKAG5ldHdvcmtfaWT7zhOoCgYAc3RhdGVzCAoAYXR0YWNobWVudAgAc3RhbmRpbmcDCQBkaXJlY3Rpb24AAAAAAQoAdG9nZ2xlX2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:conduit", + "block_state_b64": "CgAAAwgAYmxvY2tfaWScAQAACAQAbmFtZREAbWluZWNyYWZ0OmNvbmR1aXQECQBuYW1lX2hhc2jqxKAxq2EaWQMKAG5ldHdvcmtfaWTWcBVnCgYAc3RhdGVzAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:stonecutter_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTEAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lY3V0dGVyX2Jsb2NrBAkAbmFtZV9oYXNoQAXTbAM3MeYDCgBuZXR3b3JrX2lkWS4RjAoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAG5vcnRoAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:coal" + }, + { + "id": "minecraft:charcoal" + }, + { + "id": "minecraft:diamond" + }, + { + "id": "minecraft:iron_nugget" + }, + { + "id": "minecraft:raw_iron" + }, + { + "id": "minecraft:raw_gold" + }, + { + "id": "minecraft:raw_copper" + }, + { + "id": "minecraft:copper_ingot" + }, + { + "id": "minecraft:iron_ingot" + }, + { + "id": "minecraft:netherite_scrap" + }, + { + "id": "minecraft:netherite_ingot" + }, + { + "id": "minecraft:gold_nugget" + }, + { + "id": "minecraft:gold_ingot" + }, + { + "id": "minecraft:emerald" + }, + { + "id": "minecraft:quartz" + }, + { + "id": "minecraft:clay_ball" + }, + { + "id": "minecraft:brick" + }, + { + "id": "minecraft:netherbrick" + }, + { + "id": "minecraft:prismarine_shard" + }, + { + "id": "minecraft:amethyst_shard" + }, + { + "id": "minecraft:prismarine_crystals" + }, + { + "id": "minecraft:nautilus_shell" + }, + { + "id": "minecraft:heart_of_the_sea" + }, + { + "id": "minecraft:turtle_scute" + }, + { + "id": "minecraft:armadillo_scute" + }, + { + "id": "minecraft:phantom_membrane" + }, + { + "id": "minecraft:string" + }, + { + "id": "minecraft:feather" + }, + { + "id": "minecraft:flint" + }, + { + "id": "minecraft:gunpowder" + }, + { + "id": "minecraft:leather" + }, + { + "id": "minecraft:rabbit_hide" + }, + { + "id": "minecraft:rabbit_foot" + }, + { + "id": "minecraft:fire_charge" + }, + { + "id": "minecraft:blaze_rod" + }, + { + "id": "minecraft:blaze_powder" + }, + { + "id": "minecraft:magma_cream" + }, + { + "id": "minecraft:fermented_spider_eye" + }, + { + "id": "minecraft:echo_shard" + }, + { + "id": "minecraft:dragon_breath" + }, + { + "id": "minecraft:shulker_shell" + }, + { + "id": "minecraft:ghast_tear" + }, + { + "id": "minecraft:slime_ball" + }, + { + "id": "minecraft:ender_pearl" + }, + { + "id": "minecraft:ender_eye" + }, + { + "id": "minecraft:nether_star" + }, + { + "id": "minecraft:end_rod", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTQAAAACAQAbmFtZREAbWluZWNyYWZ0OmVuZF9yb2QECQBuYW1lX2hhc2jx/q5cEA0hmQMKAG5ldHdvcmtfaWQ2eM8kCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:lightning_rod", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ3AgAACAQAbmFtZRcAbWluZWNyYWZ0OmxpZ2h0bmluZ19yb2QECQBuYW1lX2hhc2ioXQF1xvfHNQMKAG5ldHdvcmtfaWRLuHyACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:end_crystal" + }, + { + "id": "minecraft:paper" + }, + { + "id": "minecraft:book" + }, + { + "id": "minecraft:writable_book" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQFAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQFAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQFAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQGAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQGAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQGAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQHAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQHAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQHAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQIAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAUAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAUAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAUAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQMAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQMAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQNAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQNAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQOAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQOAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQOAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAUAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQQAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQRAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQRAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQRAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQSAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQSAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQSAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAUAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQUAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQUAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQVAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQWAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQXAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQXAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQXAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQYAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQYAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQYAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQZAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQZAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQaAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQbAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQcAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAUAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQeAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQeAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQeAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQfAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQfAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQfAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQgAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQhAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQjAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQjAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQjAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQkAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQkAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQkAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQlAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQlAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQlAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:oak_boat" + }, + { + "id": "minecraft:spruce_boat" + }, + { + "id": "minecraft:birch_boat" + }, + { + "id": "minecraft:jungle_boat" + }, + { + "id": "minecraft:acacia_boat" + }, + { + "id": "minecraft:dark_oak_boat" + }, + { + "id": "minecraft:mangrove_boat" + }, + { + "id": "minecraft:cherry_boat" + }, + { + "id": "minecraft:bamboo_raft" + }, + { + "id": "minecraft:oak_chest_boat" + }, + { + "id": "minecraft:spruce_chest_boat" + }, + { + "id": "minecraft:birch_chest_boat" + }, + { + "id": "minecraft:jungle_chest_boat" + }, + { + "id": "minecraft:acacia_chest_boat" + }, + { + "id": "minecraft:dark_oak_chest_boat" + }, + { + "id": "minecraft:mangrove_chest_boat" + }, + { + "id": "minecraft:cherry_chest_boat" + }, + { + "id": "minecraft:bamboo_chest_raft" + }, + { + "id": "minecraft:rail", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRCAAAACAQAbmFtZQ4AbWluZWNyYWZ0OnJhaWwECQBuYW1lX2hhc2hUzmhUXYJDUQMKAG5ldHdvcmtfaWR+Sp6YCgYAc3RhdGVzAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:golden_rail", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQbAAAACAQAbmFtZRUAbWluZWNyYWZ0OmdvbGRlbl9yYWlsBAkAbmFtZV9oYXNoOoV5MaKipoUDCgBuZXR3b3JrX2lkfAcxLwoGAHN0YXRlcwENAHJhaWxfZGF0YV9iaXQAAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:detector_rail", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQcAAAACAQAbmFtZRcAbWluZWNyYWZ0OmRldGVjdG9yX3JhaWwECQBuYW1lX2hhc2gVUk31qOysUQMKAG5ldHdvcmtfaWRVW/aICgYAc3RhdGVzAQ0AcmFpbF9kYXRhX2JpdAADDgByYWlsX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:activator_rail", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR+AAAACAQAbmFtZRgAbWluZWNyYWZ0OmFjdGl2YXRvcl9yYWlsBAkAbmFtZV9oYXNosIL91qriCRkDCgBuZXR3b3JrX2lkZfckmwoGAHN0YXRlcwENAHJhaWxfZGF0YV9iaXQAAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:minecart" + }, + { + "id": "minecraft:chest_minecart" + }, + { + "id": "minecraft:hopper_minecart" + }, + { + "id": "minecraft:tnt_minecart" + }, + { + "id": "minecraft:redstone" + }, + { + "id": "minecraft:redstone_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSYAAAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZHN0b25lX2Jsb2NrBAkAbmFtZV9oYXNoRhULL0r8o0sDCgBuZXR3b3JrX2lklayOHgoGAHN0YXRlcwADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:redstone_torch", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRMAAAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZHN0b25lX3RvcmNoBAkAbmFtZV9oYXNoizFRjpYMIDgDCgBuZXR3b3JrX2lkuHz7yAoGAHN0YXRlcwgWAHRvcmNoX2ZhY2luZ19kaXJlY3Rpb24HAHVua25vd24AAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:lever", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRFAAAACAQAbmFtZQ8AbWluZWNyYWZ0OmxldmVyBAkAbmFtZV9oYXNoGMJeLJsUMLYDCgBuZXR3b3JrX2lkEF/GuAoGAHN0YXRlcwgPAGxldmVyX2RpcmVjdGlvbg4AZG93bl9lYXN0X3dlc3QBCABvcGVuX2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:wooden_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSPAAAACAQAbmFtZRcAbWluZWNyYWZ0Ondvb2Rlbl9idXR0b24ECQBuYW1lX2hhc2hR7PgSTQt0sQMKAG5ldHdvcmtfaWSU07kYCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:spruce_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSPAQAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9idXR0b24ECQBuYW1lX2hhc2jBW9Z8aYE7YQMKAG5ldHdvcmtfaWTkUIGuCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:birch_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSMAQAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX2J1dHRvbgQJAG5hbWVfaGFzaJXYgGuSHbTwAwoAbmV0d29ya19pZGWp3yoKBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:jungle_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSOAQAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9idXR0b24ECQBuYW1lX2hhc2iCgNANcJs+BQMKAG5ldHdvcmtfaWT9fImWCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:acacia_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAQAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9idXR0b24ECQBuYW1lX2hhc2gVvmcT7LTO0wMKAG5ldHdvcmtfaWRQnxIJCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:dark_oak_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSNAQAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX2J1dHRvbgQJAG5hbWVfaGFzaIV10ZGGrCIEAwoAbmV0d29ya19pZN5vAmIKBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:mangrove_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTmAgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX2J1dHRvbgQJAG5hbWVfaGFzaNzeYYKLgOzJAwoAbmV0d29ya19pZAFEGQ0KBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:cherry_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQRAwAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9idXR0b24ECQBuYW1lX2hhc2j2/IHjeAbUcwMKAG5ldHdvcmtfaWRJ1irQCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:bamboo_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT+AgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19idXR0b24ECQBuYW1lX2hhc2j7AddMi+6nsgMKAG5ldHdvcmtfaWSa9w4/CgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:stone_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRNAAAACAQAbmFtZRYAbWluZWNyYWZ0OnN0b25lX2J1dHRvbgQJAG5hbWVfaGFzaM4ejMctmvohAwoAbmV0d29ya19pZMw+aC0KBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:crimson_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fYnV0dG9uBAkAbmFtZV9oYXNofnjYHaYIeWgDCgBuZXR3b3JrX2lk+n1vyQoGAHN0YXRlcwESAGJ1dHRvbl9wcmVzc2VkX2JpdAADEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:warped_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQEAgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9idXR0b24ECQBuYW1lX2hhc2jwkV2EU6Cn1QMKAG5ldHdvcmtfaWTnHnk1CgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:polished_blackstone_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQnAgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnV0dG9uBAkAbmFtZV9oYXNojmxzQKS0S/EDCgBuZXR3b3JrX2lkDtQ95woGAHN0YXRlcwESAGJ1dHRvbl9wcmVzc2VkX2JpdAADEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:tripwire_hook", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAAAACAQAbmFtZRcAbWluZWNyYWZ0OnRyaXB3aXJlX2hvb2sECQBuYW1lX2hhc2gQdp+oGZLNnAMKAG5ldHdvcmtfaWSy+1KJCgYAc3RhdGVzAQwAYXR0YWNoZWRfYml0AAMJAGRpcmVjdGlvbgAAAAABCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:wooden_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRIAAAACAQAbmFtZR8AbWluZWNyYWZ0Ondvb2Rlbl9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaGkGs5kCuA74AwoAbmV0d29ya19pZDRzPNwKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:spruce_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSZAQAACAQAbmFtZR8AbWluZWNyYWZ0OnNwcnVjZV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaNmwuq549fJKAwoAbmV0d29ya19pZLQMCw0KBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:birch_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSWAQAACAQAbmFtZR4AbWluZWNyYWZ0OmJpcmNoX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNorQkT9kDdlTwDCgBuZXR3b3JrX2lkH0G97AoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:jungle_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSYAQAACAQAbmFtZR8AbWluZWNyYWZ0Omp1bmdsZV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaJ7DcteCkb8/AwoAbmV0d29ya19pZLdPBSAKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:acacia_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSVAQAACAQAbmFtZR8AbWluZWNyYWZ0OmFjYWNpYV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaC2frZtfoYqCAwoAbmV0d29ya19pZIDdI18KBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:dark_oak_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSXAQAACAQAbmFtZSEAbWluZWNyYWZ0OmRhcmtfb2FrX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoHUCJsTy52pwDCgBuZXR3b3JrX2lkKpi8rAoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:mangrove_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTpAgAACAQAbmFtZSEAbWluZWNyYWZ0Om1hbmdyb3ZlX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoiDsTfJaX100DCgBuZXR3b3JrX2lkuwWDyQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:cherry_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQZAwAACAQAbmFtZR8AbWluZWNyYWZ0OmNoZXJyeV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaALMqYEZDUQHAwoAbmV0d29ya19pZPNT+r0KBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:bamboo_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQBAwAACAQAbmFtZR8AbWluZWNyYWZ0OmJhbWJvb19wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaNvxJ7NIAaqlAwoAbmV0d29ya19pZIZ8XnYKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:crimson_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQFAgAACAQAbmFtZSAAbWluZWNyYWZ0OmNyaW1zb25fcHJlc3N1cmVfcGxhdGUECQBuYW1lX2hhc2hqBDVDAd31/gMKAG5ldHdvcmtfaWRmV18LCgYAc3RhdGVzAw8AcmVkc3RvbmVfc2lnbmFsAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:warped_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAgAACAQAbmFtZR8AbWluZWNyYWZ0OndhcnBlZF9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaBxFoQksWtYUAwoAbmV0d29ya19pZJVRoIcKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:stone_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRGAAAACAQAbmFtZR4AbWluZWNyYWZ0OnN0b25lX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNounJuTBUTrU8DCgBuZXR3b3JrX2lkjDydwQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:light_weighted_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSTAAAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X3dlaWdodGVkX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoOyOJkNxLtkEDCgBuZXR3b3JrX2lkrr2AjgoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:heavy_weighted_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSUAAAACAQAbmFtZScAbWluZWNyYWZ0OmhlYXZ5X3dlaWdodGVkX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoltgDmDvTajUDCgBuZXR3b3JrX2lkFxVKuQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:polished_blackstone_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAgAACAQAbmFtZSwAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfcHJlc3N1cmVfcGxhdGUECQBuYW1lX2hhc2h65Ci6/CeGqwMKAG5ldHdvcmtfaWTaSW5xCgYAc3RhdGVzAw8AcmVkc3RvbmVfc2lnbmFsAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:observer", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT7AAAACAQAbmFtZRIAbWluZWNyYWZ0Om9ic2VydmVyBAkAbmFtZV9oYXNoYhlh1lpmHTgDCgBuZXR3b3JrX2lkQEh55goGAHN0YXRlcwgaAG1pbmVjcmFmdDpmYWNpbmdfZGlyZWN0aW9uBABkb3duAQsAcG93ZXJlZF9iaXQAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:daylight_detector", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSXAAAACAQAbmFtZRsAbWluZWNyYWZ0OmRheWxpZ2h0X2RldGVjdG9yBAkAbmFtZV9oYXNoV0F0s7B7PVgDCgBuZXR3b3JrX2lkri5afQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:repeater" + }, + { + "id": "minecraft:comparator" + }, + { + "id": "minecraft:hopper" + }, + { + "id": "minecraft:dropper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR9AAAACAQAbmFtZREAbWluZWNyYWZ0OmRyb3BwZXIECQBuYW1lX2hhc2joXP7XqU0l3QMKAG5ldHdvcmtfaWQfQN6zCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgMAAAABDQB0cmlnZ2VyZWRfYml0AAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:dispenser", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQXAAAACAQAbmFtZRMAbWluZWNyYWZ0OmRpc3BlbnNlcgQJAG5hbWVfaGFzaP1RR+zAbYP2AwoAbmV0d29ya19pZGAayD0KBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAwAAAAENAHRyaWdnZXJlZF9iaXQAAAMHAHZlcnNpb24DUBQBAA==" + }, + { + "id": "minecraft:piston", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQhAAAACAQAbmFtZRAAbWluZWNyYWZ0OnBpc3RvbgQJAG5hbWVfaGFzaDs3AFh1fL0uAwoAbmV0d29ya19pZLD/5XQKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAQAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:sticky_piston", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQdAAAACAQAbmFtZRcAbWluZWNyYWZ0OnN0aWNreV9waXN0b24ECQBuYW1lX2hhc2hPFJFJSiJ0ZQMKAG5ldHdvcmtfaWT/MzCJCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgEAAAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:tnt", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQuAAAACAQAbmFtZQ0AbWluZWNyYWZ0OnRudAQJAG5hbWVfaGFzaEYOHwCvJH29AwoAbmV0d29ya19pZCGfjU4KBgBzdGF0ZXMBFABhbGxvd191bmRlcndhdGVyX2JpdAABCwBleHBsb2RlX2JpdAAAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:name_tag" + }, + { + "id": "minecraft:loom", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTLAQAACAQAbmFtZQ4AbWluZWNyYWZ0Omxvb20ECQBuYW1lX2hhc2i7DKjAXNq8TAMKAG5ldHdvcmtfaWR/49HXCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:banner", + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 8, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 7, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 15, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 12, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 14, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 1, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 4, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 5, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 13, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 9, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 3, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 11, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 10, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 2, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 6, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 15, + "nbt_b64": "CgAAAwQAVHlwZQEAAAAA" + }, + { + "id": "minecraft:creeper_banner_pattern" + }, + { + "id": "minecraft:skull_banner_pattern" + }, + { + "id": "minecraft:flower_banner_pattern" + }, + { + "id": "minecraft:mojang_banner_pattern" + }, + { + "id": "minecraft:field_masoned_banner_pattern" + }, + { + "id": "minecraft:bordure_indented_banner_pattern" + }, + { + "id": "minecraft:piglin_banner_pattern" + }, + { + "id": "minecraft:globe_banner_pattern" + }, + { + "id": "minecraft:angler_pottery_sherd" + }, + { + "id": "minecraft:archer_pottery_sherd" + }, + { + "id": "minecraft:arms_up_pottery_sherd" + }, + { + "id": "minecraft:blade_pottery_sherd" + }, + { + "id": "minecraft:brewer_pottery_sherd" + }, + { + "id": "minecraft:burn_pottery_sherd" + }, + { + "id": "minecraft:danger_pottery_sherd" + }, + { + "id": "minecraft:explorer_pottery_sherd" + }, + { + "id": "minecraft:friend_pottery_sherd" + }, + { + "id": "minecraft:heart_pottery_sherd" + }, + { + "id": "minecraft:heartbreak_pottery_sherd" + }, + { + "id": "minecraft:howl_pottery_sherd" + }, + { + "id": "minecraft:miner_pottery_sherd" + }, + { + "id": "minecraft:mourner_pottery_sherd" + }, + { + "id": "minecraft:plenty_pottery_sherd" + }, + { + "id": "minecraft:prize_pottery_sherd" + }, + { + "id": "minecraft:sheaf_pottery_sherd" + }, + { + "id": "minecraft:shelter_pottery_sherd" + }, + { + "id": "minecraft:skull_pottery_sherd" + }, + { + "id": "minecraft:snort_pottery_sherd" + }, + { + "id": "minecraft:netherite_upgrade_smithing_template" + }, + { + "id": "minecraft:sentry_armor_trim_smithing_template" + }, + { + "id": "minecraft:vex_armor_trim_smithing_template" + }, + { + "id": "minecraft:wild_armor_trim_smithing_template" + }, + { + "id": "minecraft:coast_armor_trim_smithing_template" + }, + { + "id": "minecraft:dune_armor_trim_smithing_template" + }, + { + "id": "minecraft:wayfinder_armor_trim_smithing_template" + }, + { + "id": "minecraft:shaper_armor_trim_smithing_template" + }, + { + "id": "minecraft:raiser_armor_trim_smithing_template" + }, + { + "id": "minecraft:host_armor_trim_smithing_template" + }, + { + "id": "minecraft:ward_armor_trim_smithing_template" + }, + { + "id": "minecraft:silence_armor_trim_smithing_template" + }, + { + "id": "minecraft:tide_armor_trim_smithing_template" + }, + { + "id": "minecraft:snout_armor_trim_smithing_template" + }, + { + "id": "minecraft:rib_armor_trim_smithing_template" + }, + { + "id": "minecraft:eye_armor_trim_smithing_template" + }, + { + "id": "minecraft:spire_armor_trim_smithing_template" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwAAAAAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAABwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAIBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAHBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAPBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAMBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAOBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAABBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAEBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAFBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAANBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAJBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAADBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAALBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAKBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAACBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAGBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_star", + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yIR0d/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 8, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yUk9H/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 7, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yl52d/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 15, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9y8PDw/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 12, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9y2rM6/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 14, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yHYD5/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 1, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yJi6w/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 4, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yqkQ8/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 5, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yuDKJ/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 13, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yvU7H/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 9, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yqovz/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 3, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yMlSD/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 11, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yPdj+/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 10, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yH8eA/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 2, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yFnxe/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 6, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9ynJwW/wA=" + }, + { + "id": "minecraft:chain" + }, + { + "id": "minecraft:target", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTuAQAACAQAbmFtZRAAbWluZWNyYWZ0OnRhcmdldAQJAG5hbWVfaGFzaJc66SVbYlaxAwoAbmV0d29ya19pZPBozs0KBgBzdGF0ZXMAAwcAdmVyc2lvbgNQFAEA" + }, + { + "id": "minecraft:decorated_pot", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAwAACAQAbmFtZRcAbWluZWNyYWZ0OmRlY29yYXRlZF9wb3QECQBuYW1lX2hhc2jjQgckn8VTvwMKAG5ldHdvcmtfaWRwvkUUCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uA1AUAQA=" + }, + { + "id": "minecraft:lodestone_compass" + }, + { + "id": "minecraft:wither_spawn_egg" + }, + { + "id": "minecraft:ender_dragon_spawn_egg" + } + ] +} \ No newline at end of file diff --git a/core/src/main/resources/bedrock/entity_identifiers.dat b/core/src/main/resources/bedrock/entity_identifiers.dat index 9a986cf5c435ac467cac73c25a0ba160cbfbb0be..9a123f8d8834e6af5c98b000778665b6e2022887 100644 GIT binary patch delta 62 zcmX?S+i%Cq#lXpynUa%PT*CE@ak3+$#N;#F+#3y|$w#lXpynUa%PT*CE*ak3+$#N;#F+#3y| Date: Tue, 23 Apr 2024 12:34:24 -0400 Subject: [PATCH 250/344] Serialize disconnects --- .../main/java/org/geysermc/geyser/network/CodecProcessor.java | 1 - 1 file changed, 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/network/CodecProcessor.java b/core/src/main/java/org/geysermc/geyser/network/CodecProcessor.java index 4ad02a644..0516b1601 100644 --- a/core/src/main/java/org/geysermc/geyser/network/CodecProcessor.java +++ b/core/src/main/java/org/geysermc/geyser/network/CodecProcessor.java @@ -261,7 +261,6 @@ class CodecProcessor { .updateSerializer(ScriptMessagePacket.class, ILLEGAL_SERIALIZER) // // Ignored bidirectional packets .updateSerializer(ClientCacheStatusPacket.class, IGNORED_SERIALIZER) - .updateSerializer(DisconnectPacket.class, IGNORED_SERIALIZER) .updateSerializer(SimpleEventPacket.class, IGNORED_SERIALIZER) .updateSerializer(TickSyncPacket.class, IGNORED_SERIALIZER) .updateSerializer(MultiplayerSettingsPacket.class, IGNORED_SERIALIZER) From 3bd5ab7f35c52d9a76990cedc30151b03b402a82 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Tue, 23 Apr 2024 11:23:09 -0700 Subject: [PATCH 251/344] Use old SetEntityMotionSerializer for codec < 662 (#4593) --- .../geyser/network/CodecProcessor.java | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/network/CodecProcessor.java b/core/src/main/java/org/geysermc/geyser/network/CodecProcessor.java index 0516b1601..6bd767fb7 100644 --- a/core/src/main/java/org/geysermc/geyser/network/CodecProcessor.java +++ b/core/src/main/java/org/geysermc/geyser/network/CodecProcessor.java @@ -33,6 +33,7 @@ import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.MobArmorEquipment import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.MobEquipmentSerializer_v291; import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.PlayerHotbarSerializer_v291; import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.SetEntityLinkSerializer_v291; +import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.SetEntityMotionSerializer_v291; import org.cloudburstmc.protocol.bedrock.codec.v390.serializer.PlayerSkinSerializer_v390; import org.cloudburstmc.protocol.bedrock.codec.v407.serializer.InventoryContentSerializer_v407; import org.cloudburstmc.protocol.bedrock.codec.v407.serializer.InventorySlotSerializer_v407; @@ -50,7 +51,6 @@ import org.cloudburstmc.protocol.bedrock.packet.CodeBuilderSourcePacket; import org.cloudburstmc.protocol.bedrock.packet.CraftingEventPacket; import org.cloudburstmc.protocol.bedrock.packet.CreatePhotoPacket; import org.cloudburstmc.protocol.bedrock.packet.DebugInfoPacket; -import org.cloudburstmc.protocol.bedrock.packet.DisconnectPacket; import org.cloudburstmc.protocol.bedrock.packet.EditorNetworkPacket; import org.cloudburstmc.protocol.bedrock.packet.EntityFallPacket; import org.cloudburstmc.protocol.bedrock.packet.GameTestRequestPacket; @@ -182,9 +182,18 @@ class CodecProcessor { }; /** - * Serializer that does nothing when trying to deserialize SetEntityMotionPacket since it is not used from the client. + * Serializer that does nothing when trying to deserialize SetEntityMotionPacket since it is not used from the client for codec v291. */ - private static final BedrockPacketSerializer SET_ENTITY_MOTION_SERIALIZER = new SetEntityMotionSerializer_v662() { + private static final BedrockPacketSerializer SET_ENTITY_MOTION_SERIALIZER_V291 = new SetEntityMotionSerializer_v291() { + @Override + public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, SetEntityMotionPacket packet) { + } + }; + + /** + * Serializer that does nothing when trying to deserialize SetEntityMotionPacket since it is not used from the client for codec v662. + */ + private static final BedrockPacketSerializer SET_ENTITY_MOTION_SERIALIZER_V662 = new SetEntityMotionSerializer_v662() { @Override public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, SetEntityMotionPacket packet) { } @@ -251,7 +260,9 @@ class CodecProcessor { .updateSerializer(PlayerHotbarPacket.class, PLAYER_HOTBAR_SERIALIZER) .updateSerializer(PlayerSkinPacket.class, PLAYER_SKIN_SERIALIZER) .updateSerializer(SetEntityDataPacket.class, SET_ENTITY_DATA_SERIALIZER) - .updateSerializer(SetEntityMotionPacket.class, SET_ENTITY_MOTION_SERIALIZER) + .updateSerializer(SetEntityMotionPacket.class, codec.getProtocolVersion() < 662 ? + SET_ENTITY_MOTION_SERIALIZER_V291 : + SET_ENTITY_MOTION_SERIALIZER_V662) .updateSerializer(SetEntityLinkPacket.class, SET_ENTITY_LINK_SERIALIZER) // Valid serverbound packets where reading of some fields can be skipped .updateSerializer(MobEquipmentPacket.class, MOB_EQUIPMENT_SERIALIZER) From c34295829f17b16c5d3d3a321a472c5c1d40117b Mon Sep 17 00:00:00 2001 From: chris Date: Tue, 23 Apr 2024 23:14:54 +0200 Subject: [PATCH 252/344] update actions to use java 21 (#4594) * update actions to use java 21 * jdk name correction --- .github/workflows/build-remote.yml | 4 ++-- .github/workflows/build.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-remote.yml b/.github/workflows/build-remote.yml index 75bcfaff5..d49920785 100644 --- a/.github/workflows/build-remote.yml +++ b/.github/workflows/build-remote.yml @@ -22,11 +22,11 @@ jobs: run: | echo "BUILD_NUMBER=${GITHUB_RUN_NUMBER}" >> $GITHUB_ENV - - name: Set up JDK 17 + - name: Set up JDK 21 # See https://github.com/actions/setup-java/commits uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4.0.0 with: - java-version: 17 + java-version: 21 distribution: temurin - name: Checkout repository and submodules diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1ef0118ff..284fa265a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -44,7 +44,7 @@ jobs: # See https://github.com/actions/setup-java/commits - uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4.0.0 with: - java-version: 17 + java-version: 21 distribution: temurin - name: Build From 16385a4e2b5db5c049fc28af5e032b459cdfc64a Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Wed, 24 Apr 2024 01:39:37 -0400 Subject: [PATCH 253/344] Check if session is closed when running scheduled tasks (#4595) --- .../main/java/org/geysermc/geyser/session/GeyserSession.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index aff21182e..95d5acb47 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -1171,7 +1171,9 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { public ScheduledFuture scheduleInEventLoop(Runnable runnable, long duration, TimeUnit timeUnit) { return eventLoop.schedule(() -> { try { - runnable.run(); + if (!closed) { + runnable.run(); + } } catch (Throwable e) { geyser.getLogger().error("Error thrown in " + this.bedrockUsername() + "'s event loop!", e); } From c19b4ad306b92b146999b374fffe965012ebf55b Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Wed, 24 Apr 2024 08:41:57 -0400 Subject: [PATCH 254/344] Check if boat is valid when updating paddles (#4597) * Check if boat is valid when updating paddles * Add comment * Refactor boat paddling to use ticks * Null check --- .../geyser/entity/type/BoatEntity.java | 58 ++++++------------- .../geyser/session/GeyserSession.java | 2 + 2 files changed, 21 insertions(+), 39 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/BoatEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/BoatEntity.java index 5527e773a..e3420abeb 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/BoatEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/BoatEntity.java @@ -42,7 +42,7 @@ import org.geysermc.geyser.util.InteractiveTag; import java.util.UUID; import java.util.concurrent.TimeUnit; -public class BoatEntity extends Entity { +public class BoatEntity extends Entity implements Tickable { /** * Required when IS_BUOYANT is sent in order for boats to work in the water.
@@ -58,6 +58,7 @@ public class BoatEntity extends Entity { private float paddleTimeLeft; private boolean isPaddlingRight; private float paddleTimeRight; + private boolean doTick; /** * Saved for using the "pick" functionality on a boat. @@ -133,34 +134,16 @@ public class BoatEntity extends Entity { public void setPaddlingLeft(BooleanEntityMetadata entityMetadata) { isPaddlingLeft = entityMetadata.getPrimitiveValue(); - if (isPaddlingLeft) { - // Java sends simply "true" and "false" (is_paddling_left), Bedrock keeps sending packets as you're rowing - // This is an asynchronous method that emulates Bedrock rowing until "false" is sent. - paddleTimeLeft = 0f; - if (!this.passengers.isEmpty()) { - // Get the entity by the first stored passenger and convey motion in this manner - Entity entity = this.passengers.get(0); - if (entity != null) { - updateLeftPaddle(session, entity); - } - } - } else { - // Indicate that the row position should be reset + if (!isPaddlingLeft) { + paddleTimeLeft = 0.0f; dirtyMetadata.put(EntityDataTypes.ROW_TIME_LEFT, 0.0f); } } public void setPaddlingRight(BooleanEntityMetadata entityMetadata) { isPaddlingRight = entityMetadata.getPrimitiveValue(); - if (isPaddlingRight) { - paddleTimeRight = 0f; - if (!this.passengers.isEmpty()) { - Entity entity = this.passengers.get(0); - if (entity != null) { - updateRightPaddle(session, entity); - } - } - } else { + if (!isPaddlingRight) { + paddleTimeRight = 0.0f; dirtyMetadata.put(EntityDataTypes.ROW_TIME_RIGHT, 0.0f); } } @@ -186,29 +169,26 @@ public class BoatEntity extends Entity { } } - private void updateLeftPaddle(GeyserSession session, Entity rower) { + @Override + public void tick() { + // Java sends simply "true" and "false" (is_paddling_left), Bedrock keeps sending packets as you're rowing + doTick = !doTick; // Run every 100 ms + if (!doTick || passengers.isEmpty()) { + return; + } + + Entity rower = passengers.get(0); + if (rower == null) { + return; + } + if (isPaddlingLeft) { paddleTimeLeft += ROWING_SPEED; sendAnimationPacket(session, rower, AnimatePacket.Action.ROW_LEFT, paddleTimeLeft); - - session.scheduleInEventLoop(() -> - updateLeftPaddle(session, rower), - 100, - TimeUnit.MILLISECONDS - ); } - } - - private void updateRightPaddle(GeyserSession session, Entity rower) { if (isPaddlingRight) { paddleTimeRight += ROWING_SPEED; sendAnimationPacket(session, rower, AnimatePacket.Action.ROW_RIGHT, paddleTimeRight); - - session.scheduleInEventLoop(() -> - updateRightPaddle(session, rower), - 100, - TimeUnit.MILLISECONDS - ); } } diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 95d5acb47..63022636c 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -1167,6 +1167,8 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { /** * Schedules a task and prints a stack trace if an error occurs. + *

+ * The task will not run if the session is closed. */ public ScheduledFuture scheduleInEventLoop(Runnable runnable, long duration, TimeUnit timeUnit) { return eventLoop.schedule(() -> { From 2471de100be3f229bfa415ec887e48a29002d2b2 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Wed, 24 Apr 2024 06:56:15 -0700 Subject: [PATCH 255/344] Add system property Geyser.RakSendCookie to allow disabling cookie send (#4598) --- .../java/org/geysermc/geyser/network/netty/GeyserServer.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java b/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java index 652901f36..a67bd8a32 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java @@ -228,6 +228,9 @@ public final class GeyserServer { int rakGlobalPacketLimit = positivePropOrDefault("Geyser.RakGlobalPacketLimit", DEFAULT_GLOBAL_PACKET_LIMIT); this.geyser.getLogger().debug("Setting RakNet global packet limit to " + rakGlobalPacketLimit); + boolean rakSendCookie = Boolean.parseBoolean(System.getProperty("Geyser.RakSendCookie", "true")); + this.geyser.getLogger().debug("Setting RakNet send cookie to " + rakSendCookie); + return new ServerBootstrap() .channelFactory(RakChannelFactory.server(TRANSPORT.datagramChannel())) .group(group, childGroup) @@ -235,7 +238,7 @@ public final class GeyserServer { .option(RakChannelOption.RAK_MAX_MTU, this.geyser.getConfig().getMtu()) .option(RakChannelOption.RAK_PACKET_LIMIT, rakPacketLimit) .option(RakChannelOption.RAK_GLOBAL_PACKET_LIMIT, rakGlobalPacketLimit) - .option(RakChannelOption.RAK_SEND_COOKIE, true) + .option(RakChannelOption.RAK_SEND_COOKIE, rakSendCookie) .childHandler(serverInitializer); } From 099e968bde8e9981c7467b4f82c87a85cd0bc8e0 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Fri, 19 Apr 2024 19:21:44 -0400 Subject: [PATCH 256/344] Initial, incomplete pass at Java 1.20.5 --- .../geyser/entity/type/FireworkEntity.java | 2 +- .../geyser/entity/type/ItemEntity.java | 4 +- .../geyser/entity/type/ItemFrameEntity.java | 4 +- .../entity/type/ThrowableItemEntity.java | 2 +- .../entity/type/ThrownPotionEntity.java | 2 +- .../geyser/inventory/GeyserItemStack.java | 31 +++--- .../geysermc/geyser/inventory/Inventory.java | 2 +- .../geyser/inventory/click/ClickPlan.java | 2 +- .../inventory/recipe/GeyserShapedRecipe.java | 2 +- .../recipe/GeyserShapelessRecipe.java | 2 +- .../recipe/GeyserStonecutterData.java | 2 +- .../geysermc/geyser/item/type/ArmorItem.java | 6 +- .../geysermc/geyser/item/type/ArrowItem.java | 8 +- .../geyser/item/type/AxolotlBucketItem.java | 7 +- .../geysermc/geyser/item/type/BannerItem.java | 6 +- .../geysermc/geyser/item/type/ChestItem.java | 7 +- .../geyser/item/type/CompassItem.java | 8 +- .../geyser/item/type/CrossbowItem.java | 10 +- .../geyser/item/type/DecoratedPotItem.java | 6 +- .../geyser/item/type/DyeableArmorItem.java | 6 +- .../item/type/DyeableHorseArmorItem.java | 6 +- .../geyser/item/type/EnchantedBookItem.java | 6 +- .../geyser/item/type/FilledMapItem.java | 2 +- .../geyser/item/type/FireworkRocketItem.java | 6 +- .../geyser/item/type/FireworkStarItem.java | 6 +- .../geyser/item/type/FishingRodItem.java | 7 +- .../geyser/item/type/GoatHornItem.java | 2 +- .../org/geysermc/geyser/item/type/Item.java | 63 +++++++----- .../geysermc/geyser/item/type/MapItem.java | 6 +- .../geyser/item/type/PlayerHeadItem.java | 6 +- .../geysermc/geyser/item/type/PotionItem.java | 16 +-- .../geysermc/geyser/item/type/ShieldItem.java | 6 +- .../geyser/item/type/ShulkerBoxItem.java | 71 ++++++------- .../geyser/item/type/TippedArrowItem.java | 4 +- .../item/type/TropicalFishBucketItem.java | 6 +- .../geyser/item/type/WritableBookItem.java | 6 +- .../geyser/item/type/WrittenBookItem.java | 6 +- .../populator/RecipeRegistryPopulator.java | 4 +- .../geyser/registry/type/ItemMappings.java | 2 +- .../inventory/InventoryTranslator.java | 2 +- .../inventory/PlayerInventoryTranslator.java | 4 +- .../StonecutterInventoryTranslator.java | 2 +- .../item/CustomItemTranslator.java | 30 +++--- .../{inventory => }/item/ItemTranslator.java | 99 +++++++++---------- .../BedrockBlockPickRequestTranslator.java | 2 +- .../bedrock/BedrockBookEditTranslator.java | 2 +- ...BedrockInventoryTransactionTranslator.java | 4 +- .../player/BedrockActionTranslator.java | 2 +- .../java/JavaUpdateRecipesTranslator.java | 4 +- .../entity/JavaSetEquipmentTranslator.java | 4 +- .../JavaContainerSetSlotTranslator.java | 4 +- .../JavaMerchantOffersTranslator.java | 4 +- .../level/JavaLevelParticlesTranslator.java | 4 +- .../geysermc/geyser/util/InventoryUtils.java | 2 +- 54 files changed, 285 insertions(+), 234 deletions(-) rename core/src/main/java/org/geysermc/geyser/translator/{inventory => }/item/CustomItemTranslator.java (80%) rename core/src/main/java/org/geysermc/geyser/translator/{inventory => }/item/ItemTranslator.java (88%) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/FireworkEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/FireworkEntity.java index 7a544f23c..171849ce5 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/FireworkEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/FireworkEntity.java @@ -26,7 +26,7 @@ package org.geysermc.geyser.entity.type; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.Tag; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/ItemEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ItemEntity.java index 69fb3faab..226ad7df8 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/ItemEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/ItemEntity.java @@ -26,7 +26,7 @@ package org.geysermc.geyser.entity.type; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType; @@ -37,7 +37,7 @@ import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.translator.inventory.item.ItemTranslator; +import org.geysermc.geyser.translator.item.ItemTranslator; import java.util.UUID; import java.util.concurrent.CompletableFuture; 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 ad1d4b928..453125945 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 @@ -26,7 +26,7 @@ package org.geysermc.geyser.entity.type; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.object.Direction; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; @@ -42,7 +42,7 @@ import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket; import lombok.Getter; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.translator.inventory.item.ItemTranslator; +import org.geysermc.geyser.translator.item.ItemTranslator; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InventoryUtils; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/ThrowableItemEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ThrowableItemEntity.java index 39c8386bd..3c080345e 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/ThrowableItemEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/ThrowableItemEntity.java @@ -26,7 +26,7 @@ package org.geysermc.geyser.entity.type; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/ThrownPotionEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ThrownPotionEntity.java index 1b5c1d2d0..cea371963 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/ThrownPotionEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/ThrownPotionEntity.java @@ -26,7 +26,7 @@ package org.geysermc.geyser.entity.type; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import org.cloudburstmc.math.vector.Vector3f; diff --git a/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java b/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java index 4ff8db9f0..dd1aaea81 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java @@ -25,7 +25,8 @@ package org.geysermc.geyser.inventory; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import lombok.AccessLevel; import lombok.Data; @@ -34,12 +35,13 @@ import lombok.Getter; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; +import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.translator.inventory.item.ItemTranslator; +import org.geysermc.geyser.translator.item.ItemTranslator; @Data public class GeyserItemStack { @@ -47,26 +49,26 @@ public class GeyserItemStack { private final int javaId; private int amount; - private CompoundTag nbt; + private DataComponentPatch components; private int netId; @Getter(AccessLevel.NONE) @EqualsAndHashCode.Exclude private Item item; - private GeyserItemStack(int javaId, int amount, CompoundTag nbt) { - this(javaId, amount, nbt, 1); + private GeyserItemStack(int javaId, int amount, DataComponentPatch components) { + this(javaId, amount, components, 1); } - private GeyserItemStack(int javaId, int amount, CompoundTag nbt, int netId) { + private GeyserItemStack(int javaId, int amount, DataComponentPatch components, int netId) { this.javaId = javaId; this.amount = amount; - this.nbt = nbt; + this.components = components; this.netId = netId; } public static @NonNull GeyserItemStack from(@Nullable ItemStack itemStack) { - return itemStack == null ? EMPTY : new GeyserItemStack(itemStack.getId(), itemStack.getAmount(), itemStack.getNbt()); + return itemStack == null ? EMPTY : new GeyserItemStack(itemStack.getId(), itemStack.getAmount(), itemStack.getDataComponentPatch()); } public int getJavaId() { @@ -78,7 +80,12 @@ public class GeyserItemStack { } public @Nullable CompoundTag getNbt() { - return isEmpty() ? null : nbt; + Thread.dumpStack(); + return null; + } + + public @Nullable DataComponentPatch getComponents() { + return isEmpty() ? null : components; } public int getNetId() { @@ -98,14 +105,14 @@ public class GeyserItemStack { } public @Nullable ItemStack getItemStack(int newAmount) { - return isEmpty() ? null : new ItemStack(javaId, newAmount, nbt); + return isEmpty() ? null : new ItemStack(javaId, newAmount, components); } public ItemData getItemData(GeyserSession session) { if (isEmpty()) { return ItemData.AIR; } - ItemData.Builder itemData = ItemTranslator.translateToBedrock(session, javaId, amount, nbt); + ItemData.Builder itemData = ItemTranslator.translateToBedrock(session, javaId, amount, components); itemData.netId(getNetId()); itemData.usingNetId(true); return itemData.build(); @@ -131,6 +138,6 @@ public class GeyserItemStack { } public GeyserItemStack copy(int newAmount) { - return isEmpty() ? EMPTY : new GeyserItemStack(javaId, newAmount, nbt == null ? null : nbt.clone(), netId); + return isEmpty() ? EMPTY : new GeyserItemStack(javaId, newAmount, components == null ? null : components.clone(), netId); } } diff --git a/core/src/main/java/org/geysermc/geyser/inventory/Inventory.java b/core/src/main/java/org/geysermc/geyser/inventory/Inventory.java index 3376d6c26..b78bbe1b3 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/Inventory.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/Inventory.java @@ -38,7 +38,7 @@ import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.translator.inventory.item.ItemTranslator; +import org.geysermc.geyser.translator.item.ItemTranslator; import org.jetbrains.annotations.Range; import java.util.Arrays; diff --git a/core/src/main/java/org/geysermc/geyser/inventory/click/ClickPlan.java b/core/src/main/java/org/geysermc/geyser/inventory/click/ClickPlan.java index f31f6d82f..a118670af 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/click/ClickPlan.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/click/ClickPlan.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.inventory.click; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.mc.protocol.data.game.inventory.ContainerActionType; import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; import com.github.steveice10.mc.protocol.data.game.inventory.MoveToHotbarAction; diff --git a/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserShapedRecipe.java b/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserShapedRecipe.java index 05c17cf9f..d420170f4 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserShapedRecipe.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserShapedRecipe.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.inventory.recipe; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapedRecipeData; import org.checkerframework.checker.nullness.qual.Nullable; diff --git a/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserShapelessRecipe.java b/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserShapelessRecipe.java index e300e3ec8..e6eabea2d 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserShapelessRecipe.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserShapelessRecipe.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.inventory.recipe; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapelessRecipeData; import org.checkerframework.checker.nullness.qual.Nullable; diff --git a/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserStonecutterData.java b/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserStonecutterData.java index 22163eced..ce044e745 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserStonecutterData.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserStonecutterData.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.inventory.recipe; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import org.checkerframework.checker.nullness.qual.Nullable; /** diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java index b58f760d1..669791705 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java @@ -25,9 +25,11 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.item.ArmorMaterial; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; @@ -41,8 +43,8 @@ public class ArmorItem extends Item { } @Override - public void translateNbtToBedrock(@NonNull GeyserSession session, @NonNull CompoundTag tag) { - super.translateNbtToBedrock(session, tag); + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + super.translateComponentsToBedrock(session, components, builder); if (tag.get("Trim") instanceof CompoundTag trim) { StringTag material = trim.remove("material"); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java index 938d4a79a..2462f374c 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java @@ -25,7 +25,9 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; +import com.github.steveice10.mc.protocol.data.game.item.component.PotionContents; import com.github.steveice10.opennbt.tag.builtin.StringTag; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; @@ -44,9 +46,9 @@ public class ArrowItem extends Item { TippedArrowPotion tippedArrowPotion = TippedArrowPotion.getByBedrockId(itemData.getDamage()); ItemStack itemStack = super.translateToJava(itemData, mapping, mappings); if (tippedArrowPotion != null) { - itemStack = Items.TIPPED_ARROW.newItemStack(itemStack.getAmount(), itemStack.getNbt()); + itemStack = Items.TIPPED_ARROW.newItemStack(itemStack.getAmount(), itemStack.getDataComponentPatch()); StringTag potionTag = new StringTag("Potion", tippedArrowPotion.getJavaIdentifier()); - itemStack.getNbt().put(potionTag); + itemStack.getDataComponentPatch().put(DataComponentType.POTION_CONTENTS, new PotionContents()); } return itemStack; } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/AxolotlBucketItem.java b/core/src/main/java/org/geysermc/geyser/item/type/AxolotlBucketItem.java index 81d7bf116..6e4e6c6fc 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/AxolotlBucketItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/AxolotlBucketItem.java @@ -25,10 +25,11 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; import com.github.steveice10.opennbt.tag.builtin.ByteTag; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.MinecraftLocale; @@ -38,8 +39,8 @@ public class AxolotlBucketItem extends Item { } @Override - public void translateNbtToBedrock(@NonNull GeyserSession session, @NonNull CompoundTag tag) { - super.translateNbtToBedrock(session, tag); + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + super.translateComponentsToBedrock(session, components, builder); // Bedrock Edition displays the properties of the axolotl. Java does not. // To work around this, set the custom name to the Axolotl translation and it's displayed correctly diff --git a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java index 344668836..9cd7aea42 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; @@ -32,6 +33,7 @@ import com.github.steveice10.opennbt.tag.builtin.Tag; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtList; import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; @@ -120,8 +122,8 @@ public class BannerItem extends BlockItem { } @Override - public void translateNbtToBedrock(@NonNull GeyserSession session, @NonNull CompoundTag tag) { - super.translateNbtToBedrock(session, tag); + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + super.translateComponentsToBedrock(session, components, builder); CompoundTag blockEntityTag = tag.remove("BlockEntityTag"); if (blockEntityTag != null && blockEntityTag.get("Patterns") instanceof ListTag patterns) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ChestItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ChestItem.java index 99857006c..2611c8ff6 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ChestItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ChestItem.java @@ -25,8 +25,9 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.session.GeyserSession; public class ChestItem extends BlockItem { @@ -36,8 +37,8 @@ public class ChestItem extends BlockItem { } @Override - public void translateNbtToBedrock(@NonNull GeyserSession session, @NonNull CompoundTag tag) { - super.translateNbtToBedrock(session, tag); + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + super.translateComponentsToBedrock(session, components, builder); // Strip the BlockEntityTag from the chests contents // sent to the client. The client does not parse this diff --git a/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java b/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java index 87da96447..f3933d83b 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java @@ -25,12 +25,14 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; import com.github.steveice10.opennbt.tag.builtin.ByteTag; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; @@ -58,8 +60,8 @@ public class CompassItem extends Item { } @Override - public void translateNbtToBedrock(@NonNull GeyserSession session, @NonNull CompoundTag tag) { - super.translateNbtToBedrock(session, tag); + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + super.translateComponentsToBedrock(session, components, builder); Tag lodestoneTag = tag.get("LodestoneTracked"); if (lodestoneTag instanceof ByteTag) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/CrossbowItem.java b/core/src/main/java/org/geysermc/geyser/item/type/CrossbowItem.java index e409dccfb..1ea468721 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/CrossbowItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/CrossbowItem.java @@ -25,14 +25,16 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; import com.github.steveice10.opennbt.tag.builtin.*; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; +import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.translator.inventory.item.ItemTranslator; +import org.geysermc.geyser.translator.item.ItemTranslator; public class CrossbowItem extends Item { public CrossbowItem(String javaIdentifier, Builder builder) { @@ -40,8 +42,8 @@ public class CrossbowItem extends Item { } @Override - public void translateNbtToBedrock(@NonNull GeyserSession session, @NonNull CompoundTag tag) { - super.translateNbtToBedrock(session, tag); + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + super.translateComponentsToBedrock(session, components, builder); ListTag chargedProjectiles = tag.get("ChargedProjectiles"); if (chargedProjectiles != null) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java b/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java index 10d2a1bcc..bfa86d2ad 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java @@ -25,9 +25,11 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.session.GeyserSession; public class DecoratedPotItem extends BlockItem { @@ -37,8 +39,8 @@ public class DecoratedPotItem extends BlockItem { } @Override - public void translateNbtToBedrock(@NonNull GeyserSession session, @NonNull CompoundTag tag) { - super.translateNbtToBedrock(session, tag); + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + super.translateComponentsToBedrock(session, components, builder); if (tag.remove("BlockEntityTag") instanceof CompoundTag blockEntityTag) { if (blockEntityTag.remove("sherds") instanceof ListTag sherds) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/DyeableArmorItem.java b/core/src/main/java/org/geysermc/geyser/item/type/DyeableArmorItem.java index dbcff7d0b..f1b10474d 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/DyeableArmorItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/DyeableArmorItem.java @@ -25,8 +25,10 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.item.ArmorMaterial; import org.geysermc.geyser.item.DyeableLeatherItem; import org.geysermc.geyser.registry.type.ItemMapping; @@ -38,8 +40,8 @@ public class DyeableArmorItem extends ArmorItem implements DyeableLeatherItem { } @Override - public void translateNbtToBedrock(@NonNull GeyserSession session, @NonNull CompoundTag tag) { - super.translateNbtToBedrock(session, tag); + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + super.translateComponentsToBedrock(session, components, builder); DyeableLeatherItem.translateNbtToBedrock(tag); } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/DyeableHorseArmorItem.java b/core/src/main/java/org/geysermc/geyser/item/type/DyeableHorseArmorItem.java index 0d37f5eab..39787ae2f 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/DyeableHorseArmorItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/DyeableHorseArmorItem.java @@ -25,8 +25,10 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.item.DyeableLeatherItem; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; @@ -37,8 +39,8 @@ public class DyeableHorseArmorItem extends Item implements DyeableLeatherItem { } @Override - public void translateNbtToBedrock(@NonNull GeyserSession session, @NonNull CompoundTag tag) { - super.translateNbtToBedrock(session, tag); + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + super.translateComponentsToBedrock(session, components, builder); DyeableLeatherItem.translateNbtToBedrock(tag); } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java b/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java index ac0751c73..c51278947 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java @@ -25,10 +25,12 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.session.GeyserSession; import java.util.ArrayList; @@ -40,8 +42,8 @@ public class EnchantedBookItem extends Item { } @Override - public void translateNbtToBedrock(@NonNull GeyserSession session, @NonNull CompoundTag tag) { - super.translateNbtToBedrock(session, tag); + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + super.translateComponentsToBedrock(session, components, builder); List newTags = new ArrayList<>(); Tag enchantmentTag = tag.remove("StoredEnchantments"); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/FilledMapItem.java b/core/src/main/java/org/geysermc/geyser/item/type/FilledMapItem.java index 963373523..8125ce101 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/FilledMapItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/FilledMapItem.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import org.cloudburstmc.nbt.NbtMap; diff --git a/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java b/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java index 3559cdf4d..6be1be15d 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java @@ -25,8 +25,10 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; import com.github.steveice10.opennbt.tag.builtin.*; import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.level.FireworkColor; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; @@ -38,8 +40,8 @@ public class FireworkRocketItem extends Item { } @Override - public void translateNbtToBedrock(@NonNull GeyserSession session, @NonNull CompoundTag tag) { - super.translateNbtToBedrock(session, tag); + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + super.translateComponentsToBedrock(session, components, builder); CompoundTag fireworks = tag.get("Fireworks"); if (fireworks == null) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/FireworkStarItem.java b/core/src/main/java/org/geysermc/geyser/item/type/FireworkStarItem.java index 9c13d7793..6d4347e9e 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/FireworkStarItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/FireworkStarItem.java @@ -25,11 +25,13 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.IntArrayTag; import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; @@ -39,8 +41,8 @@ public class FireworkStarItem extends Item { } @Override - public void translateNbtToBedrock(@NonNull GeyserSession session, @NonNull CompoundTag tag) { - super.translateNbtToBedrock(session, tag); + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + super.translateComponentsToBedrock(session, components, builder); Tag explosion = tag.remove("Explosion"); if (explosion instanceof CompoundTag) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/FishingRodItem.java b/core/src/main/java/org/geysermc/geyser/item/type/FishingRodItem.java index f63a1ec5a..50a0bddbc 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/FishingRodItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/FishingRodItem.java @@ -25,10 +25,11 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.session.GeyserSession; public class FishingRodItem extends Item { @@ -37,8 +38,8 @@ public class FishingRodItem extends Item { } @Override - public void translateNbtToBedrock(@NonNull GeyserSession session, @NonNull CompoundTag tag) { - super.translateNbtToBedrock(session, tag); + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + super.translateComponentsToBedrock(session, components, builder); // Fix damage inconsistency Tag damage = tag.get("Damage"); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java b/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java index aacb906c9..60b201961 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.opennbt.tag.builtin.StringTag; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; diff --git a/core/src/main/java/org/geysermc/geyser/item/type/Item.java b/core/src/main/java/org/geysermc/geyser/item/type/Item.java index 3701b5189..df3c5effe 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/Item.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/Item.java @@ -26,10 +26,18 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.Identifier; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; +import com.github.steveice10.mc.protocol.data.game.item.component.ItemEnchantments; import com.github.steveice10.opennbt.tag.builtin.*; +import net.kyori.adventure.text.Component; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; +import org.cloudburstmc.nbt.NbtList; +import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtMapBuilder; +import org.cloudburstmc.nbt.NbtType; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.inventory.item.Enchantment; @@ -38,7 +46,7 @@ import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.MinecraftLocale; -import org.geysermc.geyser.translator.inventory.item.ItemTranslator; +import org.geysermc.geyser.translator.item.ItemTranslator; import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.util.InventoryUtils; @@ -107,7 +115,7 @@ public class Item { public @NonNull ItemStack translateToJava(@NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) { if (itemData.getTag() == null) { - return new ItemStack(javaId, itemData.getCount(), new CompoundTag("")); + return new ItemStack(javaId, itemData.getCount(), null); } return new ItemStack(javaId, itemData.getCount(), ItemTranslator.translateToJavaNBT("", itemData.getTag())); } @@ -117,22 +125,31 @@ public class Item { } /** - * Takes NBT from Java Edition and converts any value that Bedrock parses differently. + * Takes components from Java Edition and map them into Bedrock. */ - public void translateNbtToBedrock(@NonNull GeyserSession session, @NonNull CompoundTag tag) { - if (tag.get("display") instanceof CompoundTag displayTag) { - if (displayTag.get("Lore") instanceof ListTag listTag) { - List lore = new ArrayList<>(); - for (Tag subTag : listTag.getValue()) { - if (!(subTag instanceof StringTag)) continue; - lore.add(new StringTag("", MessageTranslator.convertMessageLenient(((StringTag) subTag).getValue(), session.locale()))); - } - displayTag.put(new ListTag("Lore", lore)); + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { +// // Basing off of ItemStack#getHoverName as of 1.20.5. VERIFY?? +// Component customName = components.get(DataComponentType.CUSTOM_NAME); +// if (customName == null) { +// customName = components.get(DataComponentType.ITEM_NAME); +// } +// if (customName != null) { +// +// } + List loreComponents = components.get(DataComponentType.LORE); + if (loreComponents != null) { + List lore = new ArrayList<>(); + for (Component loreComponent : loreComponents) { + lore.add(MessageTranslator.convertMessage(loreComponent, session.locale())); } + builder.putList("Lore", NbtType.STRING, lore); } List newTags = new ArrayList<>(); - Tag enchantmentTag = tag.remove("Enchantments"); + ItemEnchantments enchantments = components.get(DataComponentType.ENCHANTMENTS); + if (enchantments != null) { + + } if (enchantmentTag instanceof ListTag listTag) { for (Tag subTag : listTag.getValue()) { if (!(subTag instanceof CompoundTag)) continue; @@ -211,10 +228,7 @@ public class Item { } } - protected final @Nullable CompoundTag remapEnchantment(GeyserSession session, CompoundTag tag, CompoundTag rootTag) { - Tag javaEnchId = tag.get("id"); - if (!(javaEnchId instanceof StringTag)) - return null; + protected final @Nullable NbtMap remapEnchantment(GeyserSession session, ItemEnchantments, NbtMapBuilder rootBuilder) { Enchantment enchantment = Enchantment.getByJavaIdentifier(((StringTag) javaEnchId).getValue()); if (enchantment == null) { @@ -231,11 +245,10 @@ public class Item { Tag javaEnchLvl = tag.get("lvl"); - CompoundTag bedrockTag = new CompoundTag(""); - bedrockTag.put(new ShortTag("id", (short) enchantment.ordinal())); - // If the tag cannot parse, Java Edition 1.18.2 sets to 0 - bedrockTag.put(new ShortTag("lvl", javaEnchLvl != null && javaEnchLvl.getValue() instanceof Number lvl ? lvl.shortValue() : (short) 0)); - return bedrockTag; + NbtMapBuilder builder = NbtMap.builder(); + builder.putShort("id", (short) enchantment.ordinal()); + builder.putShort("lvl", ); + return builder.build(); } private void addSweeping(GeyserSession session, CompoundTag itemTag, int level) { @@ -258,8 +271,8 @@ public class Item { /* Translation methods end */ - public ItemStack newItemStack(int count, CompoundTag tag) { - return new ItemStack(this.javaId, count, tag); + public ItemStack newItemStack(int count, DataComponentPatch components) { + return new ItemStack(this.javaId, count, components); } public void setJavaId(int javaId) { // TODO like this? diff --git a/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java b/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java index 4405b66ad..8dbeeb57f 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java @@ -25,8 +25,10 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; import com.github.steveice10.opennbt.tag.builtin.*; import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; @@ -36,8 +38,8 @@ public class MapItem extends Item { } @Override - public void translateNbtToBedrock(@NonNull GeyserSession session, @NonNull CompoundTag tag) { - super.translateNbtToBedrock(session, tag); + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + super.translateComponentsToBedrock(session, components, builder); Tag mapId = tag.remove("map"); if (mapId == null || !(mapId.getValue() instanceof Number number)) return; diff --git a/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java b/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java index 662448a52..4aefcf765 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java @@ -25,10 +25,12 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; 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 org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.MinecraftLocale; @@ -40,8 +42,8 @@ public class PlayerHeadItem extends Item { } @Override - public void translateNbtToBedrock(@NonNull GeyserSession session, @NonNull CompoundTag tag) { - super.translateNbtToBedrock(session, tag); + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + super.translateComponentsToBedrock(session, components, builder); CompoundTag displayTag; if (tag.get("display") instanceof CompoundTag existingDisplayTag) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java b/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java index 24dd56ef2..26c468fb1 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java @@ -25,7 +25,9 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; +import com.github.steveice10.mc.protocol.data.game.item.component.PotionContents; import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import org.checkerframework.checker.nullness.qual.NonNull; @@ -35,8 +37,8 @@ import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.inventory.item.Potion; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; -import org.geysermc.geyser.translator.inventory.item.CustomItemTranslator; -import org.geysermc.geyser.translator.inventory.item.ItemTranslator; +import org.geysermc.geyser.translator.item.CustomItemTranslator; +import org.geysermc.geyser.translator.item.ItemTranslator; public class PotionItem extends Item { public PotionItem(String javaIdentifier, Builder builder) { @@ -45,10 +47,10 @@ public class PotionItem extends Item { @Override public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { - if (itemStack.getNbt() == null) return super.translateToBedrock(itemStack, mapping, mappings); - Tag potionTag = itemStack.getNbt().get("Potion"); - if (potionTag instanceof StringTag) { - ItemDefinition customItemDefinition = CustomItemTranslator.getCustomItem(itemStack.getNbt(), mapping); + if (itemStack.getDataComponentPatch() == null) return super.translateToBedrock(itemStack, mapping, mappings); + PotionContents potionContents = itemStack.getDataComponentPatch().get(DataComponentType.POTION_CONTENTS); + if (potionContents != null) { + ItemDefinition customItemDefinition = CustomItemTranslator.getCustomItem(itemStack.getDataComponentPatch(), mapping); if (customItemDefinition == null) { Potion potion = Potion.getByJavaIdentifier(((StringTag) potionTag).getValue()); if (potion != null) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ShieldItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ShieldItem.java index c13dd4fcf..cd940c87c 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ShieldItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ShieldItem.java @@ -25,11 +25,13 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.item.components.ToolTier; import org.geysermc.geyser.session.GeyserSession; @@ -39,8 +41,8 @@ public class ShieldItem extends Item { } @Override - public void translateNbtToBedrock(@NonNull GeyserSession session, @NonNull CompoundTag tag) { - super.translateNbtToBedrock(session, tag); + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + super.translateComponentsToBedrock(session, components, builder); if (tag.remove("BlockEntityTag") instanceof CompoundTag blockEntityTag) { if (blockEntityTag.get("Patterns") instanceof ListTag patterns) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java index 717bad9a4..e2259eb5d 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java @@ -26,68 +26,61 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.Identifier; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.opennbt.tag.builtin.*; import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtMapBuilder; +import org.cloudburstmc.nbt.NbtType; +import org.geysermc.geyser.item.Items; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.translator.inventory.item.ItemTranslator; +import org.geysermc.geyser.translator.item.ItemTranslator; import org.geysermc.geyser.util.MathUtils; +import java.util.ArrayList; +import java.util.List; + public class ShulkerBoxItem extends BlockItem { public ShulkerBoxItem(String javaIdentifier, Builder builder) { super(javaIdentifier, builder); } @Override - public void translateNbtToBedrock(@NonNull GeyserSession session, @NonNull CompoundTag tag) { - super.translateNbtToBedrock(session, tag); + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + super.translateComponentsToBedrock(session, components, builder); - CompoundTag blockEntityTag = tag.get("BlockEntityTag"); - if (blockEntityTag == null) { + List contents = components.get(DataComponentType.CONTAINER); + if (contents == null || contents.isEmpty()) { // Empty shulker box return; } - if (blockEntityTag.get("Items") == null) return; - ListTag itemsList = new ListTag("Items"); - for (Tag item : (ListTag) blockEntityTag.get("Items")) { - CompoundTag itemData = (CompoundTag) item; // Information about the item - CompoundTag boxItemTag = new CompoundTag(""); // Final item tag to add to the list - boxItemTag.put(new ByteTag("Slot", (byte) (MathUtils.getNbtByte(itemData.get("Slot").getValue()) & 255))); - boxItemTag.put(new ByteTag("WasPickedUp", (byte) 0)); // ??? - - ItemMapping boxMapping = session.getItemMappings().getMapping(Identifier.formalize(((StringTag) itemData.get("id")).getValue())); - - if (boxMapping == null) { - // If invalid ID + List itemsList = new ArrayList<>(); + for (int slot = 0; slot < contents.size(); slot++) { + ItemStack item = contents.get(slot); + if (item.getId() == Items.AIR_ID) { continue; } + NbtMapBuilder boxItemNbt = NbtMap.builder(); // Final item tag to add to the list + boxItemNbt.putByte("Slot", (byte) slot); + boxItemNbt.putByte("WasPickedUp", (byte) 0); // ??? - boxItemTag.put(new StringTag("Name", boxMapping.getBedrockIdentifier())); - boxItemTag.put(new ShortTag("Damage", (short) boxMapping.getBedrockData())); - boxItemTag.put(new ByteTag("Count", MathUtils.getNbtByte(itemData.get("Count").getValue()))); + ItemMapping boxMapping = session.getItemMappings().getMapping(item.getId()); + + boxItemNbt.putString("Name", boxMapping.getBedrockIdentifier()); + boxItemNbt.putShort("Damage", (short) boxMapping.getBedrockData()); + boxItemNbt.putByte("Count", (byte) item.getAmount()); // Only the display name is what we have interest in, so just translate that if relevant - CompoundTag displayTag = itemData.get("tag"); - if (displayTag == null && boxMapping.hasTranslation()) { - displayTag = new CompoundTag("tag"); - } - if (displayTag != null) { - boxItemTag.put(ItemTranslator.translateDisplayProperties(session, displayTag, boxMapping, '7')); + DataComponentPatch boxComponents = item.getDataComponentPatch(); + if (boxComponents != null) { + boxItemNbt.put(ItemTranslator.translateDisplayProperties(session, displayTag, boxMapping, '7')); } - itemsList.add(boxItemTag); + itemsList.add(boxItemNbt.build()); } - tag.put(itemsList); - - // Strip the BlockEntityTag from the chests contents - // sent to the client. The client does not parse this - // or use it for anything, as this tag is fully - // server-side, so we remove it to reduce bandwidth and - // solve potential issues with very large tags. - - // There was a problem in the past where this would strip - // NBT data in creative mode, however with the new server - // authoritative inventories, this is no longer a concern. - tag.remove("BlockEntityTag"); + builder.putList("Items", NbtType.COMPOUND, itemsList); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/item/type/TippedArrowItem.java b/core/src/main/java/org/geysermc/geyser/item/type/TippedArrowItem.java index f78836d16..fcf562ba5 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/TippedArrowItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/TippedArrowItem.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; @@ -33,7 +33,7 @@ import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.inventory.item.TippedArrowPotion; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; -import org.geysermc.geyser.translator.inventory.item.ItemTranslator; +import org.geysermc.geyser.translator.item.ItemTranslator; public class TippedArrowItem extends ArrowItem { public TippedArrowItem(String javaIdentifier, Builder builder) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/TropicalFishBucketItem.java b/core/src/main/java/org/geysermc/geyser/item/type/TropicalFishBucketItem.java index 8b4e35d1e..17f90ca12 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/TropicalFishBucketItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/TropicalFishBucketItem.java @@ -25,12 +25,14 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; import com.github.steveice10.opennbt.tag.builtin.*; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.Style; import net.kyori.adventure.text.format.TextDecoration; import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.entity.type.living.animal.TropicalFishEntity; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.MinecraftLocale; @@ -47,8 +49,8 @@ public class TropicalFishBucketItem extends Item { } @Override - public void translateNbtToBedrock(@NonNull GeyserSession session, @NonNull CompoundTag tag) { - super.translateNbtToBedrock(session, tag); + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + super.translateComponentsToBedrock(session, components, builder); // Prevent name from appearing as "Bucket of" tag.put(new ByteTag("AppendCustomName", (byte) 1)); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/WritableBookItem.java b/core/src/main/java/org/geysermc/geyser/item/type/WritableBookItem.java index dfebecf7d..67221b1c6 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/WritableBookItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/WritableBookItem.java @@ -25,11 +25,13 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.text.MessageTranslator; @@ -43,8 +45,8 @@ public class WritableBookItem extends Item { } @Override - public void translateNbtToBedrock(@NonNull GeyserSession session, @NonNull CompoundTag tag) { - super.translateNbtToBedrock(session, tag); + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + super.translateComponentsToBedrock(session, components, builder); ListTag pagesTag = tag.remove("pages"); if (pagesTag == null) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java b/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java index 045aaa416..0198e73ff 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; @@ -32,6 +33,7 @@ import com.github.steveice10.opennbt.tag.builtin.Tag; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.text.MessageTranslator; @@ -48,13 +50,13 @@ public class WrittenBookItem extends WritableBookItem { } @Override - public void translateNbtToBedrock(@NonNull GeyserSession session, @NonNull CompoundTag tag) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { boolean isValid = isValidWrittenBook(tag); if (!isValid) { tag.remove("pages"); } - super.translateNbtToBedrock(session, tag); + super.translateComponentsToBedrock(session, components, builder); if (!isValid) { CompoundTag invalidTagPage = new CompoundTag(""); 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 5e4d5fc7a..34e855212 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 @@ -26,7 +26,7 @@ package org.geysermc.geyser.registry.populator; import com.fasterxml.jackson.databind.JsonNode; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; import com.github.steveice10.mc.protocol.data.game.recipe.RecipeType; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; @@ -48,7 +48,7 @@ import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.text.GeyserLocale; -import org.geysermc.geyser.translator.inventory.item.ItemTranslator; +import org.geysermc.geyser.translator.item.ItemTranslator; import java.io.ByteArrayInputStream; import java.io.IOException; 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 40359b437..33908a7e7 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 @@ -25,7 +25,7 @@ package org.geysermc.geyser.registry.type; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import lombok.Builder; diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java index 95ec99412..e6e0c6340 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.inventory; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; import com.github.steveice10.opennbt.tag.builtin.IntTag; diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java index 1447f2b5b..429b577ce 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.inventory; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundSetCreativeModeSlotPacket; @@ -53,7 +53,7 @@ import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.skin.FakeHeadProvider; import org.geysermc.geyser.text.GeyserLocale; -import org.geysermc.geyser.translator.inventory.item.ItemTranslator; +import org.geysermc.geyser.translator.item.ItemTranslator; import org.geysermc.geyser.util.InventoryUtils; import java.util.Arrays; diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/StonecutterInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/StonecutterInventoryTranslator.java index 50c040a0b..d3d15680a 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/StonecutterInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/StonecutterInventoryTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.inventory; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/CustomItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/item/CustomItemTranslator.java similarity index 80% rename from core/src/main/java/org/geysermc/geyser/translator/inventory/item/CustomItemTranslator.java rename to core/src/main/java/org/geysermc/geyser/translator/item/CustomItemTranslator.java index 06d1e3aa6..d5f85dcc3 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/CustomItemTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/item/CustomItemTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2024 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 @@ -23,11 +23,10 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.geyser.translator.inventory.item; +package org.geysermc.geyser.translator.item; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.IntTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import it.unimi.dsi.fastutil.Pair; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; @@ -44,8 +43,8 @@ import java.util.OptionalInt; public final class CustomItemTranslator { @Nullable - public static ItemDefinition getCustomItem(CompoundTag nbt, ItemMapping mapping) { - if (nbt == null) { + public static ItemDefinition getCustomItem(DataComponentPatch components, ItemMapping mapping) { + if (components == null) { return null; } List> customMappings = mapping.getCustomItemOptions(); @@ -53,10 +52,11 @@ public final class CustomItemTranslator { return null; } - int customModelData = nbt.get("CustomModelData") instanceof IntTag customModelDataTag ? customModelDataTag.getValue() : 0; + // TODO getOrDefault + int customModelData = components.get(DataComponentType.CUSTOM_MODEL_DATA); boolean checkDamage = mapping.getJavaItem().maxDamage() > 0; - int damage = !checkDamage ? 0 : nbt.get("Damage") instanceof IntTag damageTag ? damageTag.getValue() : 0; - boolean unbreakable = checkDamage && !isDamaged(nbt, damage); + int damage = !checkDamage ? 0 : components.get(DataComponentType.DAMAGE); + boolean unbreakable = checkDamage && !isDamaged(components, damage); for (Pair mappingTypes : customMappings) { CustomItemOptions options = mappingTypes.key(); @@ -105,15 +105,15 @@ public final class CustomItemTranslator { /* These two functions are based off their Mojmap equivalents from 1.19.2 */ - private static boolean isDamaged(CompoundTag nbt, int damage) { - return isDamagableItem(nbt) && damage > 0; + private static boolean isDamaged(DataComponentPatch components, int damage) { + return isDamagableItem(components) && damage > 0; } - private static boolean isDamagableItem(CompoundTag nbt) { + private static boolean isDamagableItem(DataComponentPatch components) { // mapping.getMaxDamage > 0 should also be checked (return false if not true) but we already check prior to this function - Tag unbreakableTag = nbt.get("Unbreakable"); + Boolean unbreakable = components.get(DataComponentType.UNBREAKABLE); // Tag must either not be present or be set to false - return unbreakableTag == null || !(unbreakableTag.getValue() instanceof Number number) || number.byteValue() == 0; + return unbreakable == null || !unbreakable; } private CustomItemTranslator() { diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/ItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java similarity index 88% rename from core/src/main/java/org/geysermc/geyser/translator/inventory/item/ItemTranslator.java rename to core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java index d1a256551..027c6b5ba 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/ItemTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2024 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 @@ -23,11 +23,15 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.geyser.translator.inventory.item; +package org.geysermc.geyser.translator.item; import com.github.steveice10.mc.protocol.data.game.Identifier; import com.github.steveice10.mc.protocol.data.game.entity.attribute.ModifierOperation; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.component.AdventureModePredicate; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; +import com.github.steveice10.mc.protocol.data.game.item.component.ItemAttributeModifiers; import com.github.steveice10.opennbt.tag.builtin.ByteArrayTag; import com.github.steveice10.opennbt.tag.builtin.ByteTag; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; @@ -133,20 +137,20 @@ public final class ItemTranslator { .build(); } - private static ItemData.@NonNull Builder translateToBedrock(GeyserSession session, Item javaItem, ItemMapping bedrockItem, int count, CompoundTag tag) { - CompoundTag nbt = tag != null ? tag.clone() : null; + private static ItemData.@NonNull Builder translateToBedrock(GeyserSession session, Item javaItem, ItemMapping bedrockItem, int count, DataComponentPatch components) { + NbtMapBuilder builder = NbtMap.builder(); - if (nbt != null) { - javaItem.translateNbtToBedrock(session, nbt); + if (components != null) { + javaItem.translateComponentsToBedrock(session, components, builder); } - nbt = translateDisplayProperties(session, nbt, bedrockItem); + translateDisplayProperties(session, components, bedrockItem); - if (nbt != null) { - Tag hideFlags = nbt.get("HideFlags"); - if (hideFlags == null || !hasFlagPresent(hideFlags, HIDE_ATTRIBUTES_FLAG)) { - // only add if the hide attribute modifiers flag is not present - addAttributeLore(nbt, session.locale()); + if (components != null) { + ItemAttributeModifiers attributeModifiers = components.get(DataComponentType.ATTRIBUTE_MODIFIERS); + if (attributeModifiers != null && attributeModifiers.isShowInTooltip()) { + // only add if attribute modifiers do not indicate to hide them + addAttributeLore(attributeModifiers, builder, session.locale()); } } @@ -173,10 +177,10 @@ public final class ItemTranslator { translateCustomItem(nbt, builder, bedrockItem); - if (nbt != null) { + if (components != null) { // Translate the canDestroy and canPlaceOn Java NBT - ListTag canDestroy = nbt.get("CanDestroy"); - ListTag canPlaceOn = nbt.get("CanPlaceOn"); + AdventureModePredicate canDestroy = components.get(DataComponentType.CAN_BREAK); + AdventureModePredicate canPlaceOn = components.get(DataComponentType.CAN_PLACE_ON); String[] canBreak = getCanModify(canDestroy); String[] canPlace = getCanModify(canPlaceOn); if (canBreak != null) { @@ -197,13 +201,8 @@ public final class ItemTranslator { * @param nbt the NBT of the ItemStack * @param language the locale of the player */ - private static void addAttributeLore(CompoundTag nbt, String language) { - ListTag attributeModifiers = nbt.get("AttributeModifiers"); - if (attributeModifiers == null) { - return; // nothing to convert to lore - } - - CompoundTag displayTag = nbt.get("display"); + private static void addAttributeLore(ItemAttributeModifiers modifiers, NbtMapBuilder builder, String language) { + CompoundTag displayTag = builder.get("display"); if (displayTag == null) { displayTag = new CompoundTag("display"); } @@ -214,25 +213,23 @@ public final class ItemTranslator { // maps each slot to the modifiers applied when in such slot Map> slotsToModifiers = new HashMap<>(); - for (Tag modifier : attributeModifiers) { - CompoundTag modifierTag = (CompoundTag) modifier; - + for (ItemAttributeModifiers.Entry entry : modifiers.getModifiers()) { // convert the modifier tag to a lore entry - String loreEntry = attributeToLore(modifierTag, language); + String loreEntry = attributeToLore(entry.getModifier(), language); if (loreEntry == null) { continue; // invalid or failed } StringTag loreTag = new StringTag("", loreEntry); - StringTag slotTag = modifierTag.get("Slot"); - if (slotTag == null) { + ItemAttributeModifiers.EquipmentSlotGroup slotGroup = entry.getSlot(); + if (slotGroup == ItemAttributeModifiers.EquipmentSlotGroup.ANY) { // modifier applies to all slots implicitly for (String slot : ALL_SLOTS) { slotsToModifiers.computeIfAbsent(slot, s -> new ArrayList<>()).add(loreTag); } } else { // modifier applies to only the specified slot - slotsToModifiers.computeIfAbsent(slotTag.getValue(), s -> new ArrayList<>()).add(loreTag); + slotsToModifiers.computeIfAbsent(slotGroup, s -> new ArrayList<>()).add(loreTag); } } @@ -262,31 +259,23 @@ public final class ItemTranslator { } @Nullable - private static String attributeToLore(CompoundTag modifier, String language) { - Tag amountTag = modifier.get("Amount"); - if (amountTag == null || !(amountTag.getValue() instanceof Number number)) { - return null; - } - double amount = number.doubleValue(); + private static String attributeToLore(ItemAttributeModifiers.AttributeModifier modifier, String language) { + double amount = modifier.getAmount(); if (amount == 0) { return null; } - if (!(modifier.get("AttributeName") instanceof StringTag nameTag)) { - return null; - } - String name = nameTag.getValue().replace("minecraft:", ""); - // the namespace does not need to be present, but if it is, the java client ignores it + String name = modifier.getName().replace("minecraft:", ""); + // the namespace does not need to be present, but if it is, the java client ignores it as of pre-1.20.5 String operationTotal; - Tag operationTag = modifier.get("Operation"); - ModifierOperation operation; - if (operationTag == null || (operation = ModifierOperation.from((int) operationTag.getValue())) == ModifierOperation.ADD) { + ModifierOperation operation = modifier.getOperation(); + if (operation == ModifierOperation.ADD) { if (name.equals("generic.knockback_resistance")) { amount *= 10; } operationTotal = ATTRIBUTE_FORMAT.format(amount); - } else if (operation == ModifierOperation.ADD_MULTIPLIED || operation == ModifierOperation.MULTIPLY) { + } else if (operation == ModifierOperation.ADD_MULTIPLIED_BASE || operation == ModifierOperation.ADD_MULTIPLIED_TOTAL) { operationTotal = ATTRIBUTE_FORMAT.format(amount * 100) + "%"; } else { GeyserImpl.getInstance().getLogger().warning("Unhandled ModifierOperation while adding item attributes: " + operation); @@ -363,12 +352,22 @@ public final class ItemTranslator { * @param canModifyJava the list of items in Java * @return the new list of items in Bedrock */ - private static String @Nullable [] getCanModify(ListTag canModifyJava) { - if (canModifyJava != null && canModifyJava.size() > 0) { - String[] canModifyBedrock = new String[canModifyJava.size()]; + // TODO this is now more complicated in 1.20.5. Yippee! + private static String @Nullable [] getCanModify(@Nullable AdventureModePredicate canModifyJava) { + if (canModifyJava == null) { + return null; + } + List predicates = canModifyJava.getPredicates(); + if (predicates.size() > 0) { + String[] canModifyBedrock = new String[predicates.size()]; for (int i = 0; i < canModifyBedrock.length; i++) { // Get the Java identifier of the block that can be placed - String block = Identifier.formalize(((StringTag) canModifyJava.get(i)).getValue()); + String location = predicates.get(i).getLocation(); + if (location == null) { + canModifyBedrock[i] = ""; // So it'll serialize + continue; // ??? + } + String block = Identifier.formalize(location); // Get the Bedrock identifier of the item and replace it. // This will unfortunately be limited - for example, beds and banners will be translated weirdly canModifyBedrock[i] = BlockRegistries.JAVA_TO_BEDROCK_IDENTIFIERS.getOrDefault(block, block).replace("minecraft:", ""); @@ -403,7 +402,7 @@ public final class ItemTranslator { } } - ItemDefinition definition = CustomItemTranslator.getCustomItem(itemStack.getNbt(), mapping); + ItemDefinition definition = CustomItemTranslator.getCustomItem(itemStack, mapping); if (definition == null) { // No custom item return itemDefinition; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java index 381adf2b7..59317fd7c 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.bedrock; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBookEditTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBookEditTranslator.java index 6547044c3..ec1d62d16 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBookEditTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBookEditTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.bedrock; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundEditBookPacket; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; 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 4ac835268..8d005e515 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 @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.bedrock; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.mc.protocol.data.game.entity.object.Direction; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; @@ -70,7 +70,7 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.SkullCache; import org.geysermc.geyser.skin.FakeHeadProvider; import org.geysermc.geyser.translator.inventory.InventoryTranslator; -import org.geysermc.geyser.translator.inventory.item.ItemTranslator; +import org.geysermc.geyser.translator.item.ItemTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.util.BlockUtils; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java index 33410f240..f5122b256 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java @@ -52,7 +52,7 @@ import org.geysermc.geyser.registry.type.BlockMapping; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.SkullCache; -import org.geysermc.geyser.translator.inventory.item.CustomItemTranslator; +import org.geysermc.geyser.translator.item.CustomItemTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.util.BlockUtils; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java index 94c69b780..aca02feab 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; import com.github.steveice10.mc.protocol.data.game.recipe.Recipe; import com.github.steveice10.mc.protocol.data.game.recipe.RecipeType; @@ -56,7 +56,7 @@ import org.geysermc.geyser.inventory.recipe.TrimRecipe; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.translator.inventory.item.ItemTranslator; +import org.geysermc.geyser.translator.item.ItemTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.util.InventoryUtils; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEquipmentTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEquipmentTranslator.java index 0c344bddc..c178f27d4 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEquipmentTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEquipmentTranslator.java @@ -26,7 +26,7 @@ package org.geysermc.geyser.translator.protocol.java.entity; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Equipment; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundSetEquipmentPacket; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.entity.type.Entity; @@ -35,7 +35,7 @@ import org.geysermc.geyser.entity.type.player.PlayerEntity; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.skin.FakeHeadProvider; -import org.geysermc.geyser.translator.inventory.item.ItemTranslator; +import org.geysermc.geyser.translator.item.ItemTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerSetSlotTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerSetSlotTranslator.java index 605a40d75..594c99291 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerSetSlotTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerSetSlotTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.inventory; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.inventory.ClientboundContainerSetSlotPacket; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId; @@ -41,7 +41,7 @@ import org.geysermc.geyser.inventory.recipe.GeyserShapedRecipe; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.inventory.InventoryTranslator; import org.geysermc.geyser.translator.inventory.PlayerInventoryTranslator; -import org.geysermc.geyser.translator.inventory.item.ItemTranslator; +import org.geysermc.geyser.translator.item.ItemTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.util.InventoryUtils; 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 17a4314ec..68d2bcab3 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 @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.inventory; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.mc.protocol.data.game.inventory.VillagerTrade; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.inventory.ClientboundMerchantOffersPacket; import org.cloudburstmc.nbt.NbtMap; @@ -41,7 +41,7 @@ import org.geysermc.geyser.inventory.MerchantContainer; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.translator.inventory.item.ItemTranslator; +import org.geysermc.geyser.translator.item.ItemTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.util.InventoryUtils; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelParticlesTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelParticlesTranslator.java index 11d9dbddf..78290f6bd 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelParticlesTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelParticlesTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.level; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.mc.protocol.data.game.level.particle.BlockParticleData; import com.github.steveice10.mc.protocol.data.game.level.particle.DustParticleData; import com.github.steveice10.mc.protocol.data.game.level.particle.FallingDustParticleData; @@ -49,7 +49,7 @@ import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.type.ParticleMapping; import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.translator.inventory.item.ItemTranslator; +import org.geysermc.geyser.translator.item.ItemTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.util.DimensionUtils; diff --git a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java index 25976f0f5..e56aea8c9 100644 --- a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.util; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundPickItemPacket; From c1edf20734099c7d75933c25c2e388a6d2a9f5f8 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sat, 20 Apr 2024 13:29:14 -0400 Subject: [PATCH 257/344] Here's the idea so far --- .../geyser/inventory/GeyserItemStack.java | 13 +- .../geysermc/geyser/item/type/ArmorItem.java | 4 +- .../geysermc/geyser/item/type/ArrowItem.java | 4 +- .../geyser/item/type/AxolotlBucketItem.java | 4 +- .../geysermc/geyser/item/type/BannerItem.java | 4 +- .../geysermc/geyser/item/type/ChestItem.java | 4 +- .../geyser/item/type/CompassItem.java | 4 +- .../geyser/item/type/CrossbowItem.java | 4 +- .../geyser/item/type/DecoratedPotItem.java | 4 +- .../geyser/item/type/DyeableArmorItem.java | 4 +- .../item/type/DyeableHorseArmorItem.java | 4 +- .../geyser/item/type/EnchantedBookItem.java | 4 +- .../geyser/item/type/FireworkRocketItem.java | 4 +- .../geyser/item/type/FireworkStarItem.java | 4 +- .../geyser/item/type/FishingRodItem.java | 4 +- .../org/geysermc/geyser/item/type/Item.java | 14 +- .../geysermc/geyser/item/type/MapItem.java | 4 +- .../geyser/item/type/PlayerHeadItem.java | 4 +- .../geysermc/geyser/item/type/PotionItem.java | 6 +- .../geysermc/geyser/item/type/ShieldItem.java | 4 +- .../geyser/item/type/ShulkerBoxItem.java | 19 +- .../item/type/TropicalFishBucketItem.java | 4 +- .../geyser/item/type/WritableBookItem.java | 4 +- .../geyser/item/type/WrittenBookItem.java | 4 +- .../translator/item/BedrockItemBuilder.java | 93 ++++++++ .../translator/item/CustomItemTranslator.java | 13 +- .../translator/item/ItemTranslator.java | 207 +++++++----------- 27 files changed, 241 insertions(+), 204 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/translator/item/BedrockItemBuilder.java diff --git a/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java b/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java index dd1aaea81..7e621d3aa 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java @@ -26,7 +26,7 @@ package org.geysermc.geyser.inventory; import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import lombok.AccessLevel; import lombok.Data; @@ -35,7 +35,6 @@ import lombok.Getter; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; -import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.registry.Registries; @@ -49,18 +48,18 @@ public class GeyserItemStack { private final int javaId; private int amount; - private DataComponentPatch components; + private DataComponents components; private int netId; @Getter(AccessLevel.NONE) @EqualsAndHashCode.Exclude private Item item; - private GeyserItemStack(int javaId, int amount, DataComponentPatch components) { + private GeyserItemStack(int javaId, int amount, DataComponents components) { this(javaId, amount, components, 1); } - private GeyserItemStack(int javaId, int amount, DataComponentPatch components, int netId) { + private GeyserItemStack(int javaId, int amount, DataComponents components, int netId) { this.javaId = javaId; this.amount = amount; this.components = components; @@ -68,7 +67,7 @@ public class GeyserItemStack { } public static @NonNull GeyserItemStack from(@Nullable ItemStack itemStack) { - return itemStack == null ? EMPTY : new GeyserItemStack(itemStack.getId(), itemStack.getAmount(), itemStack.getDataComponentPatch()); + return itemStack == null ? EMPTY : new GeyserItemStack(itemStack.getId(), itemStack.getAmount(), itemStack.getDataComponents()); } public int getJavaId() { @@ -84,7 +83,7 @@ public class GeyserItemStack { return null; } - public @Nullable DataComponentPatch getComponents() { + public @Nullable DataComponents getComponents() { return isEmpty() ? null : components; } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java index 669791705..eb5233b88 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import org.checkerframework.checker.nullness.qual.NonNull; @@ -43,7 +43,7 @@ public class ArmorItem extends Item { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { super.translateComponentsToBedrock(session, components, builder); if (tag.get("Trim") instanceof CompoundTag trim) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java index 2462f374c..cf66b036b 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java @@ -46,9 +46,9 @@ public class ArrowItem extends Item { TippedArrowPotion tippedArrowPotion = TippedArrowPotion.getByBedrockId(itemData.getDamage()); ItemStack itemStack = super.translateToJava(itemData, mapping, mappings); if (tippedArrowPotion != null) { - itemStack = Items.TIPPED_ARROW.newItemStack(itemStack.getAmount(), itemStack.getDataComponentPatch()); + itemStack = Items.TIPPED_ARROW.newItemStack(itemStack.getAmount(), itemStack.getDataComponents()); StringTag potionTag = new StringTag("Potion", tippedArrowPotion.getJavaIdentifier()); - itemStack.getDataComponentPatch().put(DataComponentType.POTION_CONTENTS, new PotionContents()); + itemStack.getDataComponents().put(DataComponentType.POTION_CONTENTS, new PotionContents()); } return itemStack; } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/AxolotlBucketItem.java b/core/src/main/java/org/geysermc/geyser/item/type/AxolotlBucketItem.java index 6e4e6c6fc..d0aa1e901 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/AxolotlBucketItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/AxolotlBucketItem.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.ByteTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import org.checkerframework.checker.nullness.qual.NonNull; @@ -39,7 +39,7 @@ public class AxolotlBucketItem extends Item { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { super.translateComponentsToBedrock(session, components, builder); // Bedrock Edition displays the properties of the axolotl. Java does not. diff --git a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java index 9cd7aea42..2a8ca9f15 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; @@ -122,7 +122,7 @@ public class BannerItem extends BlockItem { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { super.translateComponentsToBedrock(session, components, builder); CompoundTag blockEntityTag = tag.remove("BlockEntityTag"); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ChestItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ChestItem.java index 2611c8ff6..8644ec8be 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ChestItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ChestItem.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.session.GeyserSession; @@ -37,7 +37,7 @@ public class ChestItem extends BlockItem { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { super.translateComponentsToBedrock(session, components, builder); // Strip the BlockEntityTag from the chests contents diff --git a/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java b/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java index f3933d83b..605d19852 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java @@ -26,7 +26,7 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.ByteTag; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.IntTag; @@ -60,7 +60,7 @@ public class CompassItem extends Item { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { super.translateComponentsToBedrock(session, components, builder); Tag lodestoneTag = tag.get("LodestoneTracked"); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/CrossbowItem.java b/core/src/main/java/org/geysermc/geyser/item/type/CrossbowItem.java index 1ea468721..c38e2f2ba 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/CrossbowItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/CrossbowItem.java @@ -26,7 +26,7 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.*; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -42,7 +42,7 @@ public class CrossbowItem extends Item { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { super.translateComponentsToBedrock(session, components, builder); ListTag chargedProjectiles = tag.get("ChargedProjectiles"); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java b/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java index bfa86d2ad..74cabc3d9 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import org.checkerframework.checker.nullness.qual.NonNull; @@ -39,7 +39,7 @@ public class DecoratedPotItem extends BlockItem { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { super.translateComponentsToBedrock(session, components, builder); if (tag.remove("BlockEntityTag") instanceof CompoundTag blockEntityTag) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/DyeableArmorItem.java b/core/src/main/java/org/geysermc/geyser/item/type/DyeableArmorItem.java index f1b10474d..fbe0222bc 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/DyeableArmorItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/DyeableArmorItem.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtMapBuilder; @@ -40,7 +40,7 @@ public class DyeableArmorItem extends ArmorItem implements DyeableLeatherItem { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { super.translateComponentsToBedrock(session, components, builder); DyeableLeatherItem.translateNbtToBedrock(tag); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/DyeableHorseArmorItem.java b/core/src/main/java/org/geysermc/geyser/item/type/DyeableHorseArmorItem.java index 39787ae2f..09878e652 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/DyeableHorseArmorItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/DyeableHorseArmorItem.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtMapBuilder; @@ -39,7 +39,7 @@ public class DyeableHorseArmorItem extends Item implements DyeableLeatherItem { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { super.translateComponentsToBedrock(session, components, builder); DyeableLeatherItem.translateNbtToBedrock(tag); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java b/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java index c51278947..d3aa72cbc 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.Tag; @@ -42,7 +42,7 @@ public class EnchantedBookItem extends Item { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { super.translateComponentsToBedrock(session, components, builder); List newTags = new ArrayList<>(); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java b/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java index 6be1be15d..b44dc08eb 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.*; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtMapBuilder; @@ -40,7 +40,7 @@ public class FireworkRocketItem extends Item { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { super.translateComponentsToBedrock(session, components, builder); CompoundTag fireworks = tag.get("Fireworks"); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/FireworkStarItem.java b/core/src/main/java/org/geysermc/geyser/item/type/FireworkStarItem.java index 6d4347e9e..80a32fc44 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/FireworkStarItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/FireworkStarItem.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.IntArrayTag; import com.github.steveice10.opennbt.tag.builtin.IntTag; @@ -41,7 +41,7 @@ public class FireworkStarItem extends Item { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { super.translateComponentsToBedrock(session, components, builder); Tag explosion = tag.remove("Explosion"); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/FishingRodItem.java b/core/src/main/java/org/geysermc/geyser/item/type/FishingRodItem.java index 50a0bddbc..0e1a4cc0e 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/FishingRodItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/FishingRodItem.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import org.checkerframework.checker.nullness.qual.NonNull; @@ -38,7 +38,7 @@ public class FishingRodItem extends Item { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { super.translateComponentsToBedrock(session, components, builder); // Fix damage inconsistency diff --git a/core/src/main/java/org/geysermc/geyser/item/type/Item.java b/core/src/main/java/org/geysermc/geyser/item/type/Item.java index df3c5effe..3ecf3be1b 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/Item.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/Item.java @@ -27,7 +27,7 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.Identifier; import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.item.component.ItemEnchantments; import com.github.steveice10.opennbt.tag.builtin.*; @@ -103,12 +103,12 @@ public class Item { .definition(mapping.getBedrockDefinition()) .damage(mapping.getBedrockData()) .count(itemStack.getAmount()); - if (itemStack.getNbt() != null) { - builder.tag(ItemTranslator.translateNbtToBedrock(itemStack.getNbt())); + if (itemStack.getDataComponents() != null) { + builder.tag(ItemTranslator.translateNbtToBedrock(itemStack.getDataComponents())); } - CompoundTag nbt = itemStack.getNbt(); - ItemTranslator.translateCustomItem(nbt, builder, mapping); + DataComponents components = itemStack.getDataComponents(); + ItemTranslator.translateCustomItem(components, builder, mapping); return builder; } @@ -127,7 +127,7 @@ public class Item { /** * Takes components from Java Edition and map them into Bedrock. */ - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { // // Basing off of ItemStack#getHoverName as of 1.20.5. VERIFY?? // Component customName = components.get(DataComponentType.CUSTOM_NAME); // if (customName == null) { @@ -271,7 +271,7 @@ public class Item { /* Translation methods end */ - public ItemStack newItemStack(int count, DataComponentPatch components) { + public ItemStack newItemStack(int count, DataComponents components) { return new ItemStack(this.javaId, count, components); } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java b/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java index 8dbeeb57f..64e505800 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.*; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtMapBuilder; @@ -38,7 +38,7 @@ public class MapItem extends Item { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { super.translateComponentsToBedrock(session, components, builder); Tag mapId = tag.remove("map"); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java b/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java index 4aefcf765..6ebc728cb 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.Tag; @@ -42,7 +42,7 @@ public class PlayerHeadItem extends Item { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { super.translateComponentsToBedrock(session, components, builder); CompoundTag displayTag; diff --git a/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java b/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java index 26c468fb1..bed2945ba 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java @@ -47,10 +47,10 @@ public class PotionItem extends Item { @Override public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { - if (itemStack.getDataComponentPatch() == null) return super.translateToBedrock(itemStack, mapping, mappings); - PotionContents potionContents = itemStack.getDataComponentPatch().get(DataComponentType.POTION_CONTENTS); + if (itemStack.getDataComponents() == null) return super.translateToBedrock(itemStack, mapping, mappings); + PotionContents potionContents = itemStack.getDataComponents().get(DataComponentType.POTION_CONTENTS); if (potionContents != null) { - ItemDefinition customItemDefinition = CustomItemTranslator.getCustomItem(itemStack.getDataComponentPatch(), mapping); + ItemDefinition customItemDefinition = CustomItemTranslator.getCustomItem(itemStack.getDataComponents(), mapping); if (customItemDefinition == null) { Potion potion = Potion.getByJavaIdentifier(((StringTag) potionTag).getValue()); if (potion != null) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ShieldItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ShieldItem.java index cd940c87c..b3f9f57e3 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ShieldItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ShieldItem.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; @@ -41,7 +41,7 @@ public class ShieldItem extends Item { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { super.translateComponentsToBedrock(session, components, builder); if (tag.remove("BlockEntityTag") instanceof CompoundTag blockEntityTag) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java index e2259eb5d..3d5fa2444 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java @@ -25,11 +25,10 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.Identifier; import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.opennbt.tag.builtin.*; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; @@ -38,7 +37,6 @@ import org.geysermc.geyser.item.Items; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.ItemTranslator; -import org.geysermc.geyser.util.MathUtils; import java.util.ArrayList; import java.util.List; @@ -49,7 +47,7 @@ public class ShulkerBoxItem extends BlockItem { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { super.translateComponentsToBedrock(session, components, builder); List contents = components.get(DataComponentType.CONTAINER); @@ -73,9 +71,16 @@ public class ShulkerBoxItem extends BlockItem { boxItemNbt.putShort("Damage", (short) boxMapping.getBedrockData()); boxItemNbt.putByte("Count", (byte) item.getAmount()); // Only the display name is what we have interest in, so just translate that if relevant - DataComponentPatch boxComponents = item.getDataComponentPatch(); + DataComponents boxComponents = item.getDataComponents(); if (boxComponents != null) { - boxItemNbt.put(ItemTranslator.translateDisplayProperties(session, displayTag, boxMapping, '7')); + String customName = ItemTranslator.getCustomName(session, boxComponents, boxMapping, '7'); + if (customName != null) { + boxItemNbt.putCompound("tag", NbtMap.builder() + .putCompound("display", NbtMap.builder() + .putString("Name", customName) + .build()) + .build()); + } } itemsList.add(boxItemNbt.build()); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/TropicalFishBucketItem.java b/core/src/main/java/org/geysermc/geyser/item/type/TropicalFishBucketItem.java index 17f90ca12..2ce0dd071 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/TropicalFishBucketItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/TropicalFishBucketItem.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.*; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; @@ -49,7 +49,7 @@ public class TropicalFishBucketItem extends Item { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { super.translateComponentsToBedrock(session, components, builder); // Prevent name from appearing as "Bucket of" diff --git a/core/src/main/java/org/geysermc/geyser/item/type/WritableBookItem.java b/core/src/main/java/org/geysermc/geyser/item/type/WritableBookItem.java index 67221b1c6..46b9b80ce 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/WritableBookItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/WritableBookItem.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; @@ -45,7 +45,7 @@ public class WritableBookItem extends Item { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { super.translateComponentsToBedrock(session, components, builder); ListTag pagesTag = tag.remove("pages"); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java b/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java index 0198e73ff..46eceaa86 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; @@ -50,7 +50,7 @@ public class WrittenBookItem extends WritableBookItem { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponentPatch components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { boolean isValid = isValidWrittenBook(tag); if (!isValid) { tag.remove("pages"); diff --git a/core/src/main/java/org/geysermc/geyser/translator/item/BedrockItemBuilder.java b/core/src/main/java/org/geysermc/geyser/translator/item/BedrockItemBuilder.java new file mode 100644 index 000000000..162d57120 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/translator/item/BedrockItemBuilder.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2019-2024 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.translator.item; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtMapBuilder; +import org.cloudburstmc.nbt.NbtType; + +import java.util.ArrayList; +import java.util.List; + +/** + * An intermediary class made to allow easy access to work-in-progress NBT, such as lore and display. + */ +public final class BedrockItemBuilder { + // All Bedrock-style + @Nullable + private String customName; + @Nullable + private List lore; + /** + * Miscellaneous NBT that will be put into the final item. + */ + @Nullable + private NbtMapBuilder builder; + + public BedrockItemBuilder setCustomName(String customName) { + this.customName = customName; + return this; + } + + @NonNull + public List getOrCreateLore() { + if (lore == null) { + lore = new ArrayList<>(); + } + return lore; + } + + @NonNull + public NbtMapBuilder getOrCreateNbt() { + if (builder == null) { + builder = NbtMap.builder(); + } + return builder; + } + + /** + * @return null if no NBT is needed on this item. + */ + @Nullable + public NbtMap build() { + if (customName != null || lore != null) { + NbtMapBuilder display = NbtMap.builder(); + if (customName != null) { + display.putString("Name", customName); + } + if (lore != null) { + display.putList("Lore", NbtType.STRING, lore); + } + getOrCreateNbt().put("display", display.build()); + } + if (builder == null) { + return null; + } + return builder.build(); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/translator/item/CustomItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/item/CustomItemTranslator.java index d5f85dcc3..8a541fb9b 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/item/CustomItemTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/item/CustomItemTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.item; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import it.unimi.dsi.fastutil.Pair; import org.checkerframework.checker.nullness.qual.Nullable; @@ -43,7 +43,7 @@ import java.util.OptionalInt; public final class CustomItemTranslator { @Nullable - public static ItemDefinition getCustomItem(DataComponentPatch components, ItemMapping mapping) { + public static ItemDefinition getCustomItem(DataComponents components, ItemMapping mapping) { if (components == null) { return null; } @@ -52,10 +52,9 @@ public final class CustomItemTranslator { return null; } - // TODO getOrDefault - int customModelData = components.get(DataComponentType.CUSTOM_MODEL_DATA); + int customModelData = components.getOrDefault(DataComponentType.CUSTOM_MODEL_DATA, 0); boolean checkDamage = mapping.getJavaItem().maxDamage() > 0; - int damage = !checkDamage ? 0 : components.get(DataComponentType.DAMAGE); + int damage = !checkDamage ? 0 : components.getOrDefault(DataComponentType.DAMAGE, 0); boolean unbreakable = checkDamage && !isDamaged(components, damage); for (Pair mappingTypes : customMappings) { @@ -105,11 +104,11 @@ public final class CustomItemTranslator { /* These two functions are based off their Mojmap equivalents from 1.19.2 */ - private static boolean isDamaged(DataComponentPatch components, int damage) { + private static boolean isDamaged(DataComponents components, int damage) { return isDamagableItem(components) && damage > 0; } - private static boolean isDamagableItem(DataComponentPatch components) { + private static boolean isDamagableItem(DataComponents components) { // mapping.getMaxDamage > 0 should also be checked (return false if not true) but we already check prior to this function Boolean unbreakable = components.get(DataComponentType.UNBREAKABLE); // Tag must either not be present or be set to false diff --git a/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java index 027c6b5ba..b52861b35 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java @@ -25,11 +25,12 @@ package org.geysermc.geyser.translator.item; +import com.github.steveice10.mc.auth.data.GameProfile; import com.github.steveice10.mc.protocol.data.game.Identifier; import com.github.steveice10.mc.protocol.data.game.entity.attribute.ModifierOperation; import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.mc.protocol.data.game.item.component.AdventureModePredicate; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentPatch; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.item.component.ItemAttributeModifiers; import com.github.steveice10.opennbt.tag.builtin.ByteArrayTag; @@ -83,7 +84,6 @@ public final class ItemTranslator { */ private static final String[] ALL_SLOTS = new String[]{"mainhand", "offhand", "feet", "legs", "chest", "head"}; private static final DecimalFormat ATTRIBUTE_FORMAT = new DecimalFormat("0.#####"); - private static final byte HIDE_ATTRIBUTES_FLAG = 1 << 1; private ItemTranslator() { } @@ -102,23 +102,23 @@ public final class ItemTranslator { ItemStack itemStack = javaItem.translateToJava(data, bedrockItem, mappings); - if (itemStack.getNbt() != null) { - javaItem.translateNbtToJava(itemStack.getNbt(), bedrockItem); - if (itemStack.getNbt().isEmpty()) { - // Otherwise, seems to cause issues with villagers accepting books, and I don't see how this will break anything else. - Camotoy - itemStack = new ItemStack(itemStack.getId(), itemStack.getAmount(), null); - } - } +// if (itemStack.getNbt() != null) { +// javaItem.translateNbtToJava(itemStack.getNbt(), bedrockItem); +// if (itemStack.getNbt().isEmpty()) { +// // Otherwise, seems to cause issues with villagers accepting books, and I don't see how this will break anything else. - Camotoy +// itemStack = new ItemStack(itemStack.getId(), itemStack.getAmount(), null); +// } +// } return itemStack; } - public static ItemData.@NonNull Builder translateToBedrock(GeyserSession session, int javaId, int count, CompoundTag tag) { + public static ItemData.@NonNull Builder translateToBedrock(GeyserSession session, int javaId, int count, DataComponents components) { ItemMapping bedrockItem = session.getItemMappings().getMapping(javaId); if (bedrockItem == ItemMapping.AIR) { session.getGeyser().getLogger().debug("ItemMapping returned air: " + javaId); return ItemData.builder(); } - return translateToBedrock(session, Registries.JAVA_ITEMS.get().get(javaId), bedrockItem, count, tag); + return translateToBedrock(session, Registries.JAVA_ITEMS.get().get(javaId), bedrockItem, count, components); } @NonNull @@ -133,32 +133,35 @@ public final class ItemTranslator { return ItemData.AIR; } // Java item needs to be loaded separately. The mapping for tipped arrow would - return translateToBedrock(session, Registries.JAVA_ITEMS.get().get(stack.getId()), bedrockItem, stack.getAmount(), stack.getNbt()) + return translateToBedrock(session, Registries.JAVA_ITEMS.get().get(stack.getId()), bedrockItem, stack.getAmount(), stack.getDataComponents()) .build(); } - private static ItemData.@NonNull Builder translateToBedrock(GeyserSession session, Item javaItem, ItemMapping bedrockItem, int count, DataComponentPatch components) { - NbtMapBuilder builder = NbtMap.builder(); + private static ItemData.@NonNull Builder translateToBedrock(GeyserSession session, Item javaItem, ItemMapping bedrockItem, int count, DataComponents components) { + BedrockItemBuilder nbtBuilder = new BedrockItemBuilder(); if (components != null) { - javaItem.translateComponentsToBedrock(session, components, builder); + javaItem.translateComponentsToBedrock(session, components, nbtBuilder.getOrCreateNbt()); } - translateDisplayProperties(session, components, bedrockItem); + String customName = getCustomName(session, components, bedrockItem); + if (customName != null) { + nbtBuilder.setCustomName(customName); + } if (components != null) { ItemAttributeModifiers attributeModifiers = components.get(DataComponentType.ATTRIBUTE_MODIFIERS); if (attributeModifiers != null && attributeModifiers.isShowInTooltip()) { // only add if attribute modifiers do not indicate to hide them - addAttributeLore(attributeModifiers, builder, session.locale()); + addAttributeLore(attributeModifiers, nbtBuilder, session.locale()); } } if (session.isAdvancedTooltips()) { - nbt = addAdvancedTooltips(nbt, javaItem, session.locale()); + addAdvancedTooltips(components, nbtBuilder, javaItem, session.locale()); } - ItemStack itemStack = new ItemStack(javaItem.javaId(), count, nbt); + ItemStack itemStack = new ItemStack(javaItem.javaId(), count, components); ItemData.Builder builder = javaItem.translateToBedrock(itemStack, bedrockItem, session.getItemMappings()); if (bedrockItem.isBlock()) { @@ -172,10 +175,10 @@ public final class ItemTranslator { } if (bedrockItem.getJavaItem().equals(Items.PLAYER_HEAD)) { - translatePlayerHead(session, nbt, builder); + translatePlayerHead(session, components, builder); } - translateCustomItem(nbt, builder, bedrockItem); + translateCustomItem(components, builder, bedrockItem); if (components != null) { // Translate the canDestroy and canPlaceOn Java NBT @@ -198,21 +201,12 @@ public final class ItemTranslator { * Bedrock Edition does not see attribute modifiers like Java Edition does, * so we add them as lore instead. * - * @param nbt the NBT of the ItemStack + * @param modifiers the attribute modifiers of the ItemStack * @param language the locale of the player */ - private static void addAttributeLore(ItemAttributeModifiers modifiers, NbtMapBuilder builder, String language) { - CompoundTag displayTag = builder.get("display"); - if (displayTag == null) { - displayTag = new CompoundTag("display"); - } - ListTag lore = displayTag.get("Lore"); - if (lore == null) { - lore = new ListTag("Lore"); - } - + private static void addAttributeLore(ItemAttributeModifiers modifiers, BedrockItemBuilder builder, String language) { // maps each slot to the modifiers applied when in such slot - Map> slotsToModifiers = new HashMap<>(); + Map> slotsToModifiers = new HashMap<>(); for (ItemAttributeModifiers.Entry entry : modifiers.getModifiers()) { // convert the modifier tag to a lore entry String loreEntry = attributeToLore(entry.getModifier(), language); @@ -220,23 +214,22 @@ public final class ItemTranslator { continue; // invalid or failed } - StringTag loreTag = new StringTag("", loreEntry); ItemAttributeModifiers.EquipmentSlotGroup slotGroup = entry.getSlot(); if (slotGroup == ItemAttributeModifiers.EquipmentSlotGroup.ANY) { // modifier applies to all slots implicitly - for (String slot : ALL_SLOTS) { - slotsToModifiers.computeIfAbsent(slot, s -> new ArrayList<>()).add(loreTag); + for (String slot : ALL_SLOTS) { // TODO SOMEONE LOOK HERE PLZ + //slotsToModifiers.computeIfAbsent(slot, s -> new ArrayList<>()).add(loreEntry); } } else { // modifier applies to only the specified slot - slotsToModifiers.computeIfAbsent(slotGroup, s -> new ArrayList<>()).add(loreTag); + slotsToModifiers.computeIfAbsent(slotGroup, s -> new ArrayList<>()).add(loreEntry); } } // iterate through the small array, not the map, so that ordering matches Java Edition for (String slot : ALL_SLOTS) { - List modifiers = slotsToModifiers.get(slot); - if (modifiers == null || modifiers.isEmpty()) { + List modifierStrings = slotsToModifiers.get(slot); + if (modifierStrings == null || modifierStrings.isEmpty()) { continue; } @@ -246,16 +239,13 @@ public final class ItemTranslator { .color(NamedTextColor.GRAY) .append(Component.newline(), Component.translatable("item.modifiers." + slot)) .build(); - lore.add(new StringTag("", MessageTranslator.convertMessage(slotComponent, language))); + builder.getOrCreateLore().add(MessageTranslator.convertMessage(slotComponent, language)); // Then list all the modifiers when used in this slot - for (StringTag modifier : modifiers) { - lore.add(modifier); + for (String modifier : modifierStrings) { + builder.getOrCreateLore().add(modifier); } } - - displayTag.put(lore); - nbt.put(displayTag); } @Nullable @@ -294,29 +284,13 @@ public final class ItemTranslator { return MessageTranslator.convertMessage(attributeComponent, language); } - private static CompoundTag addAdvancedTooltips(CompoundTag nbt, Item item, String language) { - CompoundTag newNbt = nbt; - if (newNbt == null) { - newNbt = new CompoundTag("nbt"); - CompoundTag display = new CompoundTag("display"); - display.put(new ListTag("Lore")); - newNbt.put(display); - } - CompoundTag compoundTag = newNbt.get("display"); - if (compoundTag == null) { - compoundTag = new CompoundTag("display"); - } - ListTag listTag = compoundTag.get("Lore"); - - if (listTag == null) { - listTag = new ListTag("Lore"); - } + private static void addAdvancedTooltips(DataComponents components, BedrockItemBuilder builder, Item item, String language) { int maxDurability = item.maxDamage(); if (maxDurability != 0) { - Tag durabilityTag = newNbt.get("Damage"); - if (durabilityTag instanceof IntTag) { - int durability = maxDurability - ((IntTag) durabilityTag).getValue(); + Integer durabilityComponent = components.get(DataComponentType.DAMAGE); + if (durabilityComponent != null) { + int durability = maxDurability - durabilityComponent; if (durability != maxDurability) { Component component = Component.text() .resetStyle() @@ -325,24 +299,21 @@ public final class ItemTranslator { Component.text(durability), Component.text(maxDurability))) .build(); - listTag.add(new StringTag("", MessageTranslator.convertMessage(component, language))); + builder.getOrCreateLore().add(MessageTranslator.convertMessage(component, language)); } } } - listTag.add(new StringTag("", ChatColor.RESET + ChatColor.DARK_GRAY + item.javaIdentifier())); - if (nbt != null) { + builder.getOrCreateLore().add(ChatColor.RESET + ChatColor.DARK_GRAY + item.javaIdentifier()); + if (components != null) { Component component = Component.text() .resetStyle() .color(NamedTextColor.DARK_GRAY) - .append(Component.translatable("item.nbt_tags", - Component.text(nbt.size()))) + .append(Component.translatable("item.nbt_tags", // TODO + Component.text(components.getDataComponents().size()))) .build(); - listTag.add(new StringTag("", MessageTranslator.convertMessage(component, language))); + builder.getOrCreateLore().add(MessageTranslator.convertMessage(component, language)); } - compoundTag.put(listTag); - newNbt.put(compoundTag); - return newNbt; } /** @@ -396,13 +367,13 @@ public final class ItemTranslator { } if (mapping.getJavaItem().equals(Items.PLAYER_HEAD)) { - CustomSkull customSkull = getCustomSkull(session, itemStack.getNbt()); + CustomSkull customSkull = getCustomSkull(session, itemStack.getComponents()); if (customSkull != null) { itemDefinition = session.getItemMappings().getCustomBlockItemDefinitions().get(customSkull.getCustomBlockData()); } } - ItemDefinition definition = CustomItemTranslator.getCustomItem(itemStack, mapping); + ItemDefinition definition = CustomItemTranslator.getCustomItem(itemStack.getComponents(), mapping); if (definition == null) { // No custom item return itemDefinition; @@ -533,65 +504,45 @@ public final class ItemTranslator { /** * Translates the display name of the item * @param session the Bedrock client's session - * @param tag the tag to translate + * @param components the components to translate * @param mapping the item entry, in case it requires translation - * - * @return the new tag to use, should the current one be null */ - public static CompoundTag translateDisplayProperties(GeyserSession session, CompoundTag tag, ItemMapping mapping) { - return translateDisplayProperties(session, tag, mapping, 'f'); + public static String getCustomName(GeyserSession session, DataComponents components, ItemMapping mapping) { + return getCustomName(session, components, mapping, 'f'); } /** * @param translationColor if this item is not available on Java, the color that the new name should be. * Normally, this should just be white, but for shulker boxes this should be gray. */ - public static CompoundTag translateDisplayProperties(GeyserSession session, CompoundTag tag, ItemMapping mapping, char translationColor) { - boolean hasCustomName = false; - if (tag != null) { - if (tag.get("display") instanceof CompoundTag display && display.get("Name") instanceof StringTag tagName) { - String name = tagName.getValue(); - - // Get the translated name and prefix it with a reset char - name = MessageTranslator.convertMessageLenient(name, session.locale()); - - // Add the new name tag - display.put(new StringTag("Name", name)); - // Indicate that a custom name is present - hasCustomName = true; - - // Add to the new root tag - tag.put(display); + public static String getCustomName(GeyserSession session, DataComponents components, ItemMapping mapping, char translationColor) { + if (components != null) { + // ItemStack#getHoverName as of 1.20.5 + Component customName = components.get(DataComponentType.CUSTOM_NAME); + if (customName == null) { + customName = components.get(DataComponentType.ITEM_NAME); + } + if (customName != null) { + // Get the translated name and prefix it with a reset char TODO test + return MessageTranslator.convertMessage(customName, session.locale()); } } - if (!hasCustomName && mapping.hasTranslation()) { + if (mapping.hasTranslation()) { // No custom name, but we need to localize the item's name - if (tag == null) { - tag = new CompoundTag(""); - } - CompoundTag display; - if (tag.get("display") instanceof CompoundTag oldDisplay) { - display = oldDisplay; - } else { - display = new CompoundTag("display"); - // Add to the new root tag - tag.put(display); - } - String translationKey = mapping.getTranslationString(); // Reset formatting since Bedrock defaults to italics - display.put(new StringTag("Name", ChatColor.RESET + ChatColor.ESCAPE + translationColor + MinecraftLocale.getLocaleString(translationKey, session.locale()))); + return ChatColor.RESET + ChatColor.ESCAPE + translationColor + MinecraftLocale.getLocaleString(translationKey, session.locale()); } - - return tag; + // No custom name + return null; } /** * Translates the custom model data of an item */ - public static void translateCustomItem(CompoundTag nbt, ItemData.Builder builder, ItemMapping mapping) { - ItemDefinition definition = CustomItemTranslator.getCustomItem(nbt, mapping); + public static void translateCustomItem(DataComponents components, ItemData.Builder builder, ItemMapping mapping) { + ItemDefinition definition = CustomItemTranslator.getCustomItem(components, mapping); if (definition != null) { builder.definition(definition); builder.blockDefinition(null); @@ -608,8 +559,12 @@ public final class ItemTranslator { builder.blockDefinition(blockDefinition); } - private static @Nullable CustomSkull getCustomSkull(GeyserSession session, CompoundTag nbt) { - if (nbt != null && nbt.contains("SkullOwner")) { + private static @Nullable CustomSkull getCustomSkull(GeyserSession session, DataComponents components) { + if (components == null) { + return null; + } + GameProfile profile = components.get(DataComponentType.PROFILE); + if (profile != null) { if (!(nbt.get("SkullOwner") instanceof CompoundTag skullOwner)) { // It's a username give up d: return null; @@ -626,8 +581,8 @@ public final class ItemTranslator { return null; } - private static void translatePlayerHead(GeyserSession session, CompoundTag nbt, ItemData.Builder builder) { - CustomSkull customSkull = getCustomSkull(session, nbt); + private static void translatePlayerHead(GeyserSession session, DataComponents components, ItemData.Builder builder) { + CustomSkull customSkull = getCustomSkull(session, components); if (customSkull != null) { CustomBlockData customBlockData = customSkull.getCustomBlockData(); ItemDefinition itemDefinition = session.getItemMappings().getCustomBlockItemDefinitions().get(customBlockData); @@ -636,18 +591,4 @@ public final class ItemTranslator { builder.blockDefinition(blockDefinition); } } - - /** - * Checks if the NBT of a Java item stack has the given hide flag. - * - * @param hideFlags the "HideFlags", which may not be null - * @param flagMask the flag to check for, as a bit mask - * @return true if the flag is present, false if not or if the tag value is not a number - */ - private static boolean hasFlagPresent(Tag hideFlags, byte flagMask) { - if (hideFlags.getValue() instanceof Number flags) { - return (flags.byteValue() & flagMask) == flagMask; - } - return false; - } } From 909139326d3324eb6637c23f60a0f4516f09149c Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sat, 20 Apr 2024 14:55:30 -0400 Subject: [PATCH 258/344] Keep chugging away --- .../geyser/item/DyeableLeatherItem.java | 15 +++--- .../geysermc/geyser/item/type/ArmorItem.java | 25 ++++++---- .../geyser/item/type/AxolotlBucketItem.java | 14 +++--- .../geysermc/geyser/item/type/BannerItem.java | 37 +++++++------- .../geysermc/geyser/item/type/ChestItem.java | 16 ++----- .../geyser/item/type/CompassItem.java | 34 +++++++------ .../geyser/item/type/CrossbowItem.java | 35 +++++++------- .../geyser/item/type/DecoratedPotItem.java | 20 ++++---- .../geyser/item/type/DyeableArmorItem.java | 6 +-- .../item/type/DyeableHorseArmorItem.java | 6 +-- .../geyser/item/type/EnchantedBookItem.java | 4 +- .../geyser/item/type/FilledMapItem.java | 18 +++---- .../geyser/item/type/FireworkRocketItem.java | 48 +++++++++---------- .../geyser/item/type/FireworkStarItem.java | 4 +- .../geyser/item/type/FishingRodItem.java | 4 +- .../org/geysermc/geyser/item/type/Item.java | 18 ++----- .../geysermc/geyser/item/type/MapItem.java | 4 +- .../geyser/item/type/PlayerHeadItem.java | 4 +- .../geysermc/geyser/item/type/ShieldItem.java | 4 +- .../geyser/item/type/ShulkerBoxItem.java | 16 +++---- .../item/type/TropicalFishBucketItem.java | 4 +- .../geyser/item/type/WritableBookItem.java | 4 +- .../geyser/item/type/WrittenBookItem.java | 4 +- .../geyser/session/cache/LodestoneCache.java | 3 +- .../translator/item/BedrockItemBuilder.java | 35 ++++++++++++++ .../translator/item/ItemTranslator.java | 2 +- 26 files changed, 200 insertions(+), 184 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/item/DyeableLeatherItem.java b/core/src/main/java/org/geysermc/geyser/item/DyeableLeatherItem.java index e0eec767f..214b9d78c 100644 --- a/core/src/main/java/org/geysermc/geyser/item/DyeableLeatherItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/DyeableLeatherItem.java @@ -25,20 +25,21 @@ package org.geysermc.geyser.item; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; +import com.github.steveice10.mc.protocol.data.game.item.component.DyedItemColor; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.IntTag; +import org.geysermc.geyser.translator.item.BedrockItemBuilder; public interface DyeableLeatherItem { - static void translateNbtToBedrock(CompoundTag tag) { - CompoundTag displayTag = tag.get("display"); - if (displayTag == null) { + static void translateComponentsToBedrock(DataComponents components, BedrockItemBuilder builder) { + DyedItemColor dyedItemColor = components.get(DataComponentType.DYED_COLOR); + if (dyedItemColor == null) { return; } - IntTag color = displayTag.remove("color"); - if (color != null) { - tag.put(new IntTag("customColor", color.getValue())); - } + builder.putInt("customColor", dyedItemColor.getRgb()); } static void translateNbtToJava(CompoundTag tag) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java index eb5233b88..ba7f05205 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java @@ -25,14 +25,18 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.item.component.ArmorTrim; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.item.ArmorMaterial; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.item.BedrockItemBuilder; public class ArmorItem extends Item { private final ArmorMaterial material; @@ -43,23 +47,26 @@ public class ArmorItem extends Item { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); - if (tag.get("Trim") instanceof CompoundTag trim) { - StringTag material = trim.remove("material"); - StringTag pattern = trim.remove("pattern"); + ArmorTrim trim = components.get(DataComponentType.TRIM); + if (trim != null) { + // TODO material IDs + String material = trim.getMaterial().getAssetName(); + String pattern = trim.getPattern().getAssetId(); // discard custom trim patterns/materials to prevent visual glitches on bedrock - if (!material.getValue().startsWith("minecraft:") - || !pattern.getValue().startsWith("minecraft:")) { - tag.remove("Trim"); + if (!material.startsWith("minecraft:") + || !pattern.startsWith("minecraft:")) { return; } + NbtMapBuilder trimBuilder = NbtMap.builder(); // bedrock has an uppercase first letter key, and the value is not namespaced - trim.put(new StringTag("Material", stripNamespace(material.getValue()))); - trim.put(new StringTag("Pattern", stripNamespace(pattern.getValue()))); + trimBuilder.put("Material", stripNamespace(material)); + trimBuilder.put("Pattern", stripNamespace(pattern)); + builder.putCompound("Trim", trimBuilder.build()); } } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/AxolotlBucketItem.java b/core/src/main/java/org/geysermc/geyser/item/type/AxolotlBucketItem.java index d0aa1e901..99f649e87 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/AxolotlBucketItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/AxolotlBucketItem.java @@ -26,12 +26,10 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.opennbt.tag.builtin.ByteTag; -import com.github.steveice10.opennbt.tag.builtin.StringTag; import org.checkerframework.checker.nullness.qual.NonNull; -import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.MinecraftLocale; +import org.geysermc.geyser.translator.item.BedrockItemBuilder; public class AxolotlBucketItem extends Item { public AxolotlBucketItem(String javaIdentifier, Builder builder) { @@ -39,15 +37,15 @@ public class AxolotlBucketItem extends Item { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); // Bedrock Edition displays the properties of the axolotl. Java does not. // To work around this, set the custom name to the Axolotl translation and it's displayed correctly - tag.put(new ByteTag("AppendCustomName", (byte) 1)); - tag.put(new StringTag("CustomName", MinecraftLocale.getLocaleString("entity.minecraft.axolotl", session.locale()))); + builder.putByte("AppendCustomName", 1); + builder.putString("CustomName", MinecraftLocale.getLocaleString("entity.minecraft.axolotl", session.locale())); // Boilerplate required so the nametag does not appear as "Bucket of " - tag.put(new StringTag("ColorID", "")); - tag.put(new StringTag("BodyID", "")); + builder.putString("ColorID", ""); + builder.putString("BodyID", ""); } } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java index 2a8ca9f15..549809391 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java @@ -25,6 +25,8 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.item.component.BannerPatternLayer; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.IntTag; @@ -33,16 +35,14 @@ import com.github.steveice10.opennbt.tag.builtin.Tag; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtList; import org.cloudburstmc.nbt.NbtMap; -import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.item.BedrockItemBuilder; import java.util.ArrayList; import java.util.List; -import static org.geysermc.erosion.util.BannerUtils.getJavaPatternTag; - public class BannerItem extends BlockItem { /** * Holds what a Java ominous banner pattern looks like. @@ -51,19 +51,20 @@ public class BannerItem extends BlockItem { * ominous banners that we set instead. This variable is used to detect Java ominous banner patterns, and apply * the correct ominous banner pattern if Bedrock pulls the item from creative. */ - public static final ListTag OMINOUS_BANNER_PATTERN; + public static final List OMINOUS_BANNER_PATTERN; static { - OMINOUS_BANNER_PATTERN = new ListTag("Patterns"); // Construct what an ominous banner is supposed to look like - OMINOUS_BANNER_PATTERN.add(getJavaPatternTag("mr", 9)); - OMINOUS_BANNER_PATTERN.add(getJavaPatternTag("bs", 8)); - OMINOUS_BANNER_PATTERN.add(getJavaPatternTag("cs", 7)); - OMINOUS_BANNER_PATTERN.add(getJavaPatternTag("bo", 8)); - OMINOUS_BANNER_PATTERN.add(getJavaPatternTag("ms", 15)); - OMINOUS_BANNER_PATTERN.add(getJavaPatternTag("hh", 8)); - OMINOUS_BANNER_PATTERN.add(getJavaPatternTag("mc", 8)); - OMINOUS_BANNER_PATTERN.add(getJavaPatternTag("bo", 15)); + OMINOUS_BANNER_PATTERN = List.of( + new BannerPatternLayer("mr", 9), + new BannerPatternLayer("bs", 8), + new BannerPatternLayer("cs", 7), + new BannerPatternLayer("bo", 8), + new BannerPatternLayer("ms", 15), + new BannerPatternLayer("hh", 8), + new BannerPatternLayer("mc", 8), + new BannerPatternLayer("bo", 15) + ); } /** @@ -102,7 +103,7 @@ public class BannerItem extends BlockItem { * @return The Java edition format pattern nbt */ public static CompoundTag getJavaBannerPattern(NbtMap pattern) { - return getJavaPatternTag(pattern.getString("Pattern"), 15 - pattern.getInt("Color")); + return new BannerPatternLayer(pattern.getString("Pattern"), 15 - pattern.getInt("Color")); } /** @@ -122,14 +123,14 @@ public class BannerItem extends BlockItem { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); - CompoundTag blockEntityTag = tag.remove("BlockEntityTag"); - if (blockEntityTag != null && blockEntityTag.get("Patterns") instanceof ListTag patterns) { + List patterns = components.get(DataComponentType.BANNER_PATTERNS); + if (patterns != null) { if (patterns.equals(OMINOUS_BANNER_PATTERN)) { // Remove the current patterns and set the ominous banner type - tag.put(new IntTag("Type", 1)); + builder.putInt("Type", 1); } else { invertBannerColors(patterns); tag.put(patterns); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ChestItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ChestItem.java index 8644ec8be..1f6ac6964 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ChestItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ChestItem.java @@ -27,9 +27,10 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import org.checkerframework.checker.nullness.qual.NonNull; -import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.item.BedrockItemBuilder; +@Deprecated public class ChestItem extends BlockItem { public ChestItem(String javaIdentifier, Builder builder) { @@ -37,18 +38,7 @@ public class ChestItem extends BlockItem { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); - - // Strip the BlockEntityTag from the chests contents - // sent to the client. The client does not parse this - // or use it for anything, as this tag is fully - // server-side, so we remove it to reduce bandwidth and - // solve potential issues with very large tags. - - // There was a problem in the past where this would strip - // NBT data in creative mode, however with the new server - // authoritative inventories, this is no longer a concern. - tag.remove("BlockEntityTag"); } } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java b/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java index 605d19852..8d48d1307 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java @@ -26,17 +26,16 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.item.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.opennbt.tag.builtin.ByteTag; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.IntTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; +import com.github.steveice10.mc.protocol.data.game.item.component.LodestoneTracker; import org.checkerframework.checker.nullness.qual.NonNull; -import org.cloudburstmc.nbt.NbtMapBuilder; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.item.BedrockItemBuilder; public class CompassItem extends Item { public CompassItem(String javaIdentifier, Builder builder) { @@ -45,36 +44,35 @@ public class CompassItem extends Item { @Override public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { - if (isLodestoneCompass(itemStack.getNbt())) { + if (isLodestoneCompass(itemStack.getDataComponents())) { return super.translateToBedrock(itemStack, mappings.getLodestoneCompass(), mappings); } return super.translateToBedrock(itemStack, mapping, mappings); } @Override - public ItemMapping toBedrockDefinition(CompoundTag nbt, ItemMappings mappings) { - if (isLodestoneCompass(nbt)) { + public ItemMapping toBedrockDefinition(DataComponents components, ItemMappings mappings) { + if (isLodestoneCompass(components)) { return mappings.getLodestoneCompass(); } - return super.toBedrockDefinition(nbt, mappings); + return super.toBedrockDefinition(components, mappings); } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); - Tag lodestoneTag = tag.get("LodestoneTracked"); - if (lodestoneTag instanceof ByteTag) { - int trackId = session.getLodestoneCache().store(tag); + LodestoneTracker tracker = components.get(DataComponentType.LODESTONE_TRACKER); + if (tracker != null) { + int trackId = session.getLodestoneCache().store(tracker); // Set the bedrock tracking id - will return 0 if invalid - tag.put(new IntTag("trackingHandle", trackId)); + builder.putInt("trackingHandle", trackId); } } - private boolean isLodestoneCompass(CompoundTag nbt) { - if (nbt != null) { - Tag lodestoneTag = nbt.get("LodestoneTracked"); - return lodestoneTag instanceof ByteTag; + private boolean isLodestoneCompass(@Nullable DataComponents components) { + if (components != null) { + return components.getDataComponents().containsKey(DataComponentType.LODESTONE_TRACKER); } return false; } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/CrossbowItem.java b/core/src/main/java/org/geysermc/geyser/item/type/CrossbowItem.java index c38e2f2ba..5b92ba303 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/CrossbowItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/CrossbowItem.java @@ -26,44 +26,41 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.item.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.opennbt.tag.builtin.*; +import com.github.steveice10.opennbt.tag.builtin.ByteTag; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.ListTag; +import com.github.steveice10.opennbt.tag.builtin.StringTag; import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.geyser.translator.item.ItemTranslator; +import java.util.List; + public class CrossbowItem extends Item { public CrossbowItem(String javaIdentifier, Builder builder) { super(javaIdentifier, builder); } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); - ListTag chargedProjectiles = tag.get("ChargedProjectiles"); - if (chargedProjectiles != null) { - if (!chargedProjectiles.getValue().isEmpty()) { - CompoundTag javaProjectileAsNbt = (CompoundTag) chargedProjectiles.getValue().get(0); + List chargedProjectiles = components.get(DataComponentType.CHARGED_PROJECTILES); + if (chargedProjectiles != null && !chargedProjectiles.isEmpty()) { + ItemStack javaProjectile = chargedProjectiles.get(0); - ItemMapping projectileMapping = session.getItemMappings().getMapping((String) javaProjectileAsNbt.get("id").getValue()); - if (projectileMapping == null) return; - @Nullable CompoundTag projectileTag = javaProjectileAsNbt.get("tag"); - ItemStack itemStack = new ItemStack(projectileMapping.getJavaItem().javaId(), (byte) javaProjectileAsNbt.get("Count").getValue(), projectileTag); - ItemData itemData = ItemTranslator.translateToBedrock(session, itemStack); + ItemMapping projectileMapping = session.getItemMappings().getMapping(javaProjectile.getId()); + ItemData itemData = ItemTranslator.translateToBedrock(session, javaProjectile); - CompoundTag newProjectile = new CompoundTag("chargedItem"); - newProjectile.put(new ByteTag("Count", (byte) itemData.getCount())); - newProjectile.put(new StringTag("Name", projectileMapping.getBedrockIdentifier())); + NbtMapBuilder newProjectile = BedrockItemBuilder.createItemNbt(projectileMapping, itemData.getCount(), itemData.getDamage()); - newProjectile.put(new ShortTag("Damage", (short) itemData.getDamage())); - - tag.put(newProjectile); - } + builder.putCompound("chargedItem", newProjectile.build()); } } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java b/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java index 74cabc3d9..792ec0f0b 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java @@ -25,12 +25,11 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.ListTag; import org.checkerframework.checker.nullness.qual.NonNull; -import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.item.BedrockItemBuilder; public class DecoratedPotItem extends BlockItem { @@ -39,14 +38,15 @@ public class DecoratedPotItem extends BlockItem { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); - if (tag.remove("BlockEntityTag") instanceof CompoundTag blockEntityTag) { - if (blockEntityTag.remove("sherds") instanceof ListTag sherds) { - // bedrock wants it on the root level - tag.put(sherds); - } - } + components.get(DataComponentType.POT_DECORATIONS); // TODO +// if (tag.remove("BlockEntityTag") instanceof CompoundTag blockEntityTag) { +// if (blockEntityTag.remove("sherds") instanceof ListTag sherds) { +// // bedrock wants it on the root level +// tag.put(sherds); +// } +// } } } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/DyeableArmorItem.java b/core/src/main/java/org/geysermc/geyser/item/type/DyeableArmorItem.java index fbe0222bc..117e70b9a 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/DyeableArmorItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/DyeableArmorItem.java @@ -28,11 +28,11 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.checkerframework.checker.nullness.qual.NonNull; -import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.item.ArmorMaterial; import org.geysermc.geyser.item.DyeableLeatherItem; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.item.BedrockItemBuilder; public class DyeableArmorItem extends ArmorItem implements DyeableLeatherItem { public DyeableArmorItem(String javaIdentifier, ArmorMaterial material, Builder builder) { @@ -40,10 +40,10 @@ public class DyeableArmorItem extends ArmorItem implements DyeableLeatherItem { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); - DyeableLeatherItem.translateNbtToBedrock(tag); + DyeableLeatherItem.translateComponentsToBedrock(components, builder); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/item/type/DyeableHorseArmorItem.java b/core/src/main/java/org/geysermc/geyser/item/type/DyeableHorseArmorItem.java index 09878e652..cb6dd869b 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/DyeableHorseArmorItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/DyeableHorseArmorItem.java @@ -28,10 +28,10 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.checkerframework.checker.nullness.qual.NonNull; -import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.item.DyeableLeatherItem; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.item.BedrockItemBuilder; public class DyeableHorseArmorItem extends Item implements DyeableLeatherItem { public DyeableHorseArmorItem(String javaIdentifier, Builder builder) { @@ -39,10 +39,10 @@ public class DyeableHorseArmorItem extends Item implements DyeableLeatherItem { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); - DyeableLeatherItem.translateNbtToBedrock(tag); + DyeableLeatherItem.translateComponentsToBedrock(components, builder); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java b/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java index d3aa72cbc..3851813ae 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java @@ -30,8 +30,8 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import org.checkerframework.checker.nullness.qual.NonNull; -import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.item.BedrockItemBuilder; import java.util.ArrayList; import java.util.List; @@ -42,7 +42,7 @@ public class EnchantedBookItem extends Item { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); List newTags = new ArrayList<>(); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/FilledMapItem.java b/core/src/main/java/org/geysermc/geyser/item/type/FilledMapItem.java index 8125ce101..78a175f8d 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/FilledMapItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/FilledMapItem.java @@ -26,8 +26,8 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.registry.type.ItemMapping; @@ -41,16 +41,16 @@ public class FilledMapItem extends MapItem { @Override public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { ItemData.Builder builder = super.translateToBedrock(itemStack, mapping, mappings); - CompoundTag nbt = itemStack.getNbt(); - if (nbt == null) { + DataComponents components = itemStack.getDataComponents(); + if (components == null) { // This is a fallback for maps with no nbt (Change added back in June 2020; is it needed in 2023?) return builder.tag(NbtMap.builder().putInt("map", 0).build()); - } else if (nbt.get("display") instanceof CompoundTag display) { - // Note: damage 5 treasure map, 6 ??? - Tag mapColor = display.get("MapColor"); - if (mapColor != null && mapColor.getValue() instanceof Number color) { + } else { + Integer mapColor = components.get(DataComponentType.MAP_COLOR); + if (mapColor != null) { + // Note: damage 5 treasure map, 6 ??? // Java Edition allows any color; Bedrock only allows some. So let's take what colors we can get - switch (color.intValue()) { + switch (mapColor) { case 3830373 -> builder.damage(3); // Ocean Monument case 5393476 -> builder.damage(4); // Woodland explorer } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java b/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java index b44dc08eb..d688e59f6 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java @@ -25,44 +25,47 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; +import com.github.steveice10.mc.protocol.data.game.item.component.Fireworks; import com.github.steveice10.opennbt.tag.builtin.*; import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.level.FireworkColor; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.geyser.util.MathUtils; +import java.util.ArrayList; +import java.util.List; + public class FireworkRocketItem extends Item { public FireworkRocketItem(String javaIdentifier, Builder builder) { super(javaIdentifier, builder); } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); - CompoundTag fireworks = tag.get("Fireworks"); + Fireworks fireworks = components.get(DataComponentType.FIREWORKS); if (fireworks == null) { return; } + NbtMapBuilder fireworksNbt = NbtMap.builder(); + fireworksNbt.putByte("Flight", (byte) fireworks.getFlightDuration()); - if (fireworks.get("Flight") != null) { - fireworks.put(new ByteTag("Flight", MathUtils.getNbtByte(fireworks.get("Flight").getValue()))); - } - - ListTag explosions = fireworks.get("Explosions"); - if (explosions == null) { + List explosions = fireworks.getExplosions(); + if (explosions.isEmpty()) { return; } - for (Tag effect : explosions.getValue()) { - CompoundTag effectData = (CompoundTag) effect; - CompoundTag newEffectData = translateExplosionToBedrock(effectData, ""); - - explosions.remove(effectData); - explosions.add(newEffectData); + List explosionNbt = new ArrayList<>(); + for (Fireworks.FireworkExplosion explosion : explosions) { + explosionNbt.add(translateExplosionToBedrock(explosion, "")); } + } @Override @@ -70,13 +73,15 @@ public class FireworkRocketItem extends Item { super.translateNbtToJava(tag, mapping); } - static CompoundTag translateExplosionToBedrock(CompoundTag explosion, String newName) { - CompoundTag newExplosionData = new CompoundTag(newName); + static NbtMap translateExplosionToBedrock(Fireworks.FireworkExplosion explosion, String newName) { + NbtMapBuilder newExplosionData = NbtMap.builder(); if (explosion.get("Type") != null) { newExplosionData.put(new ByteTag("FireworkType", MathUtils.getNbtByte(explosion.get("Type").getValue()))); } + //newExplosionData.putByte("FireworkType", explosion.get) //TODO??? + // TODO do we need length checks if (explosion.get("Colors") != null) { int[] oldColors = (int[]) explosion.get("Colors").getValue(); byte[] colors = new byte[oldColors.length]; @@ -101,15 +106,10 @@ public class FireworkRocketItem extends Item { newExplosionData.put(new ByteArrayTag("FireworkFade", colors)); } - if (explosion.get("Trail") != null) { - newExplosionData.put(new ByteTag("FireworkTrail", MathUtils.getNbtByte(explosion.get("Trail").getValue()))); - } + newExplosionData.putBoolean("FireworkTrail", explosion.isHasTrail()); + newExplosionData.putBoolean("FireworkFlicker", explosion.isHasTwinkle()); // TODO verify - if (explosion.get("Flicker") != null) { - newExplosionData.put(new ByteTag("FireworkFlicker", MathUtils.getNbtByte(explosion.get("Flicker").getValue()))); - } - - return newExplosionData; + return newExplosionData.build(); } static CompoundTag translateExplosionToJava(CompoundTag explosion, String newName) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/FireworkStarItem.java b/core/src/main/java/org/geysermc/geyser/item/type/FireworkStarItem.java index 80a32fc44..4ae9c8b13 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/FireworkStarItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/FireworkStarItem.java @@ -31,9 +31,9 @@ import com.github.steveice10.opennbt.tag.builtin.IntArrayTag; import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import org.checkerframework.checker.nullness.qual.NonNull; -import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.item.BedrockItemBuilder; public class FireworkStarItem extends Item { public FireworkStarItem(String javaIdentifier, Builder builder) { @@ -41,7 +41,7 @@ public class FireworkStarItem extends Item { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); Tag explosion = tag.remove("Explosion"); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/FishingRodItem.java b/core/src/main/java/org/geysermc/geyser/item/type/FishingRodItem.java index 0e1a4cc0e..4538689da 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/FishingRodItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/FishingRodItem.java @@ -29,8 +29,8 @@ import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import org.checkerframework.checker.nullness.qual.NonNull; -import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.item.BedrockItemBuilder; public class FishingRodItem extends Item { public FishingRodItem(String javaIdentifier, Builder builder) { @@ -38,7 +38,7 @@ public class FishingRodItem extends Item { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); // Fix damage inconsistency diff --git a/core/src/main/java/org/geysermc/geyser/item/type/Item.java b/core/src/main/java/org/geysermc/geyser/item/type/Item.java index 3ecf3be1b..decc60da8 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/Item.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/Item.java @@ -34,10 +34,8 @@ import com.github.steveice10.opennbt.tag.builtin.*; import net.kyori.adventure.text.Component; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; -import org.cloudburstmc.nbt.NbtList; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; -import org.cloudburstmc.nbt.NbtType; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.inventory.item.Enchantment; @@ -46,6 +44,7 @@ import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.MinecraftLocale; +import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.geyser.translator.item.ItemTranslator; import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.util.InventoryUtils; @@ -120,29 +119,20 @@ public class Item { return new ItemStack(javaId, itemData.getCount(), ItemTranslator.translateToJavaNBT("", itemData.getTag())); } - public ItemMapping toBedrockDefinition(CompoundTag nbt, ItemMappings mappings) { + public ItemMapping toBedrockDefinition(DataComponents components, ItemMappings mappings) { return mappings.getMapping(javaId); } /** * Takes components from Java Edition and map them into Bedrock. */ - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { -// // Basing off of ItemStack#getHoverName as of 1.20.5. VERIFY?? -// Component customName = components.get(DataComponentType.CUSTOM_NAME); -// if (customName == null) { -// customName = components.get(DataComponentType.ITEM_NAME); -// } -// if (customName != null) { -// -// } + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { List loreComponents = components.get(DataComponentType.LORE); if (loreComponents != null) { - List lore = new ArrayList<>(); + List lore = builder.getOrCreateLore(); for (Component loreComponent : loreComponents) { lore.add(MessageTranslator.convertMessage(loreComponent, session.locale())); } - builder.putList("Lore", NbtType.STRING, lore); } List newTags = new ArrayList<>(); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java b/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java index 64e505800..b015862c5 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java @@ -28,9 +28,9 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.*; import org.checkerframework.checker.nullness.qual.NonNull; -import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.item.BedrockItemBuilder; public class MapItem extends Item { public MapItem(String javaIdentifier, Builder builder) { @@ -38,7 +38,7 @@ public class MapItem extends Item { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); Tag mapId = tag.remove("map"); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java b/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java index 6ebc728cb..dae444775 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java @@ -30,10 +30,10 @@ 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 org.checkerframework.checker.nullness.qual.NonNull; -import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.MinecraftLocale; +import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.geyser.translator.text.MessageTranslator; public class PlayerHeadItem extends Item { @@ -42,7 +42,7 @@ public class PlayerHeadItem extends Item { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); CompoundTag displayTag; diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ShieldItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ShieldItem.java index b3f9f57e3..30b50b436 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ShieldItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ShieldItem.java @@ -31,9 +31,9 @@ import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import org.checkerframework.checker.nullness.qual.NonNull; -import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.item.components.ToolTier; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.item.BedrockItemBuilder; public class ShieldItem extends Item { public ShieldItem(String javaIdentifier, Builder builder) { @@ -41,7 +41,7 @@ public class ShieldItem extends Item { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); if (tag.remove("BlockEntityTag") instanceof CompoundTag blockEntityTag) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java index 3d5fa2444..395563fe3 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java @@ -36,6 +36,7 @@ import org.cloudburstmc.nbt.NbtType; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.geyser.translator.item.ItemTranslator; import java.util.ArrayList; @@ -47,7 +48,7 @@ public class ShulkerBoxItem extends BlockItem { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); List contents = components.get(DataComponentType.CONTAINER); @@ -61,15 +62,12 @@ public class ShulkerBoxItem extends BlockItem { if (item.getId() == Items.AIR_ID) { continue; } - NbtMapBuilder boxItemNbt = NbtMap.builder(); // Final item tag to add to the list - boxItemNbt.putByte("Slot", (byte) slot); - boxItemNbt.putByte("WasPickedUp", (byte) 0); // ??? - ItemMapping boxMapping = session.getItemMappings().getMapping(item.getId()); - boxItemNbt.putString("Name", boxMapping.getBedrockIdentifier()); - boxItemNbt.putShort("Damage", (short) boxMapping.getBedrockData()); - boxItemNbt.putByte("Count", (byte) item.getAmount()); + NbtMapBuilder boxItemNbt = BedrockItemBuilder.createItemNbt(boxMapping, item.getAmount(), boxMapping.getBedrockData()); // Final item tag to add to the list + boxItemNbt.putByte("Slot", (byte) slot); + boxItemNbt.putByte("WasPickedUp", (byte) 0); // ??? TODO might not be needed + // Only the display name is what we have interest in, so just translate that if relevant DataComponents boxComponents = item.getDataComponents(); if (boxComponents != null) { @@ -85,7 +83,7 @@ public class ShulkerBoxItem extends BlockItem { itemsList.add(boxItemNbt.build()); } - builder.putList("Items", NbtType.COMPOUND, itemsList); + builder.getOrCreateNbt().putList("Items", NbtType.COMPOUND, itemsList); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/item/type/TropicalFishBucketItem.java b/core/src/main/java/org/geysermc/geyser/item/type/TropicalFishBucketItem.java index 2ce0dd071..3ece87745 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/TropicalFishBucketItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/TropicalFishBucketItem.java @@ -32,10 +32,10 @@ import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.Style; import net.kyori.adventure.text.format.TextDecoration; import org.checkerframework.checker.nullness.qual.NonNull; -import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.entity.type.living.animal.TropicalFishEntity; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.MinecraftLocale; +import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.geyser.translator.text.MessageTranslator; import java.util.ArrayList; @@ -49,7 +49,7 @@ public class TropicalFishBucketItem extends Item { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); // Prevent name from appearing as "Bucket of" diff --git a/core/src/main/java/org/geysermc/geyser/item/type/WritableBookItem.java b/core/src/main/java/org/geysermc/geyser/item/type/WritableBookItem.java index 46b9b80ce..68cdf99d4 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/WritableBookItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/WritableBookItem.java @@ -31,9 +31,9 @@ import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import org.checkerframework.checker.nullness.qual.NonNull; -import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.geyser.translator.text.MessageTranslator; import java.util.ArrayList; @@ -45,7 +45,7 @@ public class WritableBookItem extends Item { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); ListTag pagesTag = tag.remove("pages"); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java b/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java index 46eceaa86..ae6b81f6e 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java @@ -33,8 +33,8 @@ import com.github.steveice10.opennbt.tag.builtin.Tag; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.checkerframework.checker.nullness.qual.NonNull; -import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.geyser.translator.text.MessageTranslator; import java.util.List; @@ -50,7 +50,7 @@ public class WrittenBookItem extends WritableBookItem { } @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) { + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { boolean isValid = isValidWrittenBook(tag); if (!isValid) { tag.remove("pages"); diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/LodestoneCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/LodestoneCache.java index f118195b9..4bd2244ab 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/LodestoneCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/LodestoneCache.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.session.cache; +import com.github.steveice10.mc.protocol.data.game.item.component.LodestoneTracker; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; @@ -88,7 +89,7 @@ public final class LodestoneCache { this.activeLodestones.put(itemStack, new LodestonePos(id++, x, y, z, dim)); } - public int store(CompoundTag tag) { + public int store(LodestoneTracker tracker) { CompoundTag lodestonePos = tag.get("LodestonePos"); if (lodestonePos == null) { // invalid diff --git a/core/src/main/java/org/geysermc/geyser/translator/item/BedrockItemBuilder.java b/core/src/main/java/org/geysermc/geyser/translator/item/BedrockItemBuilder.java index 162d57120..83293d4ee 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/item/BedrockItemBuilder.java +++ b/core/src/main/java/org/geysermc/geyser/translator/item/BedrockItemBuilder.java @@ -30,6 +30,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; +import org.geysermc.geyser.registry.type.ItemMapping; import java.util.ArrayList; import java.util.List; @@ -70,6 +71,28 @@ public final class BedrockItemBuilder { return builder; } + // NBT convenience methods. Returns NbtMapBuilder since that's what's used the most + + public NbtMapBuilder putByte(String name, byte value) { + return getOrCreateNbt().putByte(name, value); + } + + public NbtMapBuilder putByte(String name, int value) { + return getOrCreateNbt().putByte(name, (byte) value); + } + + public NbtMapBuilder putInt(String name, int value) { + return getOrCreateNbt().putInt(name, value); + } + + public NbtMapBuilder putString(String name, String value) { + return getOrCreateNbt().putString(name, value); + } + + public NbtMapBuilder putCompound(String name, NbtMap value) { + return getOrCreateNbt().putCompound(name, value); + } + /** * @return null if no NBT is needed on this item. */ @@ -90,4 +113,16 @@ public final class BedrockItemBuilder { } return builder.build(); } + + /** + * Creates item NBT with count, name, and damage set. + */ + public static NbtMapBuilder createItemNbt(ItemMapping mapping, int count, int damage) { + NbtMapBuilder builder = NbtMap.builder(); + builder.putByte("Count", (byte) count); + builder.putString("Name", mapping.getBedrockIdentifier()); + + builder.putShort("Damage", (short) damage); + return builder; + } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java index b52861b35..6459aa9ec 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java @@ -141,7 +141,7 @@ public final class ItemTranslator { BedrockItemBuilder nbtBuilder = new BedrockItemBuilder(); if (components != null) { - javaItem.translateComponentsToBedrock(session, components, nbtBuilder.getOrCreateNbt()); + javaItem.translateComponentsToBedrock(session, components, nbtBuilder); } String customName = getCustomName(session, components, bedrockItem); From 6d8021f155765de2cd668d24985f19f03943c15e Mon Sep 17 00:00:00 2001 From: basaigh <53559772+basaigh@users.noreply.github.com> Date: Sun, 21 Apr 2024 00:12:53 +0100 Subject: [PATCH 259/344] Update the non-item parts (#4586) * Update the non-item parts * Add MaceItem * Fix registry data loading --- .../geyser/inventory/item/Enchantment.java | 5 +- .../updater/AnvilInventoryUpdater.java | 2 +- .../geysermc/geyser/item/ArmorMaterial.java | 7 +- .../java/org/geysermc/geyser/item/Items.java | 106 ++++++++++-------- .../geysermc/geyser/item/type/MaceItem.java | 39 +++++++ .../geysermc/geyser/level/JavaDimension.java | 22 ++-- .../geyser/network/netty/LocalSession.java | 2 +- .../loader/EnchantmentRegistryLoader.java | 8 +- .../registry/populator/Conversion649_630.java | 4 +- .../registry/populator/Conversion662_649.java | 24 +++- .../registry/populator/Conversion671_662.java | 25 ++++- .../geyser/session/GeyserSession.java | 5 +- .../inventory/PlayerInventoryTranslator.java | 8 +- .../translator/level/BiomeTranslator.java | 20 ++-- .../protocol/java/JavaCommandsTranslator.java | 2 +- .../protocol/java/JavaLoginTranslator.java | 8 +- .../java/JavaRegistryDataTranslator.java | 46 ++++---- .../protocol/java/JavaRespawnTranslator.java | 6 +- .../level/JavaLevelParticlesTranslator.java | 3 +- .../geysermc/geyser/util/AttributeUtils.java | 4 +- .../geysermc/geyser/util/DimensionUtils.java | 34 ++++-- .../geysermc/geyser/util/InventoryUtils.java | 8 +- .../geysermc/geyser/util/JavaCodecUtil.java | 64 ----------- gradle/libs.versions.toml | 4 +- 24 files changed, 255 insertions(+), 201 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/item/type/MaceItem.java delete mode 100644 core/src/main/java/org/geysermc/geyser/util/JavaCodecUtil.java diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/Enchantment.java b/core/src/main/java/org/geysermc/geyser/inventory/item/Enchantment.java index 5fa2a5784..773de29b1 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/item/Enchantment.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/item/Enchantment.java @@ -118,7 +118,7 @@ public enum Enchantment { KNOCKBACK, FIRE_ASPECT, LOOTING, - SWEEPING, + SWEEPING_EDGE, EFFICIENCY, SILK_TOUCH, UNBREAKING, @@ -136,6 +136,9 @@ public enum Enchantment { MULTISHOT, QUICK_CHARGE, PIERCING, + DENSITY, + BREACH, + WIND_BURST, MENDING, VANISHING_CURSE; diff --git a/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java b/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java index 5adee0c20..96ef12861 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java @@ -350,7 +350,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater { if (enchantment == JavaEnchantment.IMPALING) { // Multiplier is halved on Bedrock for some reason rarityMultiplier /= 2; - } else if (enchantment == JavaEnchantment.SWEEPING) { + } else if (enchantment == JavaEnchantment.SWEEPING_EDGE) { // Doesn't exist on Bedrock rarityMultiplier = 0; } diff --git a/core/src/main/java/org/geysermc/geyser/item/ArmorMaterial.java b/core/src/main/java/org/geysermc/geyser/item/ArmorMaterial.java index 315a8cd4d..348c0af8c 100644 --- a/core/src/main/java/org/geysermc/geyser/item/ArmorMaterial.java +++ b/core/src/main/java/org/geysermc/geyser/item/ArmorMaterial.java @@ -31,12 +31,13 @@ import java.util.function.Supplier; public enum ArmorMaterial { LEATHER(() -> Items.LEATHER), - CHAIN(() -> Items.IRON_INGOT), + CHAINMAIL(() -> Items.IRON_INGOT), IRON(() -> Items.IRON_INGOT), GOLD(() -> Items.GOLD_INGOT), DIAMOND(() -> Items.DIAMOND), - TURTLE(() -> Items.SCUTE), - NETHERITE(() -> Items.NETHERITE_INGOT); + TURTLE(() -> Items.TURTLE_SCUTE), + NETHERITE(() -> Items.NETHERITE_INGOT), + ARMADILLO(() -> Items.ARMADILLO_SCUTE); private final Supplier repairIngredient; diff --git a/core/src/main/java/org/geysermc/geyser/item/Items.java b/core/src/main/java/org/geysermc/geyser/item/Items.java index 2147ebb2c..42a087acf 100644 --- a/core/src/main/java/org/geysermc/geyser/item/Items.java +++ b/core/src/main/java/org/geysermc/geyser/item/Items.java @@ -123,6 +123,7 @@ public final class Items { public static final Item RAW_IRON_BLOCK = register(new BlockItem("raw_iron_block", builder())); public static final Item RAW_COPPER_BLOCK = register(new BlockItem("raw_copper_block", builder())); public static final Item RAW_GOLD_BLOCK = register(new BlockItem("raw_gold_block", builder())); + public static final Item HEAVY_CORE = register(new BlockItem("heavy_core", builder())); public static final Item AMETHYST_BLOCK = register(new BlockItem("amethyst_block", builder())); public static final Item BUDDING_AMETHYST = register(new BlockItem("budding_amethyst", builder())); public static final Item IRON_BLOCK = register(new BlockItem("iron_block", builder())); @@ -832,7 +833,9 @@ public final class Items { public static final Item STRUCTURE_BLOCK = register(new BlockItem("structure_block", builder())); public static final Item JIGSAW = register(new BlockItem("jigsaw", builder())); public static final Item TURTLE_HELMET = register(new ArmorItem("turtle_helmet", ArmorMaterial.TURTLE, builder().stackSize(1).maxDamage(275))); - public static final Item SCUTE = register(new Item("scute", builder())); + public static final Item TURTLE_SCUTE = register(new Item("turtle_scute", builder())); + public static final Item ARMADILLO_SCUTE = register(new Item("armadillo_scute", builder())); + public static final Item WOLF_ARMOR = register(new ArmorItem("wolf_armor", ArmorMaterial.ARMADILLO, builder().stackSize(1).maxDamage(64))); public static final Item FLINT_AND_STEEL = register(new Item("flint_and_steel", builder().stackSize(1).maxDamage(64))); public static final Item APPLE = register(new Item("apple", builder())); public static final Item BOW = register(new Item("bow", builder().stackSize(1).maxDamage(384))); @@ -852,36 +855,36 @@ public final class Items { public static final Item GOLD_INGOT = register(new Item("gold_ingot", builder())); public static final Item NETHERITE_INGOT = register(new Item("netherite_ingot", builder())); public static final Item NETHERITE_SCRAP = register(new Item("netherite_scrap", builder())); - public static final Item WOODEN_SWORD = register(new TieredItem("wooden_sword", ToolTier.WOODEN, builder().stackSize(1).attackDamage(4).maxDamage(59))); - public static final Item WOODEN_SHOVEL = register(new TieredItem("wooden_shovel", ToolTier.WOODEN, builder().stackSize(1).attackDamage(2.5).maxDamage(59))); - public static final Item WOODEN_PICKAXE = register(new TieredItem("wooden_pickaxe", ToolTier.WOODEN, builder().stackSize(1).attackDamage(2).maxDamage(59))); - public static final Item WOODEN_AXE = register(new TieredItem("wooden_axe", ToolTier.WOODEN, builder().stackSize(1).attackDamage(7).maxDamage(59))); - public static final Item WOODEN_HOE = register(new TieredItem("wooden_hoe", ToolTier.WOODEN, builder().stackSize(1).attackDamage(1).maxDamage(59))); - public static final Item STONE_SWORD = register(new TieredItem("stone_sword", ToolTier.STONE, builder().stackSize(1).attackDamage(5).maxDamage(131))); - public static final Item STONE_SHOVEL = register(new TieredItem("stone_shovel", ToolTier.STONE, builder().stackSize(1).attackDamage(3.5).maxDamage(131))); - public static final Item STONE_PICKAXE = register(new TieredItem("stone_pickaxe", ToolTier.STONE, builder().stackSize(1).attackDamage(3).maxDamage(131))); - public static final Item STONE_AXE = register(new TieredItem("stone_axe", ToolTier.STONE, builder().stackSize(1).attackDamage(9).maxDamage(131))); - public static final Item STONE_HOE = register(new TieredItem("stone_hoe", ToolTier.STONE, builder().stackSize(1).attackDamage(1).maxDamage(131))); - public static final Item GOLDEN_SWORD = register(new TieredItem("golden_sword", ToolTier.GOLDEN, builder().stackSize(1).attackDamage(4).maxDamage(32))); - public static final Item GOLDEN_SHOVEL = register(new TieredItem("golden_shovel", ToolTier.GOLDEN, builder().stackSize(1).attackDamage(2.5).maxDamage(32))); - public static final Item GOLDEN_PICKAXE = register(new TieredItem("golden_pickaxe", ToolTier.GOLDEN, builder().stackSize(1).attackDamage(2).maxDamage(32))); - public static final Item GOLDEN_AXE = register(new TieredItem("golden_axe", ToolTier.GOLDEN, builder().stackSize(1).attackDamage(7).maxDamage(32))); - public static final Item GOLDEN_HOE = register(new TieredItem("golden_hoe", ToolTier.GOLDEN, builder().stackSize(1).attackDamage(1).maxDamage(32))); - public static final Item IRON_SWORD = register(new TieredItem("iron_sword", ToolTier.IRON, builder().stackSize(1).attackDamage(6).maxDamage(250))); - public static final Item IRON_SHOVEL = register(new TieredItem("iron_shovel", ToolTier.IRON, builder().stackSize(1).attackDamage(4.5).maxDamage(250))); - public static final Item IRON_PICKAXE = register(new TieredItem("iron_pickaxe", ToolTier.IRON, builder().stackSize(1).attackDamage(4).maxDamage(250))); - public static final Item IRON_AXE = register(new TieredItem("iron_axe", ToolTier.IRON, builder().stackSize(1).attackDamage(9).maxDamage(250))); - public static final Item IRON_HOE = register(new TieredItem("iron_hoe", ToolTier.IRON, builder().stackSize(1).attackDamage(1).maxDamage(250))); - public static final Item DIAMOND_SWORD = register(new TieredItem("diamond_sword", ToolTier.DIAMOND, builder().stackSize(1).attackDamage(7).maxDamage(1561))); - public static final Item DIAMOND_SHOVEL = register(new TieredItem("diamond_shovel", ToolTier.DIAMOND, builder().stackSize(1).attackDamage(5.5).maxDamage(1561))); - public static final Item DIAMOND_PICKAXE = register(new TieredItem("diamond_pickaxe", ToolTier.DIAMOND, builder().stackSize(1).attackDamage(5).maxDamage(1561))); - public static final Item DIAMOND_AXE = register(new TieredItem("diamond_axe", ToolTier.DIAMOND, builder().stackSize(1).attackDamage(9).maxDamage(1561))); - public static final Item DIAMOND_HOE = register(new TieredItem("diamond_hoe", ToolTier.DIAMOND, builder().stackSize(1).attackDamage(1).maxDamage(1561))); - public static final Item NETHERITE_SWORD = register(new TieredItem("netherite_sword", ToolTier.NETHERITE, builder().stackSize(1).attackDamage(8).maxDamage(2031))); - public static final Item NETHERITE_SHOVEL = register(new TieredItem("netherite_shovel", ToolTier.NETHERITE, builder().stackSize(1).attackDamage(6.5).maxDamage(2031))); - public static final Item NETHERITE_PICKAXE = register(new TieredItem("netherite_pickaxe", ToolTier.NETHERITE, builder().stackSize(1).attackDamage(6).maxDamage(2031))); - public static final Item NETHERITE_AXE = register(new TieredItem("netherite_axe", ToolTier.NETHERITE, builder().stackSize(1).attackDamage(10).maxDamage(2031))); - public static final Item NETHERITE_HOE = register(new TieredItem("netherite_hoe", ToolTier.NETHERITE, builder().stackSize(1).attackDamage(1).maxDamage(2031))); + public static final Item WOODEN_SWORD = register(new TieredItem("wooden_sword", ToolTier.WOODEN, builder().stackSize(1).maxDamage(59).attackDamage(4.0))); + public static final Item WOODEN_SHOVEL = register(new TieredItem("wooden_shovel", ToolTier.WOODEN, builder().stackSize(1).maxDamage(59).attackDamage(2.5))); + public static final Item WOODEN_PICKAXE = register(new TieredItem("wooden_pickaxe", ToolTier.WOODEN, builder().stackSize(1).maxDamage(59).attackDamage(2.0))); + public static final Item WOODEN_AXE = register(new TieredItem("wooden_axe", ToolTier.WOODEN, builder().stackSize(1).maxDamage(59).attackDamage(7.0))); + public static final Item WOODEN_HOE = register(new TieredItem("wooden_hoe", ToolTier.WOODEN, builder().stackSize(1).maxDamage(59).attackDamage(1.0))); + public static final Item STONE_SWORD = register(new TieredItem("stone_sword", ToolTier.STONE, builder().stackSize(1).maxDamage(131).attackDamage(5.0))); + public static final Item STONE_SHOVEL = register(new TieredItem("stone_shovel", ToolTier.STONE, builder().stackSize(1).maxDamage(131).attackDamage(3.5))); + public static final Item STONE_PICKAXE = register(new TieredItem("stone_pickaxe", ToolTier.STONE, builder().stackSize(1).maxDamage(131).attackDamage(3.0))); + public static final Item STONE_AXE = register(new TieredItem("stone_axe", ToolTier.STONE, builder().stackSize(1).maxDamage(131).attackDamage(9.0))); + public static final Item STONE_HOE = register(new TieredItem("stone_hoe", ToolTier.STONE, builder().stackSize(1).maxDamage(131).attackDamage(1.0))); + public static final Item GOLDEN_SWORD = register(new TieredItem("golden_sword", ToolTier.GOLDEN, builder().stackSize(1).maxDamage(32).attackDamage(4.0))); + public static final Item GOLDEN_SHOVEL = register(new TieredItem("golden_shovel", ToolTier.GOLDEN, builder().stackSize(1).maxDamage(32).attackDamage(2.5))); + public static final Item GOLDEN_PICKAXE = register(new TieredItem("golden_pickaxe", ToolTier.GOLDEN, builder().stackSize(1).maxDamage(32).attackDamage(2.0))); + public static final Item GOLDEN_AXE = register(new TieredItem("golden_axe", ToolTier.GOLDEN, builder().stackSize(1).maxDamage(32).attackDamage(7.0))); + public static final Item GOLDEN_HOE = register(new TieredItem("golden_hoe", ToolTier.GOLDEN, builder().stackSize(1).maxDamage(32).attackDamage(1.0))); + public static final Item IRON_SWORD = register(new TieredItem("iron_sword", ToolTier.IRON, builder().stackSize(1).maxDamage(250).attackDamage(6.0))); + public static final Item IRON_SHOVEL = register(new TieredItem("iron_shovel", ToolTier.IRON, builder().stackSize(1).maxDamage(250).attackDamage(4.5))); + public static final Item IRON_PICKAXE = register(new TieredItem("iron_pickaxe", ToolTier.IRON, builder().stackSize(1).maxDamage(250).attackDamage(4.0))); + public static final Item IRON_AXE = register(new TieredItem("iron_axe", ToolTier.IRON, builder().stackSize(1).maxDamage(250).attackDamage(9.0))); + public static final Item IRON_HOE = register(new TieredItem("iron_hoe", ToolTier.IRON, builder().stackSize(1).maxDamage(250).attackDamage(1.0))); + public static final Item DIAMOND_SWORD = register(new TieredItem("diamond_sword", ToolTier.DIAMOND, builder().stackSize(1).maxDamage(1561).attackDamage(7.0))); + public static final Item DIAMOND_SHOVEL = register(new TieredItem("diamond_shovel", ToolTier.DIAMOND, builder().stackSize(1).maxDamage(1561).attackDamage(5.5))); + public static final Item DIAMOND_PICKAXE = register(new TieredItem("diamond_pickaxe", ToolTier.DIAMOND, builder().stackSize(1).maxDamage(1561).attackDamage(5.0))); + public static final Item DIAMOND_AXE = register(new TieredItem("diamond_axe", ToolTier.DIAMOND, builder().stackSize(1).maxDamage(1561).attackDamage(9.0))); + public static final Item DIAMOND_HOE = register(new TieredItem("diamond_hoe", ToolTier.DIAMOND, builder().stackSize(1).maxDamage(1561).attackDamage(1.0))); + public static final Item NETHERITE_SWORD = register(new TieredItem("netherite_sword", ToolTier.NETHERITE, builder().stackSize(1).maxDamage(2031).attackDamage(8.0))); + public static final Item NETHERITE_SHOVEL = register(new TieredItem("netherite_shovel", ToolTier.NETHERITE, builder().stackSize(1).maxDamage(2031).attackDamage(6.5))); + public static final Item NETHERITE_PICKAXE = register(new TieredItem("netherite_pickaxe", ToolTier.NETHERITE, builder().stackSize(1).maxDamage(2031).attackDamage(6.0))); + public static final Item NETHERITE_AXE = register(new TieredItem("netherite_axe", ToolTier.NETHERITE, builder().stackSize(1).maxDamage(2031).attackDamage(10.0))); + public static final Item NETHERITE_HOE = register(new TieredItem("netherite_hoe", ToolTier.NETHERITE, builder().stackSize(1).maxDamage(2031).attackDamage(1.0))); public static final Item STICK = register(new Item("stick", builder())); public static final Item BOWL = register(new Item("bowl", builder())); public static final Item MUSHROOM_STEW = register(new Item("mushroom_stew", builder().stackSize(1))); @@ -891,14 +894,14 @@ public final class Items { public static final Item WHEAT_SEEDS = register(new BlockItem("wheat_seeds", builder())); public static final Item WHEAT = register(new Item("wheat", builder())); public static final Item BREAD = register(new Item("bread", builder())); - public static final Item LEATHER_HELMET = register(new DyeableArmorItem("leather_helmet", ArmorMaterial.LEATHER, builder().stackSize(1).maxDamage(55))); - public static final Item LEATHER_CHESTPLATE = register(new DyeableArmorItem("leather_chestplate", ArmorMaterial.LEATHER, builder().stackSize(1).maxDamage(80))); - public static final Item LEATHER_LEGGINGS = register(new DyeableArmorItem("leather_leggings", ArmorMaterial.LEATHER, builder().stackSize(1).maxDamage(75))); - public static final Item LEATHER_BOOTS = register(new DyeableArmorItem("leather_boots", ArmorMaterial.LEATHER, builder().stackSize(1).maxDamage(65))); - public static final Item CHAINMAIL_HELMET = register(new ArmorItem("chainmail_helmet", ArmorMaterial.CHAIN, builder().stackSize(1).maxDamage(165))); - public static final Item CHAINMAIL_CHESTPLATE = register(new ArmorItem("chainmail_chestplate", ArmorMaterial.CHAIN, builder().stackSize(1).maxDamage(240))); - public static final Item CHAINMAIL_LEGGINGS = register(new ArmorItem("chainmail_leggings", ArmorMaterial.CHAIN, builder().stackSize(1).maxDamage(225))); - public static final Item CHAINMAIL_BOOTS = register(new ArmorItem("chainmail_boots", ArmorMaterial.CHAIN, builder().stackSize(1).maxDamage(195))); + public static final Item LEATHER_HELMET = register(new ArmorItem("leather_helmet", ArmorMaterial.LEATHER, builder().stackSize(1).maxDamage(55))); + public static final Item LEATHER_CHESTPLATE = register(new ArmorItem("leather_chestplate", ArmorMaterial.LEATHER, builder().stackSize(1).maxDamage(80))); + public static final Item LEATHER_LEGGINGS = register(new ArmorItem("leather_leggings", ArmorMaterial.LEATHER, builder().stackSize(1).maxDamage(75))); + public static final Item LEATHER_BOOTS = register(new ArmorItem("leather_boots", ArmorMaterial.LEATHER, builder().stackSize(1).maxDamage(65))); + public static final Item CHAINMAIL_HELMET = register(new ArmorItem("chainmail_helmet", ArmorMaterial.CHAINMAIL, builder().stackSize(1).maxDamage(165))); + public static final Item CHAINMAIL_CHESTPLATE = register(new ArmorItem("chainmail_chestplate", ArmorMaterial.CHAINMAIL, builder().stackSize(1).maxDamage(240))); + public static final Item CHAINMAIL_LEGGINGS = register(new ArmorItem("chainmail_leggings", ArmorMaterial.CHAINMAIL, builder().stackSize(1).maxDamage(225))); + public static final Item CHAINMAIL_BOOTS = register(new ArmorItem("chainmail_boots", ArmorMaterial.CHAINMAIL, builder().stackSize(1).maxDamage(195))); public static final Item IRON_HELMET = register(new ArmorItem("iron_helmet", ArmorMaterial.IRON, builder().stackSize(1).maxDamage(165))); public static final Item IRON_CHESTPLATE = register(new ArmorItem("iron_chestplate", ArmorMaterial.IRON, builder().stackSize(1).maxDamage(240))); public static final Item IRON_LEGGINGS = register(new ArmorItem("iron_leggings", ArmorMaterial.IRON, builder().stackSize(1).maxDamage(225))); @@ -1043,11 +1046,13 @@ public final class Items { public static final Item CAULDRON = register(new BlockItem("cauldron", builder())); public static final Item ENDER_EYE = register(new Item("ender_eye", builder())); public static final Item GLISTERING_MELON_SLICE = register(new Item("glistering_melon_slice", builder())); + public static final Item ARMADILLO_SPAWN_EGG = register(new SpawnEggItem("armadillo_spawn_egg", builder())); public static final Item ALLAY_SPAWN_EGG = register(new SpawnEggItem("allay_spawn_egg", builder())); public static final Item AXOLOTL_SPAWN_EGG = register(new SpawnEggItem("axolotl_spawn_egg", builder())); public static final Item BAT_SPAWN_EGG = register(new SpawnEggItem("bat_spawn_egg", builder())); public static final Item BEE_SPAWN_EGG = register(new SpawnEggItem("bee_spawn_egg", builder())); public static final Item BLAZE_SPAWN_EGG = register(new SpawnEggItem("blaze_spawn_egg", builder())); + public static final Item BOGGED_SPAWN_EGG = register(new SpawnEggItem("bogged_spawn_egg", builder())); public static final Item BREEZE_SPAWN_EGG = register(new SpawnEggItem("breeze_spawn_egg", builder())); public static final Item CAT_SPAWN_EGG = register(new SpawnEggItem("cat_spawn_egg", builder())); public static final Item CAMEL_SPAWN_EGG = register(new SpawnEggItem("camel_spawn_egg", builder())); @@ -1123,8 +1128,10 @@ public final class Items { public static final Item ZOMBIFIED_PIGLIN_SPAWN_EGG = register(new SpawnEggItem("zombified_piglin_spawn_egg", builder())); public static final Item EXPERIENCE_BOTTLE = register(new Item("experience_bottle", builder())); public static final Item FIRE_CHARGE = register(new Item("fire_charge", builder())); + public static final Item WIND_CHARGE = register(new Item("wind_charge", builder())); public static final Item WRITABLE_BOOK = register(new WritableBookItem("writable_book", builder().stackSize(1))); public static final Item WRITTEN_BOOK = register(new WrittenBookItem("written_book", builder().stackSize(16))); + public static final Item MACE = register(new MaceItem("mace", builder().stackSize(1).maxDamage(250))); public static final Item ITEM_FRAME = register(new Item("item_frame", builder())); public static final Item GLOW_ITEM_FRAME = register(new Item("glow_item_frame", builder())); public static final Item FLOWER_POT = register(new BlockItem("flower_pot", builder())); @@ -1155,10 +1162,10 @@ public final class Items { public static final Item RABBIT_FOOT = register(new Item("rabbit_foot", builder())); public static final Item RABBIT_HIDE = register(new Item("rabbit_hide", builder())); public static final Item ARMOR_STAND = register(new Item("armor_stand", builder().stackSize(16))); - public static final Item IRON_HORSE_ARMOR = register(new Item("iron_horse_armor", builder().stackSize(1))); - public static final Item GOLDEN_HORSE_ARMOR = register(new Item("golden_horse_armor", builder().stackSize(1))); - public static final Item DIAMOND_HORSE_ARMOR = register(new Item("diamond_horse_armor", builder().stackSize(1))); - public static final Item LEATHER_HORSE_ARMOR = register(new DyeableHorseArmorItem("leather_horse_armor", builder().stackSize(1))); + public static final Item IRON_HORSE_ARMOR = register(new ArmorItem("iron_horse_armor", ArmorMaterial.IRON, builder().stackSize(1))); + public static final Item GOLDEN_HORSE_ARMOR = register(new ArmorItem("golden_horse_armor", ArmorMaterial.GOLD, builder().stackSize(1))); + public static final Item DIAMOND_HORSE_ARMOR = register(new ArmorItem("diamond_horse_armor", ArmorMaterial.DIAMOND, builder().stackSize(1))); + public static final Item LEATHER_HORSE_ARMOR = register(new ArmorItem("leather_horse_armor", ArmorMaterial.LEATHER, builder().stackSize(1))); public static final Item LEAD = register(new Item("lead", builder())); public static final Item NAME_TAG = register(new Item("name_tag", builder())); public static final Item COMMAND_BLOCK_MINECART = register(new Item("command_block_minecart", builder().stackSize(1))); @@ -1216,7 +1223,7 @@ public final class Items { public static final Item MUSIC_DISC_5 = register(new Item("music_disc_5", builder().stackSize(1))); public static final Item MUSIC_DISC_PIGSTEP = register(new Item("music_disc_pigstep", builder().stackSize(1))); public static final Item DISC_FRAGMENT_5 = register(new Item("disc_fragment_5", builder())); - public static final Item TRIDENT = register(new Item("trident", builder().stackSize(1).attackDamage(9).maxDamage(250))); + public static final Item TRIDENT = register(new Item("trident", builder().stackSize(1).maxDamage(250).attackDamage(9.0))); public static final Item PHANTOM_MEMBRANE = register(new Item("phantom_membrane", builder())); public static final Item NAUTILUS_SHELL = register(new Item("nautilus_shell", builder())); public static final Item HEART_OF_THE_SEA = register(new Item("heart_of_the_sea", builder())); @@ -1229,6 +1236,8 @@ public final class Items { public static final Item MOJANG_BANNER_PATTERN = register(new Item("mojang_banner_pattern", builder().stackSize(1))); public static final Item GLOBE_BANNER_PATTERN = register(new Item("globe_banner_pattern", builder().stackSize(1))); public static final Item PIGLIN_BANNER_PATTERN = register(new Item("piglin_banner_pattern", builder().stackSize(1))); + public static final Item FLOW_BANNER_PATTERN = register(new Item("flow_banner_pattern", builder().stackSize(1))); + public static final Item GUSTER_BANNER_PATTERN = register(new Item("guster_banner_pattern", builder().stackSize(1))); public static final Item GOAT_HORN = register(new GoatHornItem("goat_horn", builder().stackSize(1))); public static final Item COMPOSTER = register(new BlockItem("composter", builder())); public static final Item BARREL = register(new ChestItem("barrel", builder())); @@ -1312,6 +1321,8 @@ public final class Items { public static final Item SILENCE_ARMOR_TRIM_SMITHING_TEMPLATE = register(new Item("silence_armor_trim_smithing_template", builder())); public static final Item RAISER_ARMOR_TRIM_SMITHING_TEMPLATE = register(new Item("raiser_armor_trim_smithing_template", builder())); public static final Item HOST_ARMOR_TRIM_SMITHING_TEMPLATE = register(new Item("host_armor_trim_smithing_template", builder())); + public static final Item FLOW_ARMOR_TRIM_SMITHING_TEMPLATE = register(new Item("flow_armor_trim_smithing_template", builder())); + public static final Item BOLT_ARMOR_TRIM_SMITHING_TEMPLATE = register(new Item("bolt_armor_trim_smithing_template", builder())); public static final Item ANGLER_POTTERY_SHERD = register(new Item("angler_pottery_sherd", builder())); public static final Item ARCHER_POTTERY_SHERD = register(new Item("archer_pottery_sherd", builder())); public static final Item ARMS_UP_POTTERY_SHERD = register(new Item("arms_up_pottery_sherd", builder())); @@ -1320,7 +1331,9 @@ public final class Items { public static final Item BURN_POTTERY_SHERD = register(new Item("burn_pottery_sherd", builder())); public static final Item DANGER_POTTERY_SHERD = register(new Item("danger_pottery_sherd", builder())); public static final Item EXPLORER_POTTERY_SHERD = register(new Item("explorer_pottery_sherd", builder())); + public static final Item FLOW_POTTERY_SHERD = register(new Item("flow_pottery_sherd", builder())); public static final Item FRIEND_POTTERY_SHERD = register(new Item("friend_pottery_sherd", builder())); + public static final Item GUSTER_POTTERY_SHERD = register(new Item("guster_pottery_sherd", builder())); public static final Item HEART_POTTERY_SHERD = register(new Item("heart_pottery_sherd", builder())); public static final Item HEARTBREAK_POTTERY_SHERD = register(new Item("heartbreak_pottery_sherd", builder())); public static final Item HOWL_POTTERY_SHERD = register(new Item("howl_pottery_sherd", builder())); @@ -1328,6 +1341,7 @@ public final class Items { public static final Item MOURNER_POTTERY_SHERD = register(new Item("mourner_pottery_sherd", builder())); public static final Item PLENTY_POTTERY_SHERD = register(new Item("plenty_pottery_sherd", builder())); public static final Item PRIZE_POTTERY_SHERD = register(new Item("prize_pottery_sherd", builder())); + public static final Item SCRAPE_POTTERY_SHERD = register(new Item("scrape_pottery_sherd", builder())); public static final Item SHEAF_POTTERY_SHERD = register(new Item("sheaf_pottery_sherd", builder())); public static final Item SHELTER_POTTERY_SHERD = register(new Item("shelter_pottery_sherd", builder())); public static final Item SKULL_POTTERY_SHERD = register(new Item("skull_pottery_sherd", builder())); @@ -1350,6 +1364,10 @@ public final class Items { public static final Item WAXED_OXIDIZED_COPPER_BULB = register(new BlockItem("waxed_oxidized_copper_bulb", builder())); public static final Item TRIAL_SPAWNER = register(new BlockItem("trial_spawner", builder())); public static final Item TRIAL_KEY = register(new Item("trial_key", builder())); + public static final Item OMINOUS_TRIAL_KEY = register(new Item("ominous_trial_key", builder())); + public static final Item VAULT = register(new BlockItem("vault", builder())); + public static final Item OMINOUS_BOTTLE = register(new Item("ominous_bottle", builder())); + public static final Item BREEZE_ROD = register(new Item("breeze_rod", builder())); public static final int AIR_ID = AIR.javaId(); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/MaceItem.java b/core/src/main/java/org/geysermc/geyser/item/type/MaceItem.java new file mode 100644 index 000000000..e7b9a8684 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/item/type/MaceItem.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2019-2024 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.item.type; + +import org.geysermc.geyser.item.Items; + +public class MaceItem extends Item { + public MaceItem(String javaIdentifier, Builder builder) { + super(javaIdentifier, builder); + } + + @Override + public boolean isValidRepairItem(Item other) { + return other == Items.BREEZE_ROD; + } +} diff --git a/core/src/main/java/org/geysermc/geyser/level/JavaDimension.java b/core/src/main/java/org/geysermc/geyser/level/JavaDimension.java index a3f6b55e4..6e7223da0 100644 --- a/core/src/main/java/org/geysermc/geyser/level/JavaDimension.java +++ b/core/src/main/java/org/geysermc/geyser/level/JavaDimension.java @@ -25,11 +25,12 @@ package org.geysermc.geyser.level; +import com.github.steveice10.mc.protocol.data.game.RegistryEntry; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.IntTag; -import org.geysermc.geyser.util.JavaCodecUtil; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import java.util.Map; +import java.util.List; /** * Represents the information we store from the current Java dimension @@ -38,19 +39,20 @@ import java.util.Map; */ public record JavaDimension(int minY, int maxY, boolean piglinSafe, double worldCoordinateScale) { - public static void load(CompoundTag tag, Map map) { - for (CompoundTag dimension : JavaCodecUtil.iterateAsTag(tag.get("minecraft:dimension_type"))) { - CompoundTag elements = dimension.get("element"); - int minY = ((IntTag) elements.get("min_y")).getValue(); - int maxY = ((IntTag) elements.get("height")).getValue(); + public static void load(List entries, Int2ObjectMap map) { + for (int i = 0; i < entries.size(); i++) { + RegistryEntry entry = entries.get(i); + CompoundTag dimension = entry.getData(); + int minY = ((IntTag) dimension.get("min_y")).getValue(); + int maxY = ((IntTag) dimension.get("height")).getValue(); // Logical height can be ignored probably - seems to be for artificial limits like the Nether. // Set if piglins/hoglins should shake - boolean piglinSafe = ((Number) elements.get("piglin_safe").getValue()).byteValue() != (byte) 0; + boolean piglinSafe = ((Number) dimension.get("piglin_safe").getValue()).byteValue() != (byte) 0; // Load world coordinate scale for the world border - double coordinateScale = ((Number) elements.get("coordinate_scale").getValue()).doubleValue(); + double coordinateScale = ((Number) dimension.get("coordinate_scale").getValue()).doubleValue(); - map.put((String) dimension.get("name").getValue(), new JavaDimension(minY, maxY, piglinSafe, coordinateScale)); + map.put(i, new JavaDimension(minY, maxY, piglinSafe, coordinateScale)); } } } diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java b/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java index a2951116f..121c70f90 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java @@ -79,7 +79,7 @@ public final class LocalSession extends TcpSession { public void initChannel(@NonNull LocalChannelWithRemoteAddress channel) { channel.spoofedRemoteAddress(new InetSocketAddress(clientIp, 0)); PacketProtocol protocol = getPacketProtocol(); - protocol.newClientSession(LocalSession.this); + protocol.newClientSession(LocalSession.this, false); refreshReadTimeoutHandler(channel); refreshWriteTimeoutHandler(channel); diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/EnchantmentRegistryLoader.java b/core/src/main/java/org/geysermc/geyser/registry/loader/EnchantmentRegistryLoader.java index 185eca694..8a0fb1f40 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/loader/EnchantmentRegistryLoader.java +++ b/core/src/main/java/org/geysermc/geyser/registry/loader/EnchantmentRegistryLoader.java @@ -56,13 +56,7 @@ public class EnchantmentRegistryLoader implements RegistryLoader entry = it.next(); JavaEnchantment key = JavaEnchantment.getByJavaIdentifier(entry.getKey()); JsonNode node = entry.getValue(); - int rarityMultiplier = switch (node.get("rarity").textValue()) { - case "common" -> 1; - case "uncommon" -> 2; - case "rare" -> 4; - case "very_rare" -> 8; - default -> throw new IllegalStateException("Unexpected value: " + node.get("rarity").textValue()); - }; + int rarityMultiplier = node.get("anvil_cost").asInt(); int maxLevel = node.get("max_level").asInt(); EnumSet incompatibleEnchantments = EnumSet.noneOf(JavaEnchantment.class); diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion649_630.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion649_630.java index 56de1081e..70a5e1ad9 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion649_630.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion649_630.java @@ -37,9 +37,11 @@ public class Conversion649_630 { String identifer = mapping.getBedrockIdentifier(); switch (identifer) { - case "minecraft:turtle_scute" -> { return mapping.withBedrockIdentifier("minecraft:scute"); } + case "minecraft:armadillo_scute", "minecraft:turtle_scute" -> { return mapping.withBedrockIdentifier("minecraft:scute"); } + case "minecraft:armadillo_spawn_egg" -> { return mapping.withBedrockIdentifier("minecraft:rabbit_spawn_egg"); } case "minecraft:trial_spawner" -> { return mapping.withBedrockIdentifier("minecraft:mob_spawner"); } case "minecraft:trial_key" -> { return mapping.withBedrockIdentifier("minecraft:echo_shard"); } + case "minecraft:wolf_armor" -> { return mapping.withBedrockIdentifier("minecraft:leather_horse_armor"); } default -> { return mapping; } } } diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion662_649.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion662_649.java index 0fe1610f2..041afdbc8 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion662_649.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion662_649.java @@ -35,7 +35,7 @@ import java.util.stream.Stream; public class Conversion662_649 { - private static final List NEW_MISC = List.of("minecraft:grass_block", "minecraft:trial_spawner"); + private static final List NEW_MISC = List.of("minecraft:grass_block", "minecraft:vault"); private static final List NEW_WOODS = List.of("minecraft:oak_wood", "minecraft:spruce_wood", "minecraft:birch_wood", "minecraft:jungle_wood", "minecraft:acacia_wood", "minecraft:dark_oak_wood", "minecraft:stripped_oak_wood", "minecraft:stripped_spruce_wood", "minecraft:stripped_birch_wood", "minecraft:stripped_jungle_wood", "minecraft:stripped_acacia_wood", "minecraft:stripped_dark_oak_wood"); private static final List NEW_LEAVES = List.of("minecraft:oak_leaves", "minecraft:spruce_leaves", "minecraft:birch_leaves", "minecraft:jungle_leaves"); private static final List NEW_LEAVES2 = List.of("minecraft:acacia_leaves", "minecraft:dark_oak_leaves"); @@ -48,9 +48,12 @@ public class Conversion662_649 { String identifer = mapping.getBedrockIdentifier(); - if (identifer.equals("minecraft:grass_block")) { - return mapping.withBedrockIdentifier("minecraft:grass"); - } + switch (identifer) { + case "minecraft:bogged_spawn_egg" -> { return mapping.withBedrockIdentifier("minecraft:creeper_spawn_egg"); } + case "minecraft:grass_block" -> { return mapping.withBedrockIdentifier("minecraft:grass"); } + case "minecraft:vault" -> { return mapping.withBedrockIdentifier("minecraft:trial_spawner"); } + case "minecraft:wind_charge" -> { return mapping.withBedrockIdentifier("minecraft:snowball"); } + }; if (NEW_WOODS.contains(identifer)) { switch (identifer) { @@ -114,6 +117,19 @@ public class Conversion662_649 { return builder.build(); } + if (name.equals("minecraft:vault")) { + replacement = "minecraft:trial_spawner"; + + NbtMapBuilder statesBuilder = NbtMap.builder() + .putInt("trial_spawner_state", 0); + + NbtMapBuilder builder = tag.toBuilder(); + builder.putString("name", replacement); + builder.putCompound("states", statesBuilder.build()); + + return builder.build(); + } + if (NEW_WOODS.contains(name)) { replacement = "minecraft:wood"; diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion671_662.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion671_662.java index 2c6db7567..29ab3f2e5 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion671_662.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion671_662.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.registry.populator; import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.registry.type.GeyserMappingItem; @@ -33,11 +34,12 @@ import java.util.List; import java.util.stream.Stream; public class Conversion671_662 { + private static final List NEW_MISC = List.of("minecraft:heavy_core", "minecraft:mace", "minecraft:flow_banner_pattern", "minecraft:guster_banner_pattern", "minecraft:flow_armor_trim_smithing_template", "minecraft:bolt_armor_trim_smithing_template", "minecraft:flow_pottery_sherd", "minecraft:guster_pottery_sherd", "minecraft:scrape_pottery_sherd", "minecraft:breeze_rod"); private static final List NEW_CORAL_FANS = List.of("minecraft:tube_coral_fan", "minecraft:brain_coral_fan", "minecraft:bubble_coral_fan", "minecraft:fire_coral_fan", "minecraft:horn_coral_fan"); private static final List NEW_DEAD_CORAL_FANS = List.of("minecraft:dead_tube_coral_fan", "minecraft:dead_brain_coral_fan", "minecraft:dead_bubble_coral_fan", "minecraft:dead_fire_coral_fan", "minecraft:dead_horn_coral_fan"); private static final List NEW_FLOWERS = List.of("minecraft:poppy", "minecraft:blue_orchid", "minecraft:allium", "minecraft:azure_bluet", "minecraft:red_tulip", "minecraft:orange_tulip", "minecraft:white_tulip", "minecraft:pink_tulip", "minecraft:oxeye_daisy", "minecraft:cornflower", "minecraft:lily_of_the_valley"); private static final List NEW_SAPLINGS = List.of("minecraft:oak_sapling", "minecraft:spruce_sapling", "minecraft:birch_sapling", "minecraft:jungle_sapling", "minecraft:acacia_sapling", "minecraft:dark_oak_sapling", "minecraft:bamboo_sapling"); - private static final List NEW_BLOCKS = Stream.of(NEW_CORAL_FANS, NEW_DEAD_CORAL_FANS, NEW_FLOWERS, NEW_SAPLINGS).flatMap(List::stream).toList(); + private static final List NEW_BLOCKS = Stream.of(NEW_MISC, NEW_CORAL_FANS, NEW_DEAD_CORAL_FANS, NEW_FLOWERS, NEW_SAPLINGS).flatMap(List::stream).toList(); static GeyserMappingItem remapItem(@SuppressWarnings("unused") Item item, GeyserMappingItem mapping) { String identifer = mapping.getBedrockIdentifier(); @@ -46,6 +48,18 @@ public class Conversion671_662 { return mapping; } + switch (identifer) { + case "minecraft:bolt_armor_trim_smithing_template" -> { return mapping.withBedrockIdentifier("minecraft:wayfinder_armor_trim_smithing_template"); } + case "minecraft:breeze_rod" -> { return mapping.withBedrockIdentifier("minecraft:blaze_rod"); } + case "minecraft:flow_armor_trim_smithing_template" -> { return mapping.withBedrockIdentifier("minecraft:spire_armor_trim_smithing_template"); } + case "minecraft:flow_banner_pattern", "minecraft:guster_banner_pattern" -> { return mapping.withBedrockIdentifier("minecraft:globe_banner_pattern"); } + case "minecraft:flow_pottery_sherd" -> { return mapping.withBedrockIdentifier("minecraft:skull_pottery_sherd"); } + case "minecraft:guster_pottery_sherd" -> { return mapping.withBedrockIdentifier("minecraft:shelter_pottery_sherd"); } + case "minecraft:scrape_pottery_sherd" -> { return mapping.withBedrockIdentifier("minecraft:heartbreak_pottery_sherd"); } + case "minecraft:heavy_core" -> { return mapping.withBedrockIdentifier("minecraft:conduit"); } + case "minecraft:mace" -> { return mapping.withBedrockIdentifier("minecraft:netherite_axe"); } + } + if (NEW_FLOWERS.contains(identifer)) { switch (identifer) { case "minecraft:poppy" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(0); } @@ -114,6 +128,15 @@ public class Conversion671_662 { String replacement; + if (name.equals("minecraft:heavy_core")) { + replacement = "minecraft:conduit"; + + NbtMapBuilder builder = tag.toBuilder(); + builder.putString("name", replacement); + + return builder.build(); + } + if (NEW_SAPLINGS.contains(name)) { replacement = "minecraft:sapling"; String saplingType = name.replaceAll("minecraft:|_sapling", "");; diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 63022636c..936fc932d 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -45,6 +45,7 @@ import com.github.steveice10.mc.protocol.data.game.statistic.Statistic; import com.github.steveice10.mc.protocol.packet.common.serverbound.ServerboundClientInformationPacket; import com.github.steveice10.mc.protocol.packet.handshake.serverbound.ClientIntentionPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatCommandPacket; +import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatCommandSignedPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundPlayerAbilitiesPacket; @@ -360,7 +361,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { * As all entities are in the same world, this can be safely applied to all other entities. */ @Setter - private String dimension = DimensionUtils.OVERWORLD; + private int dimension = DimensionUtils.OVERWORLD; @MonotonicNonNull @Setter private JavaDimension dimensionType = null; @@ -1464,7 +1465,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { * Sends a command to the Java server. */ public void sendCommand(String command) { - sendDownstreamGamePacket(new ServerboundChatCommandPacket(command, Instant.now().toEpochMilli(), 0L, Collections.emptyList(), 0, new BitSet())); + sendDownstreamGamePacket(new ServerboundChatCommandSignedPacket(command, Instant.now().toEpochMilli(), 0L, Collections.emptyList(), 0, new BitSet())); } public void setServerRenderDistance(int renderDistance) { diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java index 429b577ce..b461c7afc 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java @@ -360,7 +360,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { return rejectRequest(request); } - ServerboundSetCreativeModeSlotPacket creativeDropPacket = new ServerboundSetCreativeModeSlotPacket(-1, sourceItem.getItemStack(dropAction.getCount())); + ServerboundSetCreativeModeSlotPacket creativeDropPacket = new ServerboundSetCreativeModeSlotPacket((short)-1, sourceItem.getItemStack(dropAction.getCount())); session.sendDownstreamGamePacket(creativeDropPacket); sourceItem.sub(dropAction.getCount()); @@ -493,9 +493,9 @@ public class PlayerInventoryTranslator extends InventoryTranslator { dropStack = javaCreativeItem; } else { // Specify custom count - dropStack = new ItemStack(javaCreativeItem.getId(), dropAction.getCount(), javaCreativeItem.getNbt()); + dropStack = new ItemStack(javaCreativeItem.getId(), dropAction.getCount(), javaCreativeItem.getDataComponents()); } - ServerboundSetCreativeModeSlotPacket creativeDropPacket = new ServerboundSetCreativeModeSlotPacket(-1, dropStack); + ServerboundSetCreativeModeSlotPacket creativeDropPacket = new ServerboundSetCreativeModeSlotPacket((short)-1, dropStack); session.sendDownstreamGamePacket(creativeDropPacket); break; } @@ -516,7 +516,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { GeyserItemStack item = inventory.getItem(slot); ItemStack itemStack = item.isEmpty() ? new ItemStack(-1, 0, null) : item.getItemStack(); - ServerboundSetCreativeModeSlotPacket creativePacket = new ServerboundSetCreativeModeSlotPacket(slot, itemStack); + ServerboundSetCreativeModeSlotPacket creativePacket = new ServerboundSetCreativeModeSlotPacket((short)slot, itemStack); session.sendDownstreamGamePacket(creativePacket); } 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 90ac1cc5e..d4288c5a7 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 @@ -25,15 +25,13 @@ package org.geysermc.geyser.translator.level; +import com.github.steveice10.mc.protocol.data.game.RegistryEntry; import com.github.steveice10.mc.protocol.data.game.chunk.BitStorage; import com.github.steveice10.mc.protocol.data.game.chunk.DataPalette; import com.github.steveice10.mc.protocol.data.game.chunk.palette.GlobalPalette; import com.github.steveice10.mc.protocol.data.game.chunk.palette.Palette; import com.github.steveice10.mc.protocol.data.game.chunk.palette.SingletonPalette; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.IntTag; -import com.github.steveice10.opennbt.tag.builtin.ListTag; -import com.github.steveice10.opennbt.tag.builtin.StringTag; import it.unimi.dsi.fastutil.ints.*; import org.geysermc.geyser.level.chunk.BlockStorage; import org.geysermc.geyser.level.chunk.bitarray.BitArray; @@ -41,24 +39,24 @@ import org.geysermc.geyser.level.chunk.bitarray.BitArrayVersion; import org.geysermc.geyser.level.chunk.bitarray.SingletonBitArray; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.util.JavaCodecUtil; import org.geysermc.geyser.util.MathUtils; +import java.util.List; + // Array index formula by https://wiki.vg/Chunk_Format public class BiomeTranslator { - public static void loadServerBiomes(GeyserSession session, CompoundTag codec) { + public static void loadServerBiomes(GeyserSession session, List entries) { Int2IntMap biomeTranslations = new Int2IntOpenHashMap(); - CompoundTag worldGen = codec.get("minecraft:worldgen/biome"); - ListTag serverBiomes = worldGen.get("value"); - session.setBiomeGlobalPalette(MathUtils.getGlobalPaletteForSize(serverBiomes.size())); + session.setBiomeGlobalPalette(MathUtils.getGlobalPaletteForSize(entries.size())); int greatestBiomeId = 0; - for (CompoundTag biomeTag : JavaCodecUtil.iterateAsTag(worldGen)) { - String javaIdentifier = ((StringTag) biomeTag.get("name")).getValue(); + for (int i = 0; i < entries.size(); i++) { + RegistryEntry entry = entries.get(i); + String javaIdentifier = entry.getId(); int bedrockId = Registries.BIOME_IDENTIFIERS.get().getOrDefault(javaIdentifier, 0); - int javaId = ((IntTag) biomeTag.get("id")).getValue(); + int javaId = i; if (javaId > greatestBiomeId) { greatestBiomeId = javaId; } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCommandsTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCommandsTranslator.java index 0d7f45c7d..9d3351217 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCommandsTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCommandsTranslator.java @@ -60,7 +60,7 @@ import java.util.*; public class JavaCommandsTranslator extends PacketTranslator { private static final String[] ALL_EFFECT_IDENTIFIERS = EntityUtils.getAllEffectIdentifiers(); - private static final String[] ATTRIBUTES = AttributeType.Builtin.BUILTIN.keySet().toArray(new String[0]); + private static final String[] ATTRIBUTES = AttributeType.Builtin.BUILTIN.values().stream().map(AttributeType::getIdentifier).toList().toArray(new String[0]); private static final String[] ENUM_BOOLEAN = {"true", "false"}; private static final String[] VALID_COLORS; private static final String[] VALID_SCOREBOARD_SLOTS; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java index 4a15157f9..ebf99fb65 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java @@ -63,7 +63,7 @@ public class JavaLoginTranslator extends PacketTranslator { @Override public void translate(GeyserSession session, ClientboundRegistryDataPacket packet) { - Map dimensions = session.getDimensions(); - dimensions.clear(); - JavaDimension.load(packet.getRegistry(), dimensions); - - Int2ObjectMap chatTypes = session.getChatTypes(); - chatTypes.clear(); - for (CompoundTag tag : JavaCodecUtil.iterateAsTag(packet.getRegistry().get("minecraft:chat_type"))) { - // The ID is NOT ALWAYS THE SAME! ViaVersion as of 1.19 adds two registry entries that do NOT match vanilla. - int id = ((IntTag) tag.get("id")).getValue(); - CompoundTag element = tag.get("element"); - CompoundTag chat = element.get("chat"); - TextDecoration textDecoration = null; - if (chat != null) { - textDecoration = new TextDecoration(chat); - } - chatTypes.put(id, textDecoration); + if (packet.getRegistry().equals("minecraft:dimension_type")) { + Int2ObjectMap dimensions = session.getDimensions(); + dimensions.clear(); + JavaDimension.load(packet.getEntries(), dimensions); } - BiomeTranslator.loadServerBiomes(session, packet.getRegistry()); + if (packet.getRegistry().equals("minecraft:chat_type")) { + Int2ObjectMap chatTypes = session.getChatTypes(); + chatTypes.clear(); + List entries = packet.getEntries(); + for (int i = 0; i < entries.size(); i++) { + // The ID is NOT ALWAYS THE SAME! ViaVersion as of 1.19 adds two registry entries that do NOT match vanilla. + RegistryEntry entry = entries.get(i); + CompoundTag tag = entry.getData(); + CompoundTag chat = tag.get("chat"); + TextDecoration textDecoration = null; + if (chat != null) { + textDecoration = new TextDecoration(chat); + } + chatTypes.put(i, textDecoration); + } + } + + if (packet.getRegistry().equals("minecraft:worldgen/biome")) { + BiomeTranslator.loadServerBiomes(session, packet.getEntries()); + } } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaRespawnTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaRespawnTranslator.java index d69077dcb..bfb590247 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaRespawnTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaRespawnTranslator.java @@ -92,11 +92,11 @@ public class JavaRespawnTranslator extends PacketTranslator { - int blockState = session.getBlockMappings().getBedrockBlockId(((FallingDustParticleData) particle.getData()).getBlockState()); + int blockState = session.getBlockMappings().getBedrockBlockId(((BlockParticleData) particle.getData()).getBlockState()); return (position) -> { LevelEventPacket packet = new LevelEventPacket(); // In fact, FallingDustParticle should have data like DustParticle, diff --git a/core/src/main/java/org/geysermc/geyser/util/AttributeUtils.java b/core/src/main/java/org/geysermc/geyser/util/AttributeUtils.java index e1fe6e6f2..d79d606b4 100644 --- a/core/src/main/java/org/geysermc/geyser/util/AttributeUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/AttributeUtils.java @@ -45,12 +45,12 @@ public class AttributeUtils { } double value = base; for (AttributeModifier modifier : attribute.getModifiers()) { - if (modifier.getOperation() == ModifierOperation.ADD_MULTIPLIED) { + if (modifier.getOperation() == ModifierOperation.ADD_MULTIPLIED_BASE) { value += base * modifier.getAmount(); } } for (AttributeModifier modifier : attribute.getModifiers()) { - if (modifier.getOperation() == ModifierOperation.MULTIPLY) { + if (modifier.getOperation() == ModifierOperation.ADD_MULTIPLIED_TOTAL) { value *= 1.0D + modifier.getAmount(); } } diff --git a/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java b/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java index eaa7b5084..469accd40 100644 --- a/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java @@ -50,19 +50,19 @@ public class DimensionUtils { /** * String reference to vanilla Java overworld dimension identifier */ - public static final String OVERWORLD = "minecraft:overworld"; + public static final int OVERWORLD = 0; /** * String reference to vanilla Java nether dimension identifier */ - public static final String NETHER = "minecraft:the_nether"; + public static final int NETHER = 3; /** * String reference to vanilla Java end dimension identifier */ - public static final String THE_END = "minecraft:the_end"; + public static final int THE_END = 2; - public static void switchDimension(GeyserSession session, String javaDimension) { + public static void switchDimension(GeyserSession session, int javaDimension) { int bedrockDimension = javaToBedrock(javaDimension); // new bedrock dimension - String previousDimension = session.getDimension(); // previous java dimension + int previousDimension = session.getDimension(); // previous java dimension Entity player = session.getPlayerEntity(); @@ -142,15 +142,15 @@ public class DimensionUtils { // we check if the player is entering the nether and apply the nether fog to fake the fact that the client // thinks they are in the end dimension. if (isCustomBedrockNetherId()) { - if (NETHER.equals(javaDimension)) { + if (NETHER == javaDimension) { session.camera().sendFog(BEDROCK_FOG_HELL); - } else if (NETHER.equals(previousDimension)) { + } else if (NETHER == previousDimension) { session.camera().removeFog(BEDROCK_FOG_HELL); } } } - public static void setBedrockDimension(GeyserSession session, String javaDimension) { + public static void setBedrockDimension(GeyserSession session, int javaDimension) { session.getChunkCache().setBedrockDimension(switch (javaDimension) { case DimensionUtils.THE_END -> BedrockDimension.THE_END; case DimensionUtils.NETHER -> DimensionUtils.isCustomBedrockNetherId() ? BedrockDimension.THE_END : BedrockDimension.THE_NETHER; @@ -174,7 +174,7 @@ public class DimensionUtils { * @param javaDimension Dimension ID to convert * @return Converted Bedrock edition dimension ID */ - public static int javaToBedrock(String javaDimension) { + public static int javaToBedrock(int javaDimension) { return switch (javaDimension) { case NETHER -> BEDROCK_NETHER_ID; case THE_END -> 2; @@ -182,6 +182,20 @@ public class DimensionUtils { }; } + /** + * Map the Java edition dimension IDs to Bedrock edition + * + * @param javaDimension Dimension ID to convert + * @return Converted Bedrock edition dimension ID + */ + public static int javaToBedrock(String javaDimension) { + return switch (javaDimension) { + case "minecraft:the_nether" -> BEDROCK_NETHER_ID; + case "minecraft:the_end" -> 2; + default -> 0; + }; + } + /** * The Nether dimension in Bedrock does not permit building above Y128 - the Bedrock above the dimension. * This workaround sets the Nether as the End dimension to ignore this limit. @@ -201,7 +215,7 @@ public class DimensionUtils { * @param newDimension the new dimension that the player will be transferred to * @return the fake dimension to transfer to */ - public static String getTemporaryDimension(String currentDimension, String newDimension) { + public static int getTemporaryDimension(int currentDimension, int newDimension) { if (isCustomBedrockNetherId()) { // Prevents rare instances of Bedrock locking up return javaToBedrock(newDimension) == 2 ? OVERWORLD : NETHER; diff --git a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java index e56aea8c9..7f3a02df6 100644 --- a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java @@ -27,6 +27,7 @@ package org.geysermc.geyser.util; import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundPickItemPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundSetCreativeModeSlotPacket; @@ -66,6 +67,7 @@ import org.jetbrains.annotations.Contract; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.Objects; import java.util.concurrent.TimeUnit; import java.util.function.IntFunction; @@ -77,7 +79,7 @@ public class InventoryUtils { */ public static int LAST_RECIPE_NET_ID; - public static final ItemStack REFRESH_ITEM = new ItemStack(1, 127, new CompoundTag("")); + public static final ItemStack REFRESH_ITEM = new ItemStack(1, 127, new DataComponents(new HashMap<>())); public static void openInventory(GeyserSession session, Inventory inventory) { session.setOpenInventory(inventory); @@ -279,7 +281,7 @@ public class InventoryUtils { if (session.getGameMode() == GameMode.CREATIVE) { int slot = findEmptyHotbarSlot(inventory); - ServerboundSetCreativeModeSlotPacket actionPacket = new ServerboundSetCreativeModeSlotPacket(slot, + ServerboundSetCreativeModeSlotPacket actionPacket = new ServerboundSetCreativeModeSlotPacket((short) slot, itemStack); if ((slot - 36) != inventory.getHeldItemSlot()) { setHotbarItem(session, slot); @@ -345,7 +347,7 @@ public class InventoryUtils { ItemMapping mapping = session.getItemMappings().getMapping(itemName); // TODO if (mapping != null) { - ServerboundSetCreativeModeSlotPacket actionPacket = new ServerboundSetCreativeModeSlotPacket(slot, + ServerboundSetCreativeModeSlotPacket actionPacket = new ServerboundSetCreativeModeSlotPacket((short)slot, new ItemStack(mapping.getJavaItem().javaId())); if ((slot - 36) != inventory.getHeldItemSlot()) { setHotbarItem(session, slot); diff --git a/core/src/main/java/org/geysermc/geyser/util/JavaCodecUtil.java b/core/src/main/java/org/geysermc/geyser/util/JavaCodecUtil.java deleted file mode 100644 index 795d45490..000000000 --- a/core/src/main/java/org/geysermc/geyser/util/JavaCodecUtil.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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.util; - -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.ListTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; -import org.checkerframework.checker.nullness.qual.NonNull; - -import java.util.Iterator; - -public final class JavaCodecUtil { - - /** - * Iterate over a Java Edition codec and return each entry as a CompoundTag - */ - public static Iterable iterateAsTag(CompoundTag tag) { - ListTag value = tag.get("value"); - Iterator originalIterator = value.iterator(); - return new Iterable<>() { - @NonNull - @Override - public Iterator iterator() { - return new Iterator<>() { - @Override - public boolean hasNext() { - return originalIterator.hasNext(); - } - - @Override - public CompoundTag next() { - return (CompoundTag) originalIterator.next(); - } - }; - } - }; - } - - private JavaCodecUtil() { - } -} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2d32159f0..e9fadb577 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ protocol-connection = "3.0.0.Beta1-20240411.165033-128" raknet = "1.0.0.CR3-20240416.144209-1" blockstateupdater="1.20.80-20240411.142413-1" mcauthlib = "d9d773e" -mcprotocollib = "1.20.4-2-20240116.220521-7" +mcprotocollib = "b2e93c520a" # Revert from jitpack after release adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" @@ -107,7 +107,7 @@ guava = { group = "com.google.guava", name = "guava", version.ref = "guava" } gson = { group = "com.google.code.gson", name = "gson", version.ref = "gson" } junit = { group = "org.junit.jupiter", name = "junit-jupiter", version.ref = "junit" } mcauthlib = { group = "com.github.GeyserMC", name = "MCAuthLib", version.ref = "mcauthlib" } -mcprotocollib = { group = "com.github.steveice10", name = "mcprotocollib", version.ref = "mcprotocollib" } +mcprotocollib = { group = "com.github.geysermc", name = "mcprotocollib", version.ref = "mcprotocollib" } raknet = { group = "org.cloudburstmc.netty", name = "netty-transport-raknet", version.ref = "raknet" } terminalconsoleappender = { group = "net.minecrell", name = "terminalconsoleappender", version.ref = "terminalconsoleappender" } velocity-api = { group = "com.velocitypowered", name = "velocity-api", version.ref = "velocity" } From aed7f1bed73b6eab4e7c70be597c4c15a5767db8 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sat, 20 Apr 2024 19:20:00 -0400 Subject: [PATCH 260/344] Update the item parts --- .../geyser/item/type/CompassItem.java | 8 +-- .../geyser/item/type/FilledMapItem.java | 10 ++-- .../geyser/item/type/FireworkRocketItem.java | 45 ++++++++--------- .../geyser/item/type/FireworkStarItem.java | 23 ++++----- .../geyser/item/type/FishingRodItem.java | 8 +-- .../geyser/item/type/GoatHornItem.java | 15 ++++-- .../org/geysermc/geyser/item/type/Item.java | 16 +++--- .../geysermc/geyser/item/type/MapItem.java | 15 +++--- .../geyser/item/type/PlayerHeadItem.java | 49 +++++++------------ .../geysermc/geyser/item/type/PotionItem.java | 18 +++---- .../geyser/item/type/ShulkerBoxItem.java | 2 +- .../geyser/item/type/TippedArrowItem.java | 9 ++-- .../item/type/TropicalFishBucketItem.java | 7 +-- .../geyser/item/type/WritableBookItem.java | 26 +++++----- .../geyser/item/type/WrittenBookItem.java | 41 +++++++++------- .../translator/item/BedrockItemBuilder.java | 27 ++++++++++ .../translator/item/ItemTranslator.java | 6 +-- 17 files changed, 171 insertions(+), 154 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java b/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java index 8d48d1307..10c574d5d 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java @@ -43,11 +43,11 @@ public class CompassItem extends Item { } @Override - public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { - if (isLodestoneCompass(itemStack.getDataComponents())) { - return super.translateToBedrock(itemStack, mappings.getLodestoneCompass(), mappings); + public ItemData.Builder translateToBedrock(int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) { + if (isLodestoneCompass(components)) { + return super.translateToBedrock(count, components, mappings.getLodestoneCompass(), mappings); } - return super.translateToBedrock(itemStack, mapping, mappings); + return super.translateToBedrock(count, components, mapping, mappings); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/item/type/FilledMapItem.java b/core/src/main/java/org/geysermc/geyser/item/type/FilledMapItem.java index 78a175f8d..af0b84308 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/FilledMapItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/FilledMapItem.java @@ -25,10 +25,8 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; @@ -39,12 +37,12 @@ public class FilledMapItem extends MapItem { } @Override - public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { - ItemData.Builder builder = super.translateToBedrock(itemStack, mapping, mappings); - DataComponents components = itemStack.getDataComponents(); + public ItemData.Builder translateToBedrock(int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) { + ItemData.Builder builder = super.translateToBedrock(count, components, mapping, mappings); if (components == null) { // This is a fallback for maps with no nbt (Change added back in June 2020; is it needed in 2023?) - return builder.tag(NbtMap.builder().putInt("map", 0).build()); + //return builder.tag(NbtMap.builder().putInt("map", 0).build()); TODO if this is *still* broken, let's move it to translateComponentsToBedrock + return builder; } else { Integer mapColor = components.get(DataComponentType.MAP_COLOR); if (mapColor != null) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java b/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java index d688e59f6..afb848e2d 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java @@ -32,6 +32,7 @@ import com.github.steveice10.opennbt.tag.builtin.*; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; +import org.cloudburstmc.nbt.NbtType; import org.geysermc.geyser.level.FireworkColor; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; @@ -63,9 +64,10 @@ public class FireworkRocketItem extends Item { } List explosionNbt = new ArrayList<>(); for (Fireworks.FireworkExplosion explosion : explosions) { - explosionNbt.add(translateExplosionToBedrock(explosion, "")); + explosionNbt.add(translateExplosionToBedrock(explosion)); } - + fireworksNbt.putList("Explosions", NbtType.COMPOUND, explosionNbt); + builder.putCompound("Fireworks", fireworksNbt.build()); } @Override @@ -73,39 +75,34 @@ public class FireworkRocketItem extends Item { super.translateNbtToJava(tag, mapping); } - static NbtMap translateExplosionToBedrock(Fireworks.FireworkExplosion explosion, String newName) { + static NbtMap translateExplosionToBedrock(Fireworks.FireworkExplosion explosion) { NbtMapBuilder newExplosionData = NbtMap.builder(); - if (explosion.get("Type") != null) { - newExplosionData.put(new ByteTag("FireworkType", MathUtils.getNbtByte(explosion.get("Type").getValue()))); - } +// if (explosion.get("Type") != null) { +// newExplosionData.put(new ByteTag("FireworkType", MathUtils.getNbtByte(explosion.get("Type").getValue()))); +// } //newExplosionData.putByte("FireworkType", explosion.get) //TODO??? - // TODO do we need length checks - if (explosion.get("Colors") != null) { - int[] oldColors = (int[]) explosion.get("Colors").getValue(); - byte[] colors = new byte[oldColors.length]; + int[] oldColors = explosion.getColors(); + byte[] colors = new byte[oldColors.length]; - int i = 0; - for (int color : oldColors) { - colors[i++] = FireworkColor.fromJavaRGB(color); - } - - newExplosionData.put(new ByteArrayTag("FireworkColor", colors)); + int i = 0; + for (int color : oldColors) { + colors[i++] = FireworkColor.fromJavaRGB(color); } - if (explosion.get("FadeColors") != null) { - int[] oldColors = (int[]) explosion.get("FadeColors").getValue(); - byte[] colors = new byte[oldColors.length]; + newExplosionData.putByteArray("FireworkColor", colors); - int i = 0; - for (int color : oldColors) { - colors[i++] = FireworkColor.fromJavaRGB(color); - } + oldColors = explosion.getFadeColors(); + colors = new byte[oldColors.length]; - newExplosionData.put(new ByteArrayTag("FireworkFade", colors)); + i = 0; + for (int color : oldColors) { + colors[i++] = FireworkColor.fromJavaRGB(color); } + newExplosionData.putByteArray("FireworkFade", colors); + newExplosionData.putBoolean("FireworkTrail", explosion.isHasTrail()); newExplosionData.putBoolean("FireworkFlicker", explosion.isHasTwinkle()); // TODO verify diff --git a/core/src/main/java/org/geysermc/geyser/item/type/FireworkStarItem.java b/core/src/main/java/org/geysermc/geyser/item/type/FireworkStarItem.java index 4ae9c8b13..505296418 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/FireworkStarItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/FireworkStarItem.java @@ -25,12 +25,13 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; +import com.github.steveice10.mc.protocol.data.game.item.component.Fireworks; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.IntArrayTag; -import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.nbt.NbtMap; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; @@ -44,19 +45,15 @@ public class FireworkStarItem extends Item { public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); - Tag explosion = tag.remove("Explosion"); - if (explosion instanceof CompoundTag) { - CompoundTag newExplosion = FireworkRocketItem.translateExplosionToBedrock((CompoundTag) explosion, "FireworksItem"); - tag.put(newExplosion); - Tag color = ((CompoundTag) explosion).get("Colors"); - if (color instanceof IntArrayTag) { + Fireworks.FireworkExplosion explosion = components.get(DataComponentType.FIREWORK_EXPLOSION); + if (explosion != null) { + NbtMap newExplosion = FireworkRocketItem.translateExplosionToBedrock(explosion); + builder.putCompound("FireworksItem", newExplosion); + int[] colors = explosion.getColors(); + if (colors.length != 0) { // Determine the custom color, if any. // Mostly replicates Java's own rendering code, as Java determines the final firework star color client-side // while Bedrock determines it server-side. - int[] colors = ((IntArrayTag) color).getValue(); - if (colors.length == 0) { - return; - } int finalColor; if (colors.length == 1) { finalColor = colors[0]; @@ -77,7 +74,7 @@ public class FireworkStarItem extends Item { finalColor = r << 16 | g << 8 | b; } - tag.put(new IntTag("customColor", finalColor)); + builder.putInt("customColor", finalColor); } } } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/FishingRodItem.java b/core/src/main/java/org/geysermc/geyser/item/type/FishingRodItem.java index 4538689da..743928482 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/FishingRodItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/FishingRodItem.java @@ -26,8 +26,6 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.opennbt.tag.builtin.IntTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; @@ -42,11 +40,7 @@ public class FishingRodItem extends Item { super.translateComponentsToBedrock(session, components, builder); // Fix damage inconsistency - Tag damage = tag.get("Damage"); - if (damage instanceof IntTag) { - int originalDurability = ((IntTag) damage).getValue(); - tag.put(new IntTag("Damage", getBedrockDamage(originalDurability))); - } + builder.getDamage().ifPresent(damage -> builder.setDamage(getBedrockDamage(damage))); } public static int getBedrockDamage(int javaDamage) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java b/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java index 60b201961..20f9782df 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java @@ -26,6 +26,9 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.item.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; +import com.github.steveice10.mc.protocol.data.game.item.component.Instrument; import com.github.steveice10.opennbt.tag.builtin.StringTag; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; @@ -52,10 +55,14 @@ public class GoatHornItem extends Item { } @Override - public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { - ItemData.Builder builder = super.translateToBedrock(itemStack, mapping, mappings); - if (itemStack.getNbt() != null && itemStack.getNbt().get("instrument") instanceof StringTag instrumentTag) { - String instrument = instrumentTag.getValue(); + public ItemData.Builder translateToBedrock(int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) { + ItemData.Builder builder = super.translateToBedrock(count, components, mapping, mappings); + if (components == null) { + return builder; + } + Instrument instrument = components.get(DataComponentType.INSTRUMENT); + // TODO registry + if (instrument != null) { // Drop the Minecraft namespace if applicable if (instrument.startsWith("minecraft:")) { instrument = instrument.substring("minecraft:".length()); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/Item.java b/core/src/main/java/org/geysermc/geyser/item/type/Item.java index decc60da8..e2822ea7a 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/Item.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/Item.java @@ -39,6 +39,7 @@ import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.inventory.item.Enchantment; +import org.geysermc.geyser.item.Items; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.session.GeyserSession; @@ -93,20 +94,16 @@ public class Item { /* Translation methods to Bedrock and back */ - public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { - if (InventoryUtils.isEmpty(itemStack)) { + public ItemData.Builder translateToBedrock(int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) { + if (this == Items.AIR || count <= 0) { // Return, essentially, air return ItemData.builder(); } ItemData.Builder builder = ItemData.builder() .definition(mapping.getBedrockDefinition()) .damage(mapping.getBedrockData()) - .count(itemStack.getAmount()); - if (itemStack.getDataComponents() != null) { - builder.tag(ItemTranslator.translateNbtToBedrock(itemStack.getDataComponents())); - } + .count(count); - DataComponents components = itemStack.getDataComponents(); ItemTranslator.translateCustomItem(components, builder, mapping); return builder; @@ -135,6 +132,11 @@ public class Item { } } + Integer damage = components.get(DataComponentType.DAMAGE); + if (damage != null) { + builder.setDamage(damage); + } + List newTags = new ArrayList<>(); ItemEnchantments enchantments = components.get(DataComponentType.ENCHANTMENTS); if (enchantments != null) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java b/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java index b015862c5..72014e15e 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.*; import org.checkerframework.checker.nullness.qual.NonNull; @@ -41,14 +42,14 @@ public class MapItem extends Item { public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); - Tag mapId = tag.remove("map"); - if (mapId == null || !(mapId.getValue() instanceof Number number)) return; + Integer mapValue = components.get(DataComponentType.MAP_ID); + if (mapValue == null) { + return; + } - int mapValue = number.intValue(); - - tag.put(new LongTag("map_uuid", mapValue)); - tag.put(new IntTag("map_name_index", mapValue)); - tag.put(new ByteTag("map_display_players", (byte) 1)); + builder.putLong("map_uuid", mapValue); + builder.putInt("map_name_index", mapValue); + builder.putByte("map_display_players", (byte) 1); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java b/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java index dae444775..82219d7d9 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java @@ -25,16 +25,14 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.auth.data.GameProfile; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -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 org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.translator.item.BedrockItemBuilder; -import org.geysermc.geyser.translator.text.MessageTranslator; public class PlayerHeadItem extends Item { public PlayerHeadItem(String javaIdentifier, Builder builder) { @@ -45,35 +43,24 @@ public class PlayerHeadItem extends Item { public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); - CompoundTag displayTag; - if (tag.get("display") instanceof CompoundTag existingDisplayTag) { - displayTag = existingDisplayTag; - } else { - displayTag = new CompoundTag("display"); - tag.put(displayTag); - } - - if (displayTag.get("Name") instanceof StringTag nameTag) { - // Custom names are always yellow and italic - displayTag.put(new StringTag("Name", ChatColor.YELLOW + ChatColor.ITALIC + MessageTranslator.convertMessageLenient(nameTag.getValue(), session.locale()))); - } else { - if (tag.contains("SkullOwner")) { - StringTag name; - Tag skullOwner = tag.get("SkullOwner"); - if (skullOwner instanceof StringTag skullName) { - name = skullName; + // TODO verify + // Also - ChatColor.YELLOW + ChatColor.ITALIC + MessageTranslator.convertMessageLenient(nameTag.getValue(), session.locale())) this code existed if a custom name was already present. + // But I think we would always overwrite that because translateDisplayProperties runs after this method. + String customName = builder.getCustomName(); + if (customName == null) { + GameProfile profile = components.get(DataComponentType.PROFILE); + if (profile != null) { + String name = profile.getName(); + if (name != null) { + // Add correct name of player skull + String displayName = ChatColor.RESET + ChatColor.YELLOW + + MinecraftLocale.getLocaleString("block.minecraft.player_head.named", session.locale()).replace("%s", name); + builder.setCustomName(displayName); } else { - if (skullOwner instanceof CompoundTag && ((CompoundTag) skullOwner).get("Name") instanceof StringTag skullName) { - name = skullName; - } else { - // No name found so default to "Player Head" - displayTag.put(new StringTag("Name", ChatColor.RESET + ChatColor.YELLOW + MinecraftLocale.getLocaleString("block.minecraft.player_head", session.locale()))); - return; - } + // No name found so default to "Player Head" + builder.setCustomName(ChatColor.RESET + ChatColor.YELLOW + + MinecraftLocale.getLocaleString("block.minecraft.player_head", session.locale())); } - // Add correct name of player skull - String displayName = ChatColor.RESET + ChatColor.YELLOW + MinecraftLocale.getLocaleString("block.minecraft.player_head.named", session.locale()).replace("%s", name.getValue()); - displayTag.put(new StringTag("Name", displayName)); } } } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java b/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java index bed2945ba..6aac28c05 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java @@ -27,9 +27,9 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.mc.protocol.data.game.item.component.PotionContents; import com.github.steveice10.opennbt.tag.builtin.StringTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; @@ -46,29 +46,27 @@ public class PotionItem extends Item { } @Override - public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { - if (itemStack.getDataComponents() == null) return super.translateToBedrock(itemStack, mapping, mappings); - PotionContents potionContents = itemStack.getDataComponents().get(DataComponentType.POTION_CONTENTS); + public ItemData.Builder translateToBedrock(int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) { + if (components == null) return super.translateToBedrock(count, components, mapping, mappings); + PotionContents potionContents = components.get(DataComponentType.POTION_CONTENTS); if (potionContents != null) { - ItemDefinition customItemDefinition = CustomItemTranslator.getCustomItem(itemStack.getDataComponents(), mapping); + ItemDefinition customItemDefinition = CustomItemTranslator.getCustomItem(components, mapping); if (customItemDefinition == null) { Potion potion = Potion.getByJavaIdentifier(((StringTag) potionTag).getValue()); if (potion != null) { return ItemData.builder() .definition(mapping.getBedrockDefinition()) .damage(potion.getBedrockId()) - .count(itemStack.getAmount()) - .tag(ItemTranslator.translateNbtToBedrock(itemStack.getNbt())); + .count(count); } GeyserImpl.getInstance().getLogger().debug("Unknown Java potion: " + potionTag.getValue()); } else { return ItemData.builder() .definition(customItemDefinition) - .count(itemStack.getAmount()) - .tag(ItemTranslator.translateNbtToBedrock(itemStack.getNbt())); + .count(count); } } - return super.translateToBedrock(itemStack, mapping, mappings); + return super.translateToBedrock(count, components, mapping, mappings); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java index 395563fe3..267946442 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java @@ -83,7 +83,7 @@ public class ShulkerBoxItem extends BlockItem { itemsList.add(boxItemNbt.build()); } - builder.getOrCreateNbt().putList("Items", NbtType.COMPOUND, itemsList); + builder.putList("Items", NbtType.COMPOUND, itemsList); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/item/type/TippedArrowItem.java b/core/src/main/java/org/geysermc/geyser/item/type/TippedArrowItem.java index fcf562ba5..e4bad2f32 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/TippedArrowItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/TippedArrowItem.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; @@ -41,7 +41,7 @@ public class TippedArrowItem extends ArrowItem { } @Override - public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { + public ItemData.Builder translateToBedrock(int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) { Tag potionTag = itemStack.getNbt().get("Potion"); if (potionTag instanceof StringTag) { TippedArrowPotion tippedArrowPotion = TippedArrowPotion.getByJavaIdentifier(((StringTag) potionTag).getValue()); @@ -49,11 +49,10 @@ public class TippedArrowItem extends ArrowItem { return ItemData.builder() .definition(mapping.getBedrockDefinition()) .damage(tippedArrowPotion.getBedrockId()) - .count(itemStack.getAmount()) - .tag(ItemTranslator.translateNbtToBedrock(itemStack.getNbt())); + .count(count); } GeyserImpl.getInstance().getLogger().debug("Unknown Java potion (tipped arrow): " + potionTag.getValue()); } - return super.translateToBedrock(itemStack, mapping, mappings); + return super.translateToBedrock(count, components, mapping, mappings); } } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/TropicalFishBucketItem.java b/core/src/main/java/org/geysermc/geyser/item/type/TropicalFishBucketItem.java index 3ece87745..c0407e697 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/TropicalFishBucketItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/TropicalFishBucketItem.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.*; import net.kyori.adventure.text.Component; @@ -53,10 +54,10 @@ public class TropicalFishBucketItem extends Item { super.translateComponentsToBedrock(session, components, builder); // Prevent name from appearing as "Bucket of" - tag.put(new ByteTag("AppendCustomName", (byte) 1)); - tag.put(new StringTag("CustomName", MinecraftLocale.getLocaleString("entity.minecraft.tropical_fish", session.locale()))); + builder.putByte("AppendCustomName", (byte) 1); + builder.putString("CustomName", MinecraftLocale.getLocaleString("entity.minecraft.tropical_fish", session.locale())); // Add Java's client side lore tag - Tag bucketVariantTag = tag.get("BucketVariantTag"); + components.get(DataComponentType) if (bucketVariantTag instanceof IntTag) { CompoundTag displayTag = tag.get("display"); if (displayTag == null) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/WritableBookItem.java b/core/src/main/java/org/geysermc/geyser/item/type/WritableBookItem.java index 68cdf99d4..d925d2b8a 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/WritableBookItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/WritableBookItem.java @@ -25,12 +25,18 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; +import com.github.steveice10.mc.protocol.data.game.item.component.Filterable; +import com.github.steveice10.mc.protocol.data.game.item.component.WritableBookContent; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtMapBuilder; +import org.cloudburstmc.nbt.NbtType; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; @@ -48,22 +54,20 @@ public class WritableBookItem extends Item { public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); - ListTag pagesTag = tag.remove("pages"); - if (pagesTag == null) { + WritableBookContent bookContent = components.get(DataComponentType.WRITABLE_BOOK_CONTENT); + if (bookContent == null) { return; } - List pages = new ArrayList<>(); - for (Tag subTag : pagesTag.getValue()) { - if (!(subTag instanceof StringTag textTag)) - continue; - CompoundTag pageTag = new CompoundTag(""); - pageTag.put(new StringTag("photoname", "")); - pageTag.put(new StringTag("text", MessageTranslator.convertMessageLenient(textTag.getValue()))); - pages.add(pageTag); + List bedrockPages = new ArrayList<>(); + for (Filterable page : bookContent.getPages()) { + NbtMapBuilder pageBuilder = NbtMap.builder(); + pageBuilder.putString("photoname", ""); + pageBuilder.putString("text", MessageTranslator.convertMessageLenient(page.getRaw())); + bedrockPages.add(pageBuilder.build()); } - tag.put(new ListTag("pages", pages)); + builder.putList("pages", NbtType.COMPOUND, bedrockPages); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java b/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java index ae6b81f6e..6ca52aca4 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java @@ -25,21 +25,27 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; +import com.github.steveice10.mc.protocol.data.game.item.component.Filterable; +import com.github.steveice10.mc.protocol.data.game.item.component.WrittenBookContent; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtMapBuilder; +import org.cloudburstmc.nbt.NbtType; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.geyser.translator.text.MessageTranslator; +import java.util.ArrayList; import java.util.List; -public class WrittenBookItem extends WritableBookItem { +public class WrittenBookItem extends Item { public static final int MAXIMUM_PAGE_EDIT_LENGTH = 1024; public static final int MAXIMUM_PAGE_LENGTH = 32768; public static final int MAXIMUM_PAGE_COUNT = 100; // Java edition limit. Bedrock edition has a limit of 50 pages. @@ -51,25 +57,24 @@ public class WrittenBookItem extends WritableBookItem { @Override public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { - boolean isValid = isValidWrittenBook(tag); - if (!isValid) { - tag.remove("pages"); - } - super.translateComponentsToBedrock(session, components, builder); - if (!isValid) { - CompoundTag invalidTagPage = new CompoundTag(""); - invalidTagPage.put(new StringTag("photoname", "")); - invalidTagPage.put(new StringTag( - "text", - MessageTranslator.convertMessage( - Component.translatable("book.invalid.tag", NamedTextColor.DARK_RED), - session.locale() - ) - )); - tag.put(new ListTag("pages", List.of(invalidTagPage))); + WrittenBookContent bookContent = components.get(DataComponentType.WRITTEN_BOOK_CONTENT); + if (bookContent == null) { + return; } + List bedrockPages = new ArrayList<>(); + for (Filterable page : bookContent.getPages()) { + NbtMapBuilder pageBuilder = NbtMap.builder(); + pageBuilder.putString("photoname", ""); + pageBuilder.putString("text", MessageTranslator.convertMessage(page.getRaw())); + bedrockPages.add(pageBuilder.build()); + } + builder.putList("pages", NbtType.COMPOUND, bedrockPages); + + builder.putString("title", bookContent.getTitle().getRaw()) + .putString("author", bookContent.getAuthor()); + // TODO isResolved } private boolean isValidWrittenBook(CompoundTag tag) { diff --git a/core/src/main/java/org/geysermc/geyser/translator/item/BedrockItemBuilder.java b/core/src/main/java/org/geysermc/geyser/translator/item/BedrockItemBuilder.java index 83293d4ee..c1f7184f2 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/item/BedrockItemBuilder.java +++ b/core/src/main/java/org/geysermc/geyser/translator/item/BedrockItemBuilder.java @@ -34,6 +34,7 @@ import org.geysermc.geyser.registry.type.ItemMapping; import java.util.ArrayList; import java.util.List; +import java.util.OptionalInt; /** * An intermediary class made to allow easy access to work-in-progress NBT, such as lore and display. @@ -44,12 +45,18 @@ public final class BedrockItemBuilder { private String customName; @Nullable private List lore; + private OptionalInt damage = OptionalInt.empty(); /** * Miscellaneous NBT that will be put into the final item. */ @Nullable private NbtMapBuilder builder; + @Nullable + public String getCustomName() { + return customName; + } + public BedrockItemBuilder setCustomName(String customName) { this.customName = customName; return this; @@ -63,6 +70,15 @@ public final class BedrockItemBuilder { return lore; } + public OptionalInt getDamage() { + return damage; + } + + public BedrockItemBuilder setDamage(int damage) { + this.damage = OptionalInt.of(damage); + return this; + } + @NonNull public NbtMapBuilder getOrCreateNbt() { if (builder == null) { @@ -85,6 +101,14 @@ public final class BedrockItemBuilder { return getOrCreateNbt().putInt(name, value); } + public NbtMapBuilder putList(String name, NbtType type, List value) { + return getOrCreateNbt().putList(name, type, value); + } + + public NbtMapBuilder putLong(String name, long value) { + return getOrCreateNbt().putLong(name, value); + } + public NbtMapBuilder putString(String name, String value) { return getOrCreateNbt().putString(name, value); } @@ -108,6 +132,9 @@ public final class BedrockItemBuilder { } getOrCreateNbt().put("display", display.build()); } + if (damage.isPresent()) { + getOrCreateNbt().putInt("Damage", damage.getAsInt()); + } if (builder == null) { return null; } diff --git a/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java index 6459aa9ec..65ceb3497 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java @@ -161,9 +161,9 @@ public final class ItemTranslator { addAdvancedTooltips(components, nbtBuilder, javaItem, session.locale()); } - ItemStack itemStack = new ItemStack(javaItem.javaId(), count, components); - - ItemData.Builder builder = javaItem.translateToBedrock(itemStack, bedrockItem, session.getItemMappings()); + ItemData.Builder builder = javaItem.translateToBedrock(count, components, bedrockItem, session.getItemMappings()); + // Finalize the Bedrock NBT + builder.tag(nbtBuilder.build()); if (bedrockItem.isBlock()) { CustomBlockData customBlockData = BlockRegistries.CUSTOM_BLOCK_ITEM_OVERRIDES.getOrDefault( bedrockItem.getJavaItem().javaIdentifier(), null); From 94e533ea7ce5d87e8cbcf23a3f3d8b66bc633448 Mon Sep 17 00:00:00 2001 From: basaigh <53559772+basaigh@users.noreply.github.com> Date: Sun, 21 Apr 2024 01:33:07 +0100 Subject: [PATCH 261/344] Fix tags and attributes --- .../org/geysermc/geyser/entity/type/LivingEntity.java | 2 +- .../entity/type/living/animal/AxolotlEntity.java | 2 +- .../org/geysermc/geyser/session/GeyserSession.java | 2 +- .../org/geysermc/geyser/session/cache/TagCache.java | 10 +++++----- gradle/libs.versions.toml | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java index 245b99cef..b070bdfff 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java @@ -299,7 +299,7 @@ public class LivingEntity extends Entity { case GENERIC_MOVEMENT_SPEED -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.MOVEMENT_SPEED)); case GENERIC_FOLLOW_RANGE -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.FOLLOW_RANGE)); case GENERIC_KNOCKBACK_RESISTANCE -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.KNOCKBACK_RESISTANCE)); - case HORSE_JUMP_STRENGTH -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.HORSE_JUMP_STRENGTH)); + case GENERIC_JUMP_STRENGTH -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.HORSE_JUMP_STRENGTH)); } } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java index 85b2afc14..97753f63f 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java @@ -61,7 +61,7 @@ public class AxolotlEntity extends AnimalEntity { @Override public boolean canEat(Item item) { - return session.getTagCache().isAxolotlTemptItem(item); + return session.getTagCache().isAxolotlFood(item); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 936fc932d..8e1ed2e51 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -368,7 +368,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { /** * All dimensions that the client could possibly connect to. */ - private final Map dimensions = new Object2ObjectOpenHashMap<>(3); + private final Int2ObjectMap dimensions = new Int2ObjectOpenHashMap<>(4); private final Int2ObjectMap chatTypes = new Int2ObjectOpenHashMap<>(7); diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java index 5acfc1f09..57000bf8b 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java @@ -58,7 +58,7 @@ public class TagCache { private IntList requiresDiamondTool; /* Items */ - private IntList axolotlTemptItems; + private IntList axolotlFood; private IntList creeperIgniters; private IntList fishes; private IntList flowers; @@ -96,7 +96,7 @@ public class TagCache { } Map itemTags = packet.getTags().get("minecraft:item"); - this.axolotlTemptItems = IntList.of(itemTags.get("minecraft:axolotl_tempt_items")); + this.axolotlFood = IntList.of(itemTags.get("minecraft:axolotl_food")); this.creeperIgniters = load(itemTags.get("minecraft:creeper_igniters")); this.fishes = IntList.of(itemTags.get("minecraft:fishes")); this.flowers = IntList.of(itemTags.get("minecraft:flowers")); @@ -133,7 +133,7 @@ public class TagCache { this.requiresIronTool = IntLists.emptyList(); this.requiresDiamondTool = IntLists.emptyList(); - this.axolotlTemptItems = IntLists.emptyList(); + this.axolotlFood = IntLists.emptyList(); this.creeperIgniters = IntLists.emptyList(); this.fishes = IntLists.emptyList(); this.flowers = IntLists.emptyList(); @@ -143,8 +143,8 @@ public class TagCache { this.snifferFood = IntLists.emptyList(); } - public boolean isAxolotlTemptItem(Item item) { - return axolotlTemptItems.contains(item.javaId()); + public boolean isAxolotlFood(Item item) { + return axolotlFood.contains(item.javaId()); } public boolean isCreeperIgniter(Item item) { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e9fadb577..08c04a84a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ protocol-connection = "3.0.0.Beta1-20240411.165033-128" raknet = "1.0.0.CR3-20240416.144209-1" blockstateupdater="1.20.80-20240411.142413-1" mcauthlib = "d9d773e" -mcprotocollib = "b2e93c520a" # Revert from jitpack after release +mcprotocollib = "897eb241b6" # Revert from jitpack after release adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" From 8bd2df0828a581de8019e4e08aeb46a46458296f Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sat, 20 Apr 2024 22:42:25 -0400 Subject: [PATCH 262/344] Trying to get more compiled but brain is officially fried for the day! --- .../geyser/entity/type/FireworkEntity.java | 92 ++----------------- .../entity/type/ThrownPotionEntity.java | 16 ++-- .../inventory/item/TippedArrowPotion.java | 5 + .../geysermc/geyser/item/type/ArrowItem.java | 4 +- .../geysermc/geyser/item/type/BannerItem.java | 35 +++---- .../geyser/item/type/DecoratedPotItem.java | 2 +- .../geyser/item/type/EnchantedBookItem.java | 25 ++--- .../geyser/item/type/GoatHornItem.java | 22 ++--- .../org/geysermc/geyser/item/type/Item.java | 70 +++++--------- .../geysermc/geyser/item/type/PotionItem.java | 7 +- .../geysermc/geyser/item/type/ShieldItem.java | 35 ++++--- .../geyser/item/type/TippedArrowItem.java | 13 ++- .../item/type/TropicalFishBucketItem.java | 34 +++---- .../geyser/session/cache/LodestoneCache.java | 52 ++++++----- .../inventory/LoomInventoryTranslator.java | 7 +- .../translator/item/BedrockItemBuilder.java | 5 +- .../translator/item/ItemTranslator.java | 55 +++++------ .../bedrock/BedrockBookEditTranslator.java | 12 +-- .../entity/JavaSetEquipmentTranslator.java | 20 ++-- .../geysermc/geyser/util/InventoryUtils.java | 13 +-- 20 files changed, 210 insertions(+), 314 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/FireworkEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/FireworkEntity.java index 171849ce5..04317e6d6 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/FireworkEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/FireworkEntity.java @@ -27,24 +27,16 @@ package org.geysermc.geyser.entity.type; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.ListTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import org.cloudburstmc.math.vector.Vector3f; -import org.cloudburstmc.nbt.NbtMap; -import org.cloudburstmc.nbt.NbtMapBuilder; -import org.cloudburstmc.nbt.NbtType; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.packet.SetEntityMotionPacket; -import org.geysermc.floodgate.util.DeviceOs; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.type.player.PlayerEntity; -import org.geysermc.geyser.level.FireworkColor; +import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.util.MathUtils; +import org.geysermc.geyser.translator.item.BedrockItemBuilder; -import java.util.ArrayList; -import java.util.List; import java.util.OptionalInt; import java.util.UUID; @@ -59,80 +51,16 @@ public class FireworkEntity extends Entity { if (item == null) { return; } - CompoundTag tag = item.getNbt(); - - if (tag == null) { + DataComponents components = item.getDataComponents(); + if (components == null) { return; } - // TODO: Remove once Mojang fixes bugs with fireworks crashing clients on these specific devices. - // https://bugs.mojang.com/browse/MCPE-89115 - if (session.getClientData().getDeviceOs() == DeviceOs.XBOX - || session.getClientData().getDeviceOs() == DeviceOs.PS4) { - return; - } - - CompoundTag fireworks = tag.get("Fireworks"); - if (fireworks == null) { - // Thank you Mineplex very cool - return; - } - - NbtMapBuilder fireworksBuilder = NbtMap.builder(); - if (fireworks.get("Flight") != null) { - fireworksBuilder.putByte("Flight", MathUtils.getNbtByte(fireworks.get("Flight").getValue())); - } - - List explosions = new ArrayList<>(); - if (fireworks.get("Explosions") != null) { - for (Tag effect : ((ListTag) fireworks.get("Explosions")).getValue()) { - CompoundTag effectData = (CompoundTag) effect; - NbtMapBuilder effectBuilder = NbtMap.builder(); - - if (effectData.get("Type") != null) { - effectBuilder.putByte("FireworkType", MathUtils.getNbtByte(effectData.get("Type").getValue())); - } - - if (effectData.get("Colors") != null) { - int[] oldColors = (int[]) effectData.get("Colors").getValue(); - byte[] colors = new byte[oldColors.length]; - - int i = 0; - for (int color : oldColors) { - colors[i++] = FireworkColor.fromJavaRGB(color); - } - - effectBuilder.putByteArray("FireworkColor", colors); - } - - if (effectData.get("FadeColors") != null) { - int[] oldColors = (int[]) effectData.get("FadeColors").getValue(); - byte[] colors = new byte[oldColors.length]; - - int i = 0; - for (int color : oldColors) { - colors[i++] = FireworkColor.fromJavaRGB(color); - } - - effectBuilder.putByteArray("FireworkFade", colors); - } - - if (effectData.get("Trail") != null) { - effectBuilder.putByte("FireworkTrail", MathUtils.getNbtByte(effectData.get("Trail").getValue())); - } - - if (effectData.get("Flicker") != null) { - effectBuilder.putByte("FireworkFlicker", MathUtils.getNbtByte(effectData.get("Flicker").getValue())); - } - - explosions.add(effectBuilder.build()); - } - } - - fireworksBuilder.putList("Explosions", NbtType.COMPOUND, explosions); - - NbtMapBuilder builder = NbtMap.builder(); - builder.put("Fireworks", fireworksBuilder.build()); + // TODO this looked the same, so I'm going to assume it is and (keep below comment if true) + // Translate using item methods to get firework NBT for Bedrock + BedrockItemBuilder builder = new BedrockItemBuilder(); + Items.FIREWORK_ROCKET.translateComponentsToBedrock(session, components, builder); + dirtyMetadata.put(EntityDataTypes.DISPLAY_FIREWORK, builder.build()); } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/ThrownPotionEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ThrownPotionEntity.java index cea371963..31428477a 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/ThrownPotionEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/ThrownPotionEntity.java @@ -27,8 +27,9 @@ package org.geysermc.geyser.entity.type; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.opennbt.tag.builtin.StringTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; +import com.github.steveice10.mc.protocol.data.game.item.component.PotionContents; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; @@ -58,16 +59,17 @@ public class ThrownPotionEntity extends ThrowableItemEntity { setFlag(EntityFlag.LINGERING, false); } else { // As of Java 1.19.3, the server/client doesn't seem to care of the item is actually a potion? - if (itemStack.getNbt() != null) { - Tag potionTag = itemStack.getNbt().get("Potion"); - if (potionTag instanceof StringTag) { - Potion potion = Potion.getByJavaIdentifier(((StringTag) potionTag).getValue()); + DataComponents components = itemStack.getDataComponents(); + if (components != null) { + PotionContents potionContents = components.get(DataComponentType.POTION_CONTENTS); + if (potionContents != null) { + Potion potion = Potion.VALUES[potionContents.getPotionId()]; if (potion != null) { dirtyMetadata.put(EntityDataTypes.EFFECT_COLOR, (int) potion.getBedrockId()); setFlag(EntityFlag.ENCHANTED, !NON_ENCHANTED_POTIONS.contains(potion)); } else { dirtyMetadata.put(EntityDataTypes.EFFECT_COLOR, 0); - GeyserImpl.getInstance().getLogger().debug("Unknown java potion: " + potionTag.getValue()); + GeyserImpl.getInstance().getLogger().debug("Unknown java potion: " + potionContents.getPotionId()); } } diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/TippedArrowPotion.java b/core/src/main/java/org/geysermc/geyser/inventory/item/TippedArrowPotion.java index 3ba0ad56f..5c33fec67 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/item/TippedArrowPotion.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/item/TippedArrowPotion.java @@ -36,6 +36,7 @@ import java.util.Locale; */ @Getter public enum TippedArrowPotion { + WATER(-1, ArrowParticleColors.NONE), // Guessing this based off of the Potion enum. TODO merge? MUNDANE(2, ArrowParticleColors.NONE), // 3 is extended? THICK(4, ArrowParticleColors.NONE), AWKWARD(5, ArrowParticleColors.NONE), @@ -94,6 +95,10 @@ public enum TippedArrowPotion { this.javaColor = arrowParticleColor.getColor(); } + public static TippedArrowPotion of(int id) { + return VALUES[id]; + } + public static @Nullable TippedArrowPotion getByJavaIdentifier(String javaIdentifier) { for (TippedArrowPotion potion : VALUES) { if (potion.javaIdentifier.equals(javaIdentifier)) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java index cf66b036b..16d5fd482 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java @@ -26,8 +26,6 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.item.component.PotionContents; import com.github.steveice10.opennbt.tag.builtin.StringTag; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; @@ -48,7 +46,7 @@ public class ArrowItem extends Item { if (tippedArrowPotion != null) { itemStack = Items.TIPPED_ARROW.newItemStack(itemStack.getAmount(), itemStack.getDataComponents()); StringTag potionTag = new StringTag("Potion", tippedArrowPotion.getJavaIdentifier()); - itemStack.getDataComponents().put(DataComponentType.POTION_CONTENTS, new PotionContents()); + //itemStack.getDataComponents().put(DataComponentType.POTION_CONTENTS, new PotionContents()); } return itemStack; } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java index 549809391..32806c3c2 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java @@ -56,14 +56,14 @@ public class BannerItem extends BlockItem { static { // Construct what an ominous banner is supposed to look like OMINOUS_BANNER_PATTERN = List.of( - new BannerPatternLayer("mr", 9), - new BannerPatternLayer("bs", 8), - new BannerPatternLayer("cs", 7), - new BannerPatternLayer("bo", 8), - new BannerPatternLayer("ms", 15), - new BannerPatternLayer("hh", 8), - new BannerPatternLayer("mc", 8), - new BannerPatternLayer("bo", 15) +// new BannerPatternLayer("mr", 9), +// new BannerPatternLayer("bs", 8), +// new BannerPatternLayer("cs", 7), +// new BannerPatternLayer("bo", 8), +// new BannerPatternLayer("ms", 15), +// new BannerPatternLayer("hh", 8), +// new BannerPatternLayer("mc", 8), +// new BannerPatternLayer("bo", 15) ); } @@ -103,7 +103,8 @@ public class BannerItem extends BlockItem { * @return The Java edition format pattern nbt */ public static CompoundTag getJavaBannerPattern(NbtMap pattern) { - return new BannerPatternLayer(pattern.getString("Pattern"), 15 - pattern.getInt("Color")); + //return new BannerPatternLayer(0/*pattern.getString("Pattern")*/, 15 - pattern.getInt("Color")); + return null; } /** @@ -128,13 +129,13 @@ public class BannerItem extends BlockItem { List patterns = components.get(DataComponentType.BANNER_PATTERNS); if (patterns != null) { - if (patterns.equals(OMINOUS_BANNER_PATTERN)) { - // Remove the current patterns and set the ominous banner type - builder.putInt("Type", 1); - } else { - invertBannerColors(patterns); - tag.put(patterns); - } +// if (patterns.equals(OMINOUS_BANNER_PATTERN)) { +// // Remove the current patterns and set the ominous banner type +// builder.putInt("Type", 1); +// } else { +// invertBannerColors(patterns); +// tag.put(patterns); +// } } } @@ -146,7 +147,7 @@ public class BannerItem extends BlockItem { // Ominous banner pattern tag.remove("Type"); CompoundTag blockEntityTag = new CompoundTag("BlockEntityTag"); - blockEntityTag.put(OMINOUS_BANNER_PATTERN); + //blockEntityTag.put(OMINOUS_BANNER_PATTERN); tag.put(blockEntityTag); } else if (tag.get("Patterns") instanceof ListTag patterns) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java b/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java index 792ec0f0b..8d9be4db2 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java @@ -41,7 +41,7 @@ public class DecoratedPotItem extends BlockItem { public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); - components.get(DataComponentType.POT_DECORATIONS); // TODO + components.get(DataComponentType.POT_DECORATIONS); // TODO what does this look like on Bedrock? // if (tag.remove("BlockEntityTag") instanceof CompoundTag blockEntityTag) { // if (blockEntityTag.remove("sherds") instanceof ListTag sherds) { // // bedrock wants it on the root level diff --git a/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java b/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java index 3851813ae..095537a09 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java @@ -25,16 +25,18 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.ListTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; +import com.github.steveice10.mc.protocol.data.game.item.component.ItemEnchantments; import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtType; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; import java.util.ArrayList; import java.util.List; +import java.util.Map; public class EnchantedBookItem extends Item { public EnchantedBookItem(String javaIdentifier, Builder builder) { @@ -45,20 +47,19 @@ public class EnchantedBookItem extends Item { public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); - List newTags = new ArrayList<>(); - Tag enchantmentTag = tag.remove("StoredEnchantments"); - if (enchantmentTag instanceof ListTag listTag) { - for (Tag subTag : listTag.getValue()) { - if (!(subTag instanceof CompoundTag)) continue; - CompoundTag bedrockTag = remapEnchantment(session, (CompoundTag) subTag, tag); + List bedrockEnchants = new ArrayList<>(); + ItemEnchantments enchantments = components.get(DataComponentType.STORED_ENCHANTMENTS); + if (enchantments != null) { // TODO don't duplicate code? + for (Map.Entry enchantment : enchantments.getEnchantments().entrySet()) { + NbtMap bedrockTag = remapEnchantment(session, enchantment.getKey(), enchantment.getValue(), builder); if (bedrockTag != null) { - newTags.add(bedrockTag); + bedrockEnchants.add(bedrockTag); } } } - if (!newTags.isEmpty()) { - tag.put(new ListTag("ench", newTags)); + if (!bedrockEnchants.isEmpty()) { + builder.putList("ench", NbtType.COMPOUND, bedrockEnchants); } } } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java b/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java index 20f9782df..48e75dc79 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java @@ -64,16 +64,16 @@ public class GoatHornItem extends Item { // TODO registry if (instrument != null) { // Drop the Minecraft namespace if applicable - if (instrument.startsWith("minecraft:")) { - instrument = instrument.substring("minecraft:".length()); - } - - int damage = INSTRUMENTS.indexOf(instrument); - if (damage == -1) { - damage = 0; - GeyserImpl.getInstance().getLogger().debug("Unknown goat horn instrument: " + instrumentTag.getValue()); - } - builder.damage(damage); +// if (instrument.startsWith("minecraft:")) { +// instrument = instrument.substring("minecraft:".length()); +// } +// +// int damage = INSTRUMENTS.indexOf(instrument); +// if (damage == -1) { +// damage = 0; +// GeyserImpl.getInstance().getLogger().debug("Unknown goat horn instrument: " + instrumentTag.getValue()); +// } +// builder.damage(damage); } return builder; } @@ -90,7 +90,7 @@ public class GoatHornItem extends Item { String instrument = INSTRUMENTS.get(damage); StringTag instrumentTag = new StringTag("instrument", "minecraft:" + instrument); - itemStack.getNbt().put(instrumentTag); + //itemStack.getNbt().put(instrumentTag); return itemStack; } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/Item.java b/core/src/main/java/org/geysermc/geyser/item/type/Item.java index e2822ea7a..2779768db 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/Item.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/Item.java @@ -27,15 +27,15 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.Identifier; import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.mc.protocol.data.game.item.component.ItemEnchantments; import com.github.steveice10.opennbt.tag.builtin.*; import net.kyori.adventure.text.Component; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.nbt.NbtMap; -import org.cloudburstmc.nbt.NbtMapBuilder; +import org.cloudburstmc.nbt.NbtType; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.inventory.item.Enchantment; @@ -48,7 +48,6 @@ import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.geyser.translator.item.ItemTranslator; import org.geysermc.geyser.translator.text.MessageTranslator; -import org.geysermc.geyser.util.InventoryUtils; import java.util.ArrayList; import java.util.List; @@ -113,7 +112,7 @@ public class Item { if (itemData.getTag() == null) { return new ItemStack(javaId, itemData.getCount(), null); } - return new ItemStack(javaId, itemData.getCount(), ItemTranslator.translateToJavaNBT("", itemData.getTag())); + return new ItemStack(javaId, itemData.getCount(), null/*ItemTranslator.translateToJavaNBT("", itemData.getTag())*/); } public ItemMapping toBedrockDefinition(DataComponents components, ItemMappings mappings) { @@ -137,23 +136,19 @@ public class Item { builder.setDamage(damage); } - List newTags = new ArrayList<>(); + List enchantNbtList = new ArrayList<>(); ItemEnchantments enchantments = components.get(DataComponentType.ENCHANTMENTS); if (enchantments != null) { - - } - if (enchantmentTag instanceof ListTag listTag) { - for (Tag subTag : listTag.getValue()) { - if (!(subTag instanceof CompoundTag)) continue; - CompoundTag bedrockTag = remapEnchantment(session, (CompoundTag) subTag, tag); - if (bedrockTag != null) { - newTags.add(bedrockTag); + for (Map.Entry enchantment : enchantments.getEnchantments().entrySet()) { + NbtMap enchantNbt = remapEnchantment(session, enchantment.getKey(), enchantment.getValue(), builder); + if (enchantNbt != null) { + enchantNbtList.add(enchantNbt); } } } - if (!newTags.isEmpty()) { - tag.put(new ListTag("ench", newTags)); + if (!enchantNbtList.isEmpty()) { + builder.putList("ench", NbtType.COMPOUND, enchantNbtList); } } @@ -220,45 +215,30 @@ public class Item { } } - protected final @Nullable NbtMap remapEnchantment(GeyserSession session, ItemEnchantments, NbtMapBuilder rootBuilder) { - - Enchantment enchantment = Enchantment.getByJavaIdentifier(((StringTag) javaEnchId).getValue()); + protected final @Nullable NbtMap remapEnchantment(GeyserSession session, int enchantId, int level, BedrockItemBuilder builder) { + // TODO verify + // TODO streamline Enchantment process + Enchantment.JavaEnchantment enchantment = Enchantment.JavaEnchantment.of(enchantId); + if (enchantment == Enchantment.JavaEnchantment.SWEEPING_EDGE) { + addSweeping(session, builder, level); + return null; + } if (enchantment == null) { - if (Identifier.formalize((String) javaEnchId.getValue()).equals("minecraft:sweeping")) { - Tag javaEnchLvl = tag.get("lvl"); - int sweepingLvl = javaEnchLvl != null && javaEnchLvl.getValue() instanceof Number lvl ? lvl.intValue() : 0; - - addSweeping(session, rootTag, sweepingLvl); - return null; - } - GeyserImpl.getInstance().getLogger().debug("Unknown Java enchantment while NBT item translating: " + javaEnchId.getValue()); + GeyserImpl.getInstance().getLogger().debug("Unknown Java enchantment while NBT item translating: " + enchantId); return null; } - Tag javaEnchLvl = tag.get("lvl"); - - NbtMapBuilder builder = NbtMap.builder(); - builder.putShort("id", (short) enchantment.ordinal()); - builder.putShort("lvl", ); - return builder.build(); + return NbtMap.builder() + .putShort("id", (short) Enchantment.valueOf(enchantment.name()).ordinal()) + .putShort("lvl", (short) level) + .build(); } - private void addSweeping(GeyserSession session, CompoundTag itemTag, int level) { - CompoundTag displayTag = itemTag.get("display"); - if (displayTag == null) { - displayTag = new CompoundTag("display"); - itemTag.put(displayTag); - } - ListTag loreTag = displayTag.get("Lore"); - if (loreTag == null) { - loreTag = new ListTag("Lore"); - displayTag.put(loreTag); - } - + private void addSweeping(GeyserSession session, BedrockItemBuilder builder, int level) { String sweepingTranslation = MinecraftLocale.getLocaleString("enchantment.minecraft.sweeping", session.locale()); String lvlTranslation = MinecraftLocale.getLocaleString("enchantment.level." + level, session.locale()); - loreTag.add(new StringTag("", ChatColor.RESET + ChatColor.GRAY + sweepingTranslation + " " + lvlTranslation)); + builder.getOrCreateLore().add(ChatColor.RESET + ChatColor.GRAY + sweepingTranslation + " " + lvlTranslation); } /* Translation methods end */ diff --git a/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java b/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java index 6aac28c05..63b9240c0 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java @@ -38,7 +38,6 @@ import org.geysermc.geyser.inventory.item.Potion; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.translator.item.CustomItemTranslator; -import org.geysermc.geyser.translator.item.ItemTranslator; public class PotionItem extends Item { public PotionItem(String javaIdentifier, Builder builder) { @@ -52,14 +51,14 @@ public class PotionItem extends Item { if (potionContents != null) { ItemDefinition customItemDefinition = CustomItemTranslator.getCustomItem(components, mapping); if (customItemDefinition == null) { - Potion potion = Potion.getByJavaIdentifier(((StringTag) potionTag).getValue()); + Potion potion = Potion.VALUES[potionContents.getPotionId()]; if (potion != null) { return ItemData.builder() .definition(mapping.getBedrockDefinition()) .damage(potion.getBedrockId()) .count(count); } - GeyserImpl.getInstance().getLogger().debug("Unknown Java potion: " + potionTag.getValue()); + GeyserImpl.getInstance().getLogger().debug("Unknown Java potion: " + potionContents.getPotionId()); } else { return ItemData.builder() .definition(customItemDefinition) @@ -75,7 +74,7 @@ public class PotionItem extends Item { ItemStack itemStack = super.translateToJava(itemData, mapping, mappings); if (potion != null) { StringTag potionTag = new StringTag("Potion", potion.getJavaIdentifier()); - itemStack.getNbt().put(potionTag); + //itemStack.getNbt().put(potionTag); } return itemStack; } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ShieldItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ShieldItem.java index 30b50b436..f495222f3 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ShieldItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ShieldItem.java @@ -26,10 +26,6 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.IntTag; -import com.github.steveice10.opennbt.tag.builtin.ListTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.item.components.ToolTier; import org.geysermc.geyser.session.GeyserSession; @@ -44,21 +40,22 @@ public class ShieldItem extends Item { public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); - if (tag.remove("BlockEntityTag") instanceof CompoundTag blockEntityTag) { - if (blockEntityTag.get("Patterns") instanceof ListTag patterns) { - for (Tag pattern : patterns) { - if (((CompoundTag) pattern).get("Color") instanceof IntTag color) { - color.setValue(15 - color.getValue()); - } - } - // Bedrock looks for patterns at the root - tag.put(patterns); - } - if (blockEntityTag.get("Base") instanceof IntTag base) { - base.setValue(15 - base.getValue()); - tag.put(base); - } - } + // TODO figure out patterns first. +// if (tag.remove("BlockEntityTag") instanceof CompoundTag blockEntityTag) { +// if (blockEntityTag.get("Patterns") instanceof ListTag patterns) { +// for (Tag pattern : patterns) { +// if (((CompoundTag) pattern).get("Color") instanceof IntTag color) { +// color.setValue(15 - color.getValue()); +// } +// } +// // Bedrock looks for patterns at the root +// tag.put(patterns); +// } +// if (blockEntityTag.get("Base") instanceof IntTag base) { +// base.setValue(15 - base.getValue()); +// tag.put(base); +// } +// } } @Override diff --git a/core/src/main/java/org/geysermc/geyser/item/type/TippedArrowItem.java b/core/src/main/java/org/geysermc/geyser/item/type/TippedArrowItem.java index e4bad2f32..9074c2ec8 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/TippedArrowItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/TippedArrowItem.java @@ -25,15 +25,14 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.opennbt.tag.builtin.StringTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; +import com.github.steveice10.mc.protocol.data.game.item.component.PotionContents; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.inventory.item.TippedArrowPotion; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; -import org.geysermc.geyser.translator.item.ItemTranslator; public class TippedArrowItem extends ArrowItem { public TippedArrowItem(String javaIdentifier, Builder builder) { @@ -42,16 +41,16 @@ public class TippedArrowItem extends ArrowItem { @Override public ItemData.Builder translateToBedrock(int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) { - Tag potionTag = itemStack.getNbt().get("Potion"); - if (potionTag instanceof StringTag) { - TippedArrowPotion tippedArrowPotion = TippedArrowPotion.getByJavaIdentifier(((StringTag) potionTag).getValue()); + PotionContents potionContents = components.get(DataComponentType.POTION_CONTENTS); + if (potionContents != null) { + TippedArrowPotion tippedArrowPotion = TippedArrowPotion.of(potionContents.getPotionId()); if (tippedArrowPotion != null) { return ItemData.builder() .definition(mapping.getBedrockDefinition()) .damage(tippedArrowPotion.getBedrockId()) .count(count); } - GeyserImpl.getInstance().getLogger().debug("Unknown Java potion (tipped arrow): " + potionTag.getValue()); + GeyserImpl.getInstance().getLogger().debug("Unknown Java potion (tipped arrow): " + potionContents.getPotionId()); } return super.translateToBedrock(count, components, mapping, mappings); } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/TropicalFishBucketItem.java b/core/src/main/java/org/geysermc/geyser/item/type/TropicalFishBucketItem.java index c0407e697..f70e6b295 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/TropicalFishBucketItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/TropicalFishBucketItem.java @@ -27,7 +27,8 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.opennbt.tag.builtin.*; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.Tag; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.Style; @@ -39,7 +40,6 @@ import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.geyser.translator.text.MessageTranslator; -import java.util.ArrayList; import java.util.List; public class TropicalFishBucketItem extends Item { @@ -57,24 +57,24 @@ public class TropicalFishBucketItem extends Item { builder.putByte("AppendCustomName", (byte) 1); builder.putString("CustomName", MinecraftLocale.getLocaleString("entity.minecraft.tropical_fish", session.locale())); // Add Java's client side lore tag - components.get(DataComponentType) - if (bucketVariantTag instanceof IntTag) { - CompoundTag displayTag = tag.get("display"); - if (displayTag == null) { - displayTag = new CompoundTag("display"); - tag.put(displayTag); + // Do you know how frequently Java NBT used to be before 1.20.5? It was a lot. And now it's just this lowly check. + CompoundTag entityTag = components.get(DataComponentType.BUCKET_ENTITY_DATA); + if (entityTag != null && !entityTag.isEmpty()) { + //TODO test + Tag bucketVariant = entityTag.get("BucketVariantTag"); + if (bucketVariant == null || !(bucketVariant.getValue() instanceof Number)) { + return; } + List lore = builder.getOrCreateLore(); - List lore = new ArrayList<>(); - - int varNumber = ((IntTag) bucketVariantTag).getValue(); + int varNumber = ((Number) bucketVariant.getValue()).intValue(); int predefinedVariantId = TropicalFishEntity.getPredefinedId(varNumber); if (predefinedVariantId != -1) { Component tooltip = Component.translatable("entity.minecraft.tropical_fish.predefined." + predefinedVariantId, LORE_STYLE); - lore.add(0, new StringTag("", MessageTranslator.convertMessage(tooltip, session.locale()))); + lore.add(0, MessageTranslator.convertMessage(tooltip, session.locale())); } else { Component typeTooltip = Component.translatable("entity.minecraft.tropical_fish.type." + TropicalFishEntity.getVariantName(varNumber), LORE_STYLE); - lore.add(0, new StringTag("", MessageTranslator.convertMessage(typeTooltip, session.locale()))); + lore.add(0, MessageTranslator.convertMessage(typeTooltip, session.locale())); byte baseColor = TropicalFishEntity.getBaseColor(varNumber); byte patternColor = TropicalFishEntity.getPatternColor(varNumber); @@ -83,14 +83,8 @@ public class TropicalFishBucketItem extends Item { colorTooltip = colorTooltip.append(Component.text(", ", LORE_STYLE)) .append(Component.translatable("color.minecraft." + TropicalFishEntity.getColorName(patternColor), LORE_STYLE)); } - lore.add(1, new StringTag("", MessageTranslator.convertMessage(colorTooltip, session.locale()))); + lore.add(1, MessageTranslator.convertMessage(colorTooltip, session.locale())); } - - ListTag loreTag = displayTag.get("Lore"); - if (loreTag != null) { - lore.addAll(loreTag.getValue()); - } - displayTag.put(new ListTag("Lore", lore)); } } } diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/LodestoneCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/LodestoneCache.java index 4bd2244ab..eced0e50b 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/LodestoneCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/LodestoneCache.java @@ -25,13 +25,14 @@ package org.geysermc.geyser.session.cache; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.GlobalPos; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.mc.protocol.data.game.item.component.LodestoneTracker; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.IntTag; -import com.github.steveice10.opennbt.tag.builtin.StringTag; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.inventory.GeyserItemStack; import java.util.Map; @@ -54,22 +55,27 @@ public final class LodestoneCache { private int id = 1; public void cacheInventoryItem(GeyserItemStack itemStack) { - CompoundTag tag = itemStack.getNbt(); - if (tag == null) { + DataComponents components = itemStack.getComponents(); + if (components == null) { // invalid return; } - CompoundTag lodestonePos = tag.get("LodestonePos"); - if (lodestonePos == null) { - // invalid + LodestoneTracker tracker = components.get(DataComponentType.LODESTONE_TRACKER); + if (tracker == null) { return; } - // Get all info needed for tracking - int x = ((IntTag) lodestonePos.get("X")).getValue(); - int y = ((IntTag) lodestonePos.get("Y")).getValue(); - int z = ((IntTag) lodestonePos.get("Z")).getValue(); - String dim = ((StringTag) tag.get("LodestoneDimension")).getValue(); + GlobalPos position = tracker.getPos(); + + if (position == null) { + GeyserImpl.getInstance().getLogger().error("Position is null. Find out why."); + Thread.dumpStack(); + return; + } + int x = position.getX(); + int y = position.getY(); + int z = position.getZ(); + String dim = position.getDimension(); for (LodestonePos pos : this.activeLodestones.values()) { if (pos.equals(x, y, z, dim)) { @@ -90,17 +96,17 @@ public final class LodestoneCache { } public int store(LodestoneTracker tracker) { - CompoundTag lodestonePos = tag.get("LodestonePos"); - if (lodestonePos == null) { - // invalid - return 0; - } + GlobalPos position = tracker.getPos(); - // Get all info needed for tracking - int x = ((IntTag) lodestonePos.get("X")).getValue(); - int y = ((IntTag) lodestonePos.get("Y")).getValue(); - int z = ((IntTag) lodestonePos.get("Z")).getValue(); - String dim = ((StringTag) tag.get("LodestoneDimension")).getValue(); + if (position == null) { + GeyserImpl.getInstance().getLogger().error("Position is null. Find out why."); + Thread.dumpStack(); + return -1; + } + int x = position.getX(); + int y = position.getY(); + int z = position.getZ(); + String dim = position.getDimension(); for (LodestonePos pos : this.activeLodestones.values()) { if (pos.equals(x, y, z, dim)) { diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/LoomInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/LoomInventoryTranslator.java index 0e43ba660..6c7a11ff2 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/LoomInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/LoomInventoryTranslator.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.translator.inventory; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; @@ -51,6 +52,7 @@ import org.geysermc.geyser.item.type.DyeItem; import org.geysermc.geyser.session.GeyserSession; import java.util.Collections; +import java.util.HashMap; import java.util.List; public class LoomInventoryTranslator extends AbstractBlockInventoryTranslator { @@ -154,9 +156,10 @@ public class LoomInventoryTranslator extends AbstractBlockInventoryTranslator { GeyserItemStack inputCopy = inventory.getItem(0).copy(1); inputCopy.setNetId(session.getNextItemNetId()); // Add the pattern manually, for better item synchronization - if (inputCopy.getNbt() == null) { - inputCopy.setNbt(new CompoundTag("")); + if (inputCopy.getComponents() == null) { + inputCopy.setComponents(new DataComponents(new HashMap<>())); } + //TODO CompoundTag blockEntityTag = inputCopy.getNbt().get("BlockEntityTag"); CompoundTag javaBannerPattern = BannerItem.getJavaBannerPattern(pattern); diff --git a/core/src/main/java/org/geysermc/geyser/translator/item/BedrockItemBuilder.java b/core/src/main/java/org/geysermc/geyser/translator/item/BedrockItemBuilder.java index c1f7184f2..52d5b7e31 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/item/BedrockItemBuilder.java +++ b/core/src/main/java/org/geysermc/geyser/translator/item/BedrockItemBuilder.java @@ -142,13 +142,12 @@ public final class BedrockItemBuilder { } /** - * Creates item NBT with count, name, and damage set. + * Creates item NBT to nest within NBT with name, count, and damage set. */ public static NbtMapBuilder createItemNbt(ItemMapping mapping, int count, int damage) { NbtMapBuilder builder = NbtMap.builder(); - builder.putByte("Count", (byte) count); builder.putString("Name", mapping.getBedrockIdentifier()); - + builder.putByte("Count", (byte) count); builder.putShort("Damage", (short) damage); return builder; } diff --git a/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java index 65ceb3497..c96542fc1 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java @@ -30,52 +30,42 @@ import com.github.steveice10.mc.protocol.data.game.Identifier; import com.github.steveice10.mc.protocol.data.game.entity.attribute.ModifierOperation; import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.mc.protocol.data.game.item.component.AdventureModePredicate; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.mc.protocol.data.game.item.component.ItemAttributeModifiers; -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.github.steveice10.opennbt.tag.builtin.*; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; -import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; -import org.geysermc.geyser.api.block.custom.CustomBlockData; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.nbt.NbtList; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; +import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.block.custom.CustomBlockData; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.registry.BlockRegistries; +import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.type.CustomSkull; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.skin.SkinManager; -import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.util.InventoryUtils; import java.text.DecimalFormat; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; public final class ItemTranslator { @@ -357,7 +347,7 @@ public final class ItemTranslator { return ItemDefinition.AIR; } - ItemMapping mapping = itemStack.asItem().toBedrockDefinition(itemStack.getNbt(), session.getItemMappings()); + ItemMapping mapping = itemStack.asItem().toBedrockDefinition(itemStack.getComponents(), session.getItemMappings()); ItemDefinition itemDefinition = mapping.getBedrockDefinition(); CustomBlockData customBlockData = BlockRegistries.CUSTOM_BLOCK_ITEM_OVERRIDES.getOrDefault( @@ -563,20 +553,21 @@ public final class ItemTranslator { if (components == null) { return null; } + //TODO GameProfile profile = components.get(DataComponentType.PROFILE); if (profile != null) { - if (!(nbt.get("SkullOwner") instanceof CompoundTag skullOwner)) { - // It's a username give up d: - return null; - } - SkinManager.GameProfileData data = SkinManager.GameProfileData.from(skullOwner); - if (data == null) { - session.getGeyser().getLogger().debug("Not sure how to handle skull head item display. " + nbt); - return null; - } - - String skinHash = data.skinUrl().substring(data.skinUrl().lastIndexOf('/') + 1); - return BlockRegistries.CUSTOM_SKULLS.get(skinHash); +// if (!(nbt.get("SkullOwner") instanceof CompoundTag skullOwner)) { +// // It's a username give up d: +// return null; +// } +// SkinManager.GameProfileData data = SkinManager.GameProfileData.from(skullOwner); +// if (data == null) { +// session.getGeyser().getLogger().debug("Not sure how to handle skull head item display. " + nbt); +// return null; +// } +// +// String skinHash = data.skinUrl().substring(data.skinUrl().lastIndexOf('/') + 1); +// return BlockRegistries.CUSTOM_SKULLS.get(skinHash); } return null; } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBookEditTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBookEditTranslator.java index ec1d62d16..ba802e42e 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBookEditTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBookEditTranslator.java @@ -26,6 +26,8 @@ package org.geysermc.geyser.translator.protocol.bedrock; import com.github.steveice10.mc.protocol.data.game.item.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; +import com.github.steveice10.mc.protocol.data.game.item.component.WritableBookContent; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundEditBookPacket; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; @@ -39,10 +41,7 @@ import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.translator.text.MessageTranslator; -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; +import java.util.*; @Translator(packet = BookEditPacket.class) public class BedrockBookEditTranslator extends PacketTranslator { @@ -56,8 +55,9 @@ public class BedrockBookEditTranslator extends PacketTranslator GeyserItemStack itemStack = session.getPlayerInventory().getItemInHand(); if (itemStack != null) { - CompoundTag tag = itemStack.getNbt() != null ? itemStack.getNbt() : new CompoundTag(""); - ItemStack bookItem = new ItemStack(itemStack.getJavaId(), itemStack.getAmount(), tag); + DataComponents components = itemStack.getComponents() != null ? itemStack.getComponents() : new DataComponents(new HashMap<>()); + ItemStack bookItem = new ItemStack(itemStack.getJavaId(), itemStack.getAmount(), components); + WritableBookContent List pages = tag.contains("pages") ? new LinkedList<>(((ListTag) tag.get("pages")).getValue()) : new LinkedList<>(); int page = packet.getPageNumber(); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEquipmentTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEquipmentTranslator.java index c178f27d4..6178a51e8 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEquipmentTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEquipmentTranslator.java @@ -31,10 +31,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.Client import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.LivingEntity; -import org.geysermc.geyser.entity.type.player.PlayerEntity; -import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.skin.FakeHeadProvider; import org.geysermc.geyser.translator.item.ItemTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; @@ -62,14 +59,15 @@ public class JavaSetEquipmentTranslator extends PacketTranslator { ItemStack javaItem = equipment.getItem(); - if (livingEntity instanceof PlayerEntity - && javaItem != null - && javaItem.getId() == Items.PLAYER_HEAD.javaId() - && javaItem.getNbt() != null) { - FakeHeadProvider.setHead(session, (PlayerEntity) livingEntity, javaItem.getNbt().get("SkullOwner")); - } else { - FakeHeadProvider.restoreOriginalSkin(session, livingEntity); - } + // TODO +// if (livingEntity instanceof PlayerEntity +// && javaItem != null +// && javaItem.getId() == Items.PLAYER_HEAD.javaId() +// && javaItem.getNbt() != null) { +// FakeHeadProvider.setHead(session, (PlayerEntity) livingEntity, javaItem.getNbt().get("SkullOwner")); +// } else { +// FakeHeadProvider.restoreOriginalSkin(session, livingEntity); +// } livingEntity.setHelmet(item); armorUpdated = true; diff --git a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java index 7f3a02df6..08c2b6cdb 100644 --- a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java @@ -25,13 +25,12 @@ package org.geysermc.geyser.util; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundPickItemPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundSetCreativeModeSlotPacket; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; @@ -43,11 +42,7 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket; import org.cloudburstmc.protocol.bedrock.packet.PlayerHotbarPacket; import org.geysermc.geyser.GeyserImpl; -import org.geysermc.geyser.inventory.Container; -import org.geysermc.geyser.inventory.GeyserItemStack; -import org.geysermc.geyser.inventory.Inventory; -import org.geysermc.geyser.inventory.LecternContainer; -import org.geysermc.geyser.inventory.PlayerInventory; +import org.geysermc.geyser.inventory.*; import org.geysermc.geyser.inventory.click.Click; import org.geysermc.geyser.inventory.recipe.GeyserRecipe; import org.geysermc.geyser.inventory.recipe.GeyserShapedRecipe; @@ -256,7 +251,7 @@ public class InventoryUtils { continue; } // If this is the item we're looking for - if (geyserItem.getJavaId() == itemStack.getId() && Objects.equals(geyserItem.getNbt(), itemStack.getNbt())) { + if (geyserItem.getJavaId() == itemStack.getId() && Objects.equals(geyserItem.getComponents(), itemStack.getDataComponents())) { //TODO verify setHotbarItem(session, i); // Don't check inventory if item was in hotbar return; @@ -270,7 +265,7 @@ public class InventoryUtils { continue; } // If this is the item we're looking for - if (geyserItem.getJavaId() == itemStack.getId() && Objects.equals(geyserItem.getNbt(), itemStack.getNbt())) { + if (geyserItem.getJavaId() == itemStack.getId() && Objects.equals(geyserItem.getComponents(), itemStack.getDataComponents())) { //TODO verify ServerboundPickItemPacket packetToSend = new ServerboundPickItemPacket(i); // https://wiki.vg/Protocol#Pick_Item session.sendDownstreamGamePacket(packetToSend); return; From ab8832b771deffb569a5558fa171faf587bd370e Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Sun, 21 Apr 2024 01:09:23 -0400 Subject: [PATCH 263/344] Compiles --- .../BedrockBlockPickRequestTranslator.java | 4 +- .../bedrock/BedrockBookEditTranslator.java | 52 +++++++++---------- .../player/BedrockActionTranslator.java | 2 +- 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java index 59317fd7c..3781ef3c0 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java @@ -69,7 +69,7 @@ public class BedrockBlockPickRequestTranslator extends PacketTranslator session.ensureInEventLoop(() -> { if (tag == null) { @@ -94,7 +94,7 @@ public class BedrockBlockPickRequestTranslator extends PacketTranslator if (itemStack != null) { DataComponents components = itemStack.getComponents() != null ? itemStack.getComponents() : new DataComponents(new HashMap<>()); ItemStack bookItem = new ItemStack(itemStack.getJavaId(), itemStack.getAmount(), components); - WritableBookContent - List pages = tag.contains("pages") ? new LinkedList<>(((ListTag) tag.get("pages")).getValue()) : new LinkedList<>(); + List pages = new LinkedList<>(); + + WritableBookContent writableBookContent = components.get(DataComponentType.WRITABLE_BOOK_CONTENT); + if (writableBookContent != null) { + for (Filterable page : writableBookContent.getPages()) { + pages.add(page.getRaw()); + } + } int page = packet.getPageNumber(); if (page < 0 || WrittenBookItem.MAXIMUM_PAGE_COUNT <= page) { @@ -69,21 +73,21 @@ public class BedrockBookEditTranslator extends PacketTranslator case ADD_PAGE: { // Add empty pages in between for (int i = pages.size(); i < page; i++) { - pages.add(i, new StringTag("", "")); + pages.add(i, ""); } - pages.add(page, new StringTag("", MessageTranslator.convertToPlainText(packet.getText()))); + pages.add(page, MessageTranslator.convertToPlainText(packet.getText())); break; } // Called whenever a page is modified case REPLACE_PAGE: { if (page < pages.size()) { - pages.set(page, new StringTag("", MessageTranslator.convertToPlainText(packet.getText()))); + pages.set(page, MessageTranslator.convertToPlainText(packet.getText())); } else { // Add empty pages in between for (int i = pages.size(); i < page; i++) { - pages.add(i, new StringTag("", "")); + pages.add(i, ""); } - pages.add(page, new StringTag("", MessageTranslator.convertToPlainText(packet.getText()))); + pages.add(page, MessageTranslator.convertToPlainText(packet.getText())); } break; } @@ -100,33 +104,29 @@ public class BedrockBookEditTranslator extends PacketTranslator } break; } - case SIGN_BOOK: { - tag.put(new StringTag("author", MessageTranslator.convertToPlainText(packet.getAuthor()))); - tag.put(new StringTag("title", MessageTranslator.convertToPlainText(packet.getTitle()))); - break; - } default: return; } // Remove empty pages at the end - while (pages.size() > 0) { - StringTag currentPage = (StringTag) pages.get(pages.size() - 1); - if (currentPage.getValue() == null || currentPage.getValue().isEmpty()) { + while (!pages.isEmpty()) { + String currentPage = pages.get(pages.size() - 1); + if (currentPage.isEmpty()) { pages.remove(pages.size() - 1); } else { break; } } - tag.put(new ListTag("pages", pages)); + + List> filterablePages = new ArrayList<>(pages.size()); + for (String raw : pages) { + filterablePages.add(new Filterable<>(raw, null)); + } + components.put(DataComponentType.WRITABLE_BOOK_CONTENT, new WritableBookContent(filterablePages)); + // Update local copy session.getPlayerInventory().setItem(36 + session.getPlayerInventory().getHeldItemSlot(), GeyserItemStack.from(bookItem), session); session.getInventoryTranslator().updateInventory(session, session.getPlayerInventory()); - List networkPages = new ArrayList<>(); - for (Tag pageTag : pages) { - networkPages.add(((StringTag) pageTag).getValue()); - } - String title; if (packet.getAction() == BookEditPacket.Action.SIGN_BOOK) { // Add title to packet so the server knows we're signing @@ -139,7 +139,7 @@ public class BedrockBookEditTranslator extends PacketTranslator title = null; } - session.getBookEditCache().setPacket(new ServerboundEditBookPacket(session.getPlayerInventory().getHeldItemSlot(), networkPages, title)); + session.getBookEditCache().setPacket(new ServerboundEditBookPacket(session.getPlayerInventory().getHeldItemSlot(), pages, title)); // There won't be any more book updates after this, so we can try sending the edit packet immediately if (packet.getAction() == BookEditPacket.Action.SIGN_BOOK) { session.getBookEditCache().checkForSend(); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java index f5122b256..2fd9ce405 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java @@ -168,7 +168,7 @@ public class BedrockActionTranslator extends PacketTranslator Date: Sun, 21 Apr 2024 16:20:22 -0400 Subject: [PATCH 264/344] Tiny fixes --- .../geyser/item/type/DecoratedPotItem.java | 21 ++++++++---- .../geyser/item/type/WrittenBookItem.java | 34 ++----------------- .../inventory/InventoryTranslator.java | 15 ++++---- 3 files changed, 24 insertions(+), 46 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java b/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java index 8d9be4db2..ea194522b 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java @@ -28,9 +28,14 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.nbt.NbtType; +import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; +import java.util.ArrayList; +import java.util.List; + public class DecoratedPotItem extends BlockItem { public DecoratedPotItem(String javaIdentifier, Builder builder) { @@ -41,12 +46,14 @@ public class DecoratedPotItem extends BlockItem { public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); - components.get(DataComponentType.POT_DECORATIONS); // TODO what does this look like on Bedrock? -// if (tag.remove("BlockEntityTag") instanceof CompoundTag blockEntityTag) { -// if (blockEntityTag.remove("sherds") instanceof ListTag sherds) { -// // bedrock wants it on the root level -// tag.put(sherds); -// } -// } + List decorations = components.get(DataComponentType.POT_DECORATIONS); // TODO maybe unbox in MCProtocolLib + if (decorations != null) { + List sherds = new ArrayList<>(decorations.size()); + for (Integer decoration : decorations) { + ItemMapping mapping = session.getItemMappings().getMapping(decoration); + sherds.add(mapping.getBedrockIdentifier()); + } + builder.putList("sherds", NbtType.STRING, sherds); + } } } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java b/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java index 6ca52aca4..a6b5e73d4 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java @@ -29,10 +29,6 @@ import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentT import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.mc.protocol.data.game.item.component.Filterable; import com.github.steveice10.mc.protocol.data.game.item.component.WrittenBookContent; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.ListTag; -import com.github.steveice10.opennbt.tag.builtin.StringTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; import net.kyori.adventure.text.Component; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtMap; @@ -47,7 +43,6 @@ import java.util.List; public class WrittenBookItem extends Item { public static final int MAXIMUM_PAGE_EDIT_LENGTH = 1024; - public static final int MAXIMUM_PAGE_LENGTH = 32768; public static final int MAXIMUM_PAGE_COUNT = 100; // Java edition limit. Bedrock edition has a limit of 50 pages. public static final int MAXIMUM_TITLE_LENGTH = 16; @@ -73,33 +68,8 @@ public class WrittenBookItem extends Item { builder.putList("pages", NbtType.COMPOUND, bedrockPages); builder.putString("title", bookContent.getTitle().getRaw()) - .putString("author", bookContent.getAuthor()); + .putString("author", bookContent.getAuthor()) + .putInt("generation", bookContent.getGeneration()); // TODO isResolved } - - private boolean isValidWrittenBook(CompoundTag tag) { - if (!(tag.get("title") instanceof StringTag title)) { - return false; - } - if (title.getValue().length() > (MAXIMUM_TITLE_LENGTH * 2)) { - // Java rejects books with titles more than 2x the maximum length allowed in the input box - return false; - } - - if (!(tag.get("author") instanceof StringTag)) { - return false; - } - - if (!(tag.get("pages") instanceof ListTag pages)) { - return false; - } - for (Tag pageTag : pages) { - if (pageTag instanceof StringTag page) { - if (page.getValue().length() > MAXIMUM_PAGE_LENGTH) { - return false; - } - } - } - return true; - } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java index e6e0c6340..2d7a1ae5a 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java @@ -25,11 +25,11 @@ package org.geysermc.geyser.translator.inventory; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; +import com.github.steveice10.mc.protocol.data.game.item.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; -import com.github.steveice10.opennbt.tag.builtin.IntTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; import it.unimi.dsi.fastutil.ints.*; import lombok.AllArgsConstructor; import org.checkerframework.checker.nullness.qual.Nullable; @@ -909,10 +909,11 @@ public abstract class InventoryTranslator { // As of 1.16.210: Bedrock needs confirmation on what the current item durability is. // If 0 is sent, then Bedrock thinks the item is not damaged int durability = 0; - if (itemStack.getNbt() != null) { - Tag damage = itemStack.getNbt().get("Damage"); - if (damage instanceof IntTag) { - durability = ItemUtils.getCorrectBedrockDurability(itemStack.asItem(), ((IntTag) damage).getValue()); + DataComponents components = itemStack.getComponents(); + if (components != null) { + Integer damage = components.get(DataComponentType.DAMAGE); + if (damage != null) { + durability = ItemUtils.getCorrectBedrockDurability(itemStack.asItem(), damage); } } From 61907b18512276bf2a3ba959caff6cd74a9d17e4 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sun, 21 Apr 2024 16:36:54 -0400 Subject: [PATCH 265/344] Little more work --- .../geyser/inventory/AnvilContainer.java | 3 +- .../geyser/inventory/GeyserItemStack.java | 25 +++++++++++++++++ .../updater/AnvilInventoryUpdater.java | 28 +++++++------------ .../translator/text/MessageTranslator.java | 10 +++++++ .../geysermc/geyser/util/InventoryUtils.java | 2 +- .../org/geysermc/geyser/util/ItemUtils.java | 17 ++++++----- 6 files changed, 56 insertions(+), 29 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/inventory/AnvilContainer.java b/core/src/main/java/org/geysermc/geyser/inventory/AnvilContainer.java index 9e0b83768..3c7b7e4bd 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/AnvilContainer.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/AnvilContainer.java @@ -29,6 +29,7 @@ import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundRenameItemPacket; import lombok.Getter; import lombok.Setter; +import net.kyori.adventure.text.Component; import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.text.MessageTranslator; @@ -72,7 +73,7 @@ public class AnvilContainer extends Container { String correctRename; newName = rename; - String originalName = ItemUtils.getCustomName(getInput().getNbt()); + Component originalName = ItemUtils.getCustomName(getInput().getComponents()); String plainOriginalName = MessageTranslator.convertToPlainTextLenient(originalName, session.locale()); String plainNewName = MessageTranslator.convertToPlainText(rename); diff --git a/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java b/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java index 7e621d3aa..a1ecc6f58 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.inventory; import com.github.steveice10.mc.protocol.data.game.item.ItemStack; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import lombok.AccessLevel; @@ -87,6 +88,30 @@ public class GeyserItemStack { return isEmpty() ? null : components; } + public boolean getComponent(DataComponentType type, boolean def) { + if (components == null) { + return def; + } + + Boolean result = components.get(type); + if (result != null) { + return result; + } + return def; + } + + public int getComponent(DataComponentType type, int def) { + if (components == null) { + return def; + } + + Integer result = components.get(type); + if (result != null) { + return result; + } + return def; + } + public int getNetId() { return isEmpty() ? 0 : netId; } diff --git a/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java b/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java index 96ef12861..9bf001f42 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.inventory.updater; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundRenameItemPacket; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; @@ -34,6 +35,7 @@ import com.github.steveice10.opennbt.tag.builtin.Tag; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntMaps; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import net.kyori.adventure.text.Component; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId; @@ -118,7 +120,8 @@ public class AnvilInventoryUpdater extends InventoryUpdater { // Changing the item in the input slot resets the name field on Bedrock, but // does not result in a FilterTextPacket - String originalName = MessageTranslator.convertToPlainTextLenient(ItemUtils.getCustomName(input.getNbt()), session.locale()); + // TODO test + String originalName = MessageTranslator.convertToPlainText(ItemUtils.getCustomName(input.getComponents())); ServerboundRenameItemPacket renameItemPacket = new ServerboundRenameItemPacket(originalName); session.sendDownstreamGamePacket(renameItemPacket); @@ -424,38 +427,27 @@ public class AnvilInventoryUpdater extends InventoryUpdater { } // This should really check the name field in all cases, but that requires the localized name // of the item which can change depending on NBT and Minecraft Edition - String originalName = ItemUtils.getCustomName(anvilContainer.getInput().getNbt()); + Component originalName = ItemUtils.getCustomName(anvilContainer.getInput().getComponents()); if (bedrock && originalName != null && anvilContainer.getNewName() != null) { // Check text and formatting - String legacyOriginalName = MessageTranslator.convertMessageLenient(originalName, session.locale()); + String legacyOriginalName = MessageTranslator.convertMessage(originalName, session.locale()); return !legacyOriginalName.equals(anvilContainer.getNewName()); } - return !Objects.equals(originalName, ItemUtils.getCustomName(anvilContainer.getResult().getNbt())); - } - - @SuppressWarnings("SameParameterValue") - private int getTagIntValueOr(GeyserItemStack itemStack, String tagName, int defaultValue) { - if (itemStack.getNbt() != null) { - Tag tag = itemStack.getNbt().get(tagName); - if (tag != null && tag.getValue() instanceof Number value) { - return value.intValue(); - } - } - return defaultValue; + return !Objects.equals(originalName, ItemUtils.getCustomName(anvilContainer.getResult().getComponents())); } private int getRepairCost(GeyserItemStack itemStack) { - return getTagIntValueOr(itemStack, "RepairCost", 0); + return itemStack.getComponent(DataComponentType.REPAIR_COST, 0); } private boolean hasDurability(GeyserItemStack itemStack) { if (itemStack.asItem().maxDamage() > 0) { - return getTagIntValueOr(itemStack, "Unbreakable", 0) == 0; + return itemStack.getComponent(DataComponentType.UNBREAKABLE, false); } return false; } private int getDamage(GeyserItemStack itemStack) { - return getTagIntValueOr(itemStack, "Damage", 0); + return itemStack.getComponent(DataComponentType.DAMAGE, 0); } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java index d93123cff..ed6b9404d 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java @@ -245,6 +245,16 @@ public class MessageTranslator { return GSON_SERIALIZER.serialize(component); } + /** + * Convert legacy format message to plain text + * + * @param message Message to convert + * @return The plain text of the message + */ + public static String convertToPlainText(Component message) { + return PlainTextComponentSerializer.plainText().serialize(message); + } + /** * Convert legacy format message to plain text * diff --git a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java index 08c2b6cdb..2b619714e 100644 --- a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java @@ -180,7 +180,7 @@ public class InventoryUtils { public static boolean canStack(GeyserItemStack item1, GeyserItemStack item2) { if (item1.isEmpty() || item2.isEmpty()) return false; - return item1.getJavaId() == item2.getJavaId() && Objects.equals(item1.getNbt(), item2.getNbt()); + return item1.getJavaId() == item2.getJavaId() && Objects.equals(item1.getComponents(), item2.getComponents()); } /** diff --git a/core/src/main/java/org/geysermc/geyser/util/ItemUtils.java b/core/src/main/java/org/geysermc/geyser/util/ItemUtils.java index a116c5cf2..2138103d4 100644 --- a/core/src/main/java/org/geysermc/geyser/util/ItemUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/ItemUtils.java @@ -25,10 +25,13 @@ package org.geysermc.geyser.util; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.Tag; +import net.kyori.adventure.text.Component; import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.FishingRodItem; @@ -70,17 +73,13 @@ public class ItemUtils { } /** - * @param itemTag the NBT tag of the item + * @param components the data components of the item * @return the custom name of the item */ - public static @Nullable String getCustomName(CompoundTag itemTag) { - if (itemTag != null) { - if (itemTag.get("display") instanceof CompoundTag displayTag) { - if (displayTag.get("Name") instanceof StringTag nameTag) { - return nameTag.getValue(); - } - } + public static @Nullable Component getCustomName(DataComponents components) { + if (components == null) { + return null; } - return null; + return components.get(DataComponentType.CUSTOM_NAME); } } From 57ce5706ee6fc7f2f674a95beef293cd84dd278a Mon Sep 17 00:00:00 2001 From: basaigh <53559772+basaigh@users.noreply.github.com> Date: Sun, 21 Apr 2024 21:49:56 +0100 Subject: [PATCH 266/344] Update mappings submodule --- core/src/main/resources/mappings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/resources/mappings b/core/src/main/resources/mappings index 4f89411d5..cb2cbe9f2 160000 --- a/core/src/main/resources/mappings +++ b/core/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit 4f89411d5bfb4e48699f635876d9c556e5c7e505 +Subproject commit cb2cbe9f262d14640f7c46885f1c8c9d23f2beaa From b73f23de0f190ae2b6942af083b9767059dc78dd Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Sun, 21 Apr 2024 22:54:54 +0200 Subject: [PATCH 267/344] remove global palette bits, fix nullable block entity tags --- .../java/org/geysermc/geyser/session/GeyserSession.java | 5 ----- .../geysermc/geyser/translator/level/BiomeTranslator.java | 4 ---- .../java/level/JavaLevelChunkWithLightTranslator.java | 8 ++++---- .../src/main/java/org/geysermc/geyser/util/MathUtils.java | 7 ------- 4 files changed, 4 insertions(+), 20 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 8e1ed2e51..994879f82 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -263,11 +263,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { @Setter private ItemMappings itemMappings; - /** - * Required to decode biomes correctly. - */ - @Setter - private int biomeGlobalPalette; /** * Stores the map between Java and Bedrock biome network IDs. */ 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 d4288c5a7..f05ed5ed1 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 @@ -31,7 +31,6 @@ import com.github.steveice10.mc.protocol.data.game.chunk.DataPalette; import com.github.steveice10.mc.protocol.data.game.chunk.palette.GlobalPalette; import com.github.steveice10.mc.protocol.data.game.chunk.palette.Palette; import com.github.steveice10.mc.protocol.data.game.chunk.palette.SingletonPalette; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import it.unimi.dsi.fastutil.ints.*; import org.geysermc.geyser.level.chunk.BlockStorage; import org.geysermc.geyser.level.chunk.bitarray.BitArray; @@ -39,7 +38,6 @@ import org.geysermc.geyser.level.chunk.bitarray.BitArrayVersion; import org.geysermc.geyser.level.chunk.bitarray.SingletonBitArray; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.util.MathUtils; import java.util.List; @@ -49,8 +47,6 @@ public class BiomeTranslator { public static void loadServerBiomes(GeyserSession session, List entries) { Int2IntMap biomeTranslations = new Int2IntOpenHashMap(); - session.setBiomeGlobalPalette(MathUtils.getGlobalPaletteForSize(entries.size())); - int greatestBiomeId = 0; for (int i = 0; i < entries.size(); i++) { RegistryEntry entry = entries.get(i); 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 a98ead719..e34c0d96d 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 @@ -98,7 +98,6 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator Date: Sun, 21 Apr 2024 22:22:15 +0100 Subject: [PATCH 268/344] Bump mcpl to fix item deserialization --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 08c04a84a..5e2720942 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ protocol-connection = "3.0.0.Beta1-20240411.165033-128" raknet = "1.0.0.CR3-20240416.144209-1" blockstateupdater="1.20.80-20240411.142413-1" mcauthlib = "d9d773e" -mcprotocollib = "897eb241b6" # Revert from jitpack after release +mcprotocollib = "2a7176f7ee" # Revert from jitpack after release adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" From c5e02d28e6adedeffcad6c2b2d4dddc4c8602bee Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Sun, 21 Apr 2024 23:48:30 +0200 Subject: [PATCH 269/344] ensure geyser builds --- .../java/org/geysermc/geyser/inventory/AnvilContainer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/inventory/AnvilContainer.java b/core/src/main/java/org/geysermc/geyser/inventory/AnvilContainer.java index 3c7b7e4bd..1c5826cdb 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/AnvilContainer.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/AnvilContainer.java @@ -29,7 +29,6 @@ import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundRenameItemPacket; import lombok.Getter; import lombok.Setter; -import net.kyori.adventure.text.Component; import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.text.MessageTranslator; @@ -73,7 +72,8 @@ public class AnvilContainer extends Container { String correctRename; newName = rename; - Component originalName = ItemUtils.getCustomName(getInput().getComponents()); + // TODO 1.20.5 fix properly - this name is apparently nullable?? + String originalName = MessageTranslator.convertMessage(ItemUtils.getCustomName(getInput().getComponents())); String plainOriginalName = MessageTranslator.convertToPlainTextLenient(originalName, session.locale()); String plainNewName = MessageTranslator.convertToPlainText(rename); From 8381a148fc3557534cd250ba9b0eb3871a3e49f5 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Sun, 21 Apr 2024 19:23:05 -0400 Subject: [PATCH 270/344] Fix book signing --- .../translator/protocol/bedrock/BedrockBookEditTranslator.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBookEditTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBookEditTranslator.java index 8e045a51c..4350f6a83 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBookEditTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBookEditTranslator.java @@ -104,6 +104,9 @@ public class BedrockBookEditTranslator extends PacketTranslator } break; } + case SIGN_BOOK: { + break; + } default: return; } From dac5f69d47aa74f46c2ca0bd0a3d505879f8f20e Mon Sep 17 00:00:00 2001 From: basaigh <53559772+basaigh@users.noreply.github.com> Date: Mon, 22 Apr 2024 20:56:57 +0100 Subject: [PATCH 271/344] Bump mcpl --- .../java/org/geysermc/geyser/item/type/ArmorItem.java | 11 +++++------ .../org/geysermc/geyser/item/type/GoatHornItem.java | 3 ++- gradle/libs.versions.toml | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java index ba7f05205..33ff6a7d8 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java @@ -52,16 +52,15 @@ public class ArmorItem extends Item { ArmorTrim trim = components.get(DataComponentType.TRIM); if (trim != null) { - // TODO material IDs - String material = trim.getMaterial().getAssetName(); - String pattern = trim.getPattern().getAssetId(); - // discard custom trim patterns/materials to prevent visual glitches on bedrock - if (!material.startsWith("minecraft:") - || !pattern.startsWith("minecraft:")) { + if (trim.getMaterial().isCustom() || trim.getPattern().isCustom()) { return; } + // TODO material IDs + String material = trim.getMaterial().getCustomValue().getAssetName(); + String pattern = trim.getPattern().getCustomValue().getAssetId(); + NbtMapBuilder trimBuilder = NbtMap.builder(); // bedrock has an uppercase first letter key, and the value is not namespaced trimBuilder.put("Material", stripNamespace(material)); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java b/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java index 48e75dc79..35b7a76fc 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.item.type; +import com.github.steveice10.mc.protocol.data.game.Holder; import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; @@ -60,7 +61,7 @@ public class GoatHornItem extends Item { if (components == null) { return builder; } - Instrument instrument = components.get(DataComponentType.INSTRUMENT); + Holder instrument = components.get(DataComponentType.INSTRUMENT); // TODO registry if (instrument != null) { // Drop the Minecraft namespace if applicable diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5e2720942..4189f8857 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ protocol-connection = "3.0.0.Beta1-20240411.165033-128" raknet = "1.0.0.CR3-20240416.144209-1" blockstateupdater="1.20.80-20240411.142413-1" mcauthlib = "d9d773e" -mcprotocollib = "2a7176f7ee" # Revert from jitpack after release +mcprotocollib = "8bc6990525" # Revert from jitpack after release adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" From c34f0f2c3b1b2f0ca024dd53899746f2cc3fbeab Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Mon, 22 Apr 2024 16:36:03 -0400 Subject: [PATCH 272/344] Update for latest MCProtocolLib --- .../main/java/org/geysermc/geyser/item/type/ArmorItem.java | 6 +++--- gradle/libs.versions.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java index 33ff6a7d8..ab936bd08 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java @@ -53,13 +53,13 @@ public class ArmorItem extends Item { ArmorTrim trim = components.get(DataComponentType.TRIM); if (trim != null) { // discard custom trim patterns/materials to prevent visual glitches on bedrock - if (trim.getMaterial().isCustom() || trim.getPattern().isCustom()) { + if (trim.material().isCustom() || trim.pattern().isCustom()) { return; } // TODO material IDs - String material = trim.getMaterial().getCustomValue().getAssetName(); - String pattern = trim.getPattern().getCustomValue().getAssetId(); + String material = trim.material().custom().assetName(); + String pattern = trim.pattern().custom().assetId(); NbtMapBuilder trimBuilder = NbtMap.builder(); // bedrock has an uppercase first letter key, and the value is not namespaced diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4189f8857..b7e692ab7 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ protocol-connection = "3.0.0.Beta1-20240411.165033-128" raknet = "1.0.0.CR3-20240416.144209-1" blockstateupdater="1.20.80-20240411.142413-1" mcauthlib = "d9d773e" -mcprotocollib = "8bc6990525" # Revert from jitpack after release +mcprotocollib = "4ee05b62" # Revert from jitpack after release adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" From 6a5efa3c9dc1aa7d3d29a5dd17378195104fb1d6 Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Mon, 22 Apr 2024 23:36:48 +0200 Subject: [PATCH 273/344] Start on 1.20.5 mod platform support - NeoForge (temporarily) excluded Also fixes lecterns, and block break speed calculations --- .github/workflows/build-remote.yml | 2 +- .github/workflows/build.yml | 2 +- .github/workflows/preview.yml | 2 +- bootstrap/mod/build.gradle.kts | 3 +- .../fabric/src/main/resources/fabric.mod.json | 5 +- .../platform/mod/ModPingPassthrough.java | 5 +- .../mod/command/ModCommandSender.java | 3 +- .../mod/world/GeyserModWorldManager.java | 153 +++++------------- .../geyser.modded-conventions.gradle.kts | 10 +- build.gradle.kts | 2 +- .../inventory/LecternInventoryTranslator.java | 22 ++- .../level/JavaBlockDestructionTranslator.java | 3 +- .../org/geysermc/geyser/util/BlockUtils.java | 45 +++--- .../org/geysermc/geyser/util/ItemUtils.java | 28 ++-- settings.gradle.kts | 4 +- 15 files changed, 110 insertions(+), 179 deletions(-) diff --git a/.github/workflows/build-remote.yml b/.github/workflows/build-remote.yml index d49920785..09326d429 100644 --- a/.github/workflows/build-remote.yml +++ b/.github/workflows/build-remote.yml @@ -64,7 +64,7 @@ jobs: with: name: Geyser NeoForge path: geyser/bootstrap/mod/neoforge/build/libs/Geyser-NeoForge.jar - if-no-files-found: error + #if-no-files-found: error // TODO 1.20.5 until neoforge updates - name: Archive artifacts (Geyser Standalone) uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 if: success() diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 284fa265a..cfb509f30 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -68,7 +68,7 @@ jobs: with: name: Geyser NeoForge path: bootstrap/mod/neoforge/build/libs/Geyser-NeoForge.jar - if-no-files-found: error + #if-no-files-found: error // TODO 1.20.5 - currently no neoforge artifacts - name: Archive artifacts (Geyser Standalone) uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 if: success() diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index 13712d5ef..a33c71a79 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -53,10 +53,10 @@ jobs: with: appID: ${{ secrets.RELEASE_APP_ID }} appPrivateKey: ${{ secrets.RELEASE_APP_PK }} + # neoforge:Geyser-NeoForge.jar // TODO 1.20.5 files: | bungeecord:Geyser-BungeeCord.jar fabric:Geyser-Fabric.jar - neoforge:Geyser-NeoForge.jar spigot:Geyser-Spigot.jar standalone:Geyser-Standalone.jar velocity:Geyser-Velocity.jar diff --git a/bootstrap/mod/build.gradle.kts b/bootstrap/mod/build.gradle.kts index 7651a2df2..281fd45e7 100644 --- a/bootstrap/mod/build.gradle.kts +++ b/bootstrap/mod/build.gradle.kts @@ -1,5 +1,6 @@ architectury { - common("neoforge", "fabric") + common("fabric") + //common("neoforge", "fabric") // todo 1.20.5 } loom { diff --git a/bootstrap/mod/fabric/src/main/resources/fabric.mod.json b/bootstrap/mod/fabric/src/main/resources/fabric.mod.json index 6bd217433..7fb6b302c 100644 --- a/bootstrap/mod/fabric/src/main/resources/fabric.mod.json +++ b/bootstrap/mod/fabric/src/main/resources/fabric.mod.json @@ -23,9 +23,8 @@ "geyser.mixins.json" ], "depends": { - "fabricloader": ">=0.15.2", + "fabricloader": ">=0.15.10", "fabric": "*", - "minecraft": ">=1.20.4", - "fabric-permissions-api-v0": "*" + "minecraft": ">=1.20.4" } } diff --git a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/ModPingPassthrough.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/ModPingPassthrough.java index 12d690d83..a2bbfa379 100644 --- a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/ModPingPassthrough.java +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/ModPingPassthrough.java @@ -29,6 +29,7 @@ import lombok.AllArgsConstructor; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import net.minecraft.core.RegistryAccess; import net.minecraft.network.Connection; import net.minecraft.network.PacketSendListener; import net.minecraft.network.protocol.Packet; @@ -69,7 +70,7 @@ public class ModPingPassthrough implements IGeyserPingPassthrough { StatusInterceptor connection = new StatusInterceptor(); ServerStatusPacketListener statusPacketListener = new ServerStatusPacketListenerImpl(status, connection); - statusPacketListener.handleStatusRequest(new ServerboundStatusRequestPacket()); + statusPacketListener.handleStatusRequest(ServerboundStatusRequestPacket.INSTANCE); // mods like MiniMOTD (that inject into the above method) have now processed the response status = Objects.requireNonNull(connection.status, "status response"); } catch (Exception e) { @@ -79,7 +80,7 @@ public class ModPingPassthrough implements IGeyserPingPassthrough { } } - String jsonDescription = net.minecraft.network.chat.Component.Serializer.toJson(status.description()); + String jsonDescription = net.minecraft.network.chat.Component.Serializer.toJson(status.description(), RegistryAccess.EMPTY); String legacyDescription = LEGACY_SERIALIZER.serialize(GSON_SERIALIZER.deserializeOr(jsonDescription, Component.empty())); return new GeyserPingInfo( diff --git a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/command/ModCommandSender.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/command/ModCommandSender.java index 17154ffd8..5bebfae93 100644 --- a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/command/ModCommandSender.java +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/command/ModCommandSender.java @@ -27,6 +27,7 @@ package org.geysermc.geyser.platform.mod.command; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.minecraft.commands.CommandSourceStack; +import net.minecraft.core.RegistryAccess; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import org.checkerframework.checker.nullness.qual.NonNull; @@ -63,7 +64,7 @@ public class ModCommandSender implements GeyserCommandSource { public void sendMessage(net.kyori.adventure.text.Component message) { if (source.getEntity() instanceof ServerPlayer player) { String decoded = GsonComponentSerializer.gson().serialize(message); - player.displayClientMessage(Objects.requireNonNull(Component.Serializer.fromJson(decoded)), false); + player.displayClientMessage(Objects.requireNonNull(Component.Serializer.fromJson(decoded, RegistryAccess.EMPTY)), false); return; } GeyserCommandSource.super.sendMessage(message); diff --git a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/world/GeyserModWorldManager.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/world/GeyserModWorldManager.java index 04c538632..e9d612976 100644 --- a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/world/GeyserModWorldManager.java +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/world/GeyserModWorldManager.java @@ -27,37 +27,28 @@ package org.geysermc.geyser.platform.mod.world; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityInfo; +import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import net.minecraft.SharedConstants; import net.minecraft.core.BlockPos; -import net.minecraft.nbt.ByteArrayTag; -import net.minecraft.nbt.ByteTag; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.DoubleTag; -import net.minecraft.nbt.EndTag; -import net.minecraft.nbt.FloatTag; -import net.minecraft.nbt.IntArrayTag; -import net.minecraft.nbt.IntTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.LongArrayTag; -import net.minecraft.nbt.LongTag; -import net.minecraft.nbt.ShortTag; -import net.minecraft.nbt.StringTag; -import net.minecraft.nbt.Tag; -import net.minecraft.nbt.TagVisitor; +import net.minecraft.core.RegistryAccess; +import net.minecraft.core.component.DataComponents; +import net.minecraft.network.chat.Component; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.network.Filterable; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.WritableBookItem; -import net.minecraft.world.item.WrittenBookItem; +import net.minecraft.world.item.component.WritableBookContent; +import net.minecraft.world.item.component.WrittenBookContent; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BannerBlockEntity; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.LecternBlockEntity; import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.world.level.chunk.ChunkStatus; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunkSection; +import net.minecraft.world.level.chunk.status.ChunkStatus; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; @@ -72,10 +63,12 @@ import org.geysermc.geyser.util.BlockEntityUtils; import java.util.ArrayList; import java.util.List; -import java.util.Objects; import java.util.concurrent.CompletableFuture; public class GeyserModWorldManager extends GeyserWorldManager { + + private static final GsonComponentSerializer GSON_SERIALIZER = GsonComponentSerializer.gson(); + private static final LegacyComponentSerializer LEGACY_SERIALIZER = LegacyComponentSerializer.legacySection(); private final MinecraftServer server; public GeyserModWorldManager(MinecraftServer server) { @@ -180,7 +173,7 @@ public class GeyserModWorldManager extends GeyserWorldManager { } ItemStack book = lectern.getBook(); - int pageCount = WrittenBookItem.getPageCount(book); + int pageCount = getPageCount(book); boolean hasBookPages = pageCount > 0; NbtMapBuilder lecternTag = LecternUtils.getBaseLecternTag(x, y, z, hasBookPages ? pageCount : 1); lecternTag.putInt("page", lectern.getPage() / 2); @@ -189,11 +182,9 @@ public class GeyserModWorldManager extends GeyserWorldManager { .putShort("Damage", (short) 0) .putString("Name", "minecraft:writable_book"); List pages = new ArrayList<>(hasBookPages ? pageCount : 1); - if (hasBookPages && WritableBookItem.makeSureTagIsValid(book.getTag())) { - ListTag listTag = book.getTag().getList("pages", 8); - - for (int i = 0; i < listTag.size(); i++) { - String page = listTag.getString(i); + if (hasBookPages) { + List bookPages = getPages(book); + for (String page : bookPages) { NbtMapBuilder pageBuilder = NbtMap.builder() .putString("photoname", "") .putString("text", page); @@ -243,9 +234,8 @@ public class GeyserModWorldManager extends GeyserWorldManager { // Potentially exposes other NBT data? But we need to get the NBT data for the banner patterns *and* // the banner might have a custom name, both of which a Java client knows and caches ItemStack itemStack = banner.getItem(); - var tag = OpenNbtTagVisitor.convert("", itemStack.getOrCreateTag()); - future.complete(tag); + future.complete(null); // todo 1.20.5 return; } future.complete(null); @@ -257,95 +247,32 @@ public class GeyserModWorldManager extends GeyserWorldManager { return server.getPlayerList().getPlayer(session.getPlayerEntity().getUuid()); } - // Future considerations: option to clone; would affect arrays - private static class OpenNbtTagVisitor implements TagVisitor { - private String currentKey; - private final com.github.steveice10.opennbt.tag.builtin.CompoundTag root; - private com.github.steveice10.opennbt.tag.builtin.Tag currentTag; - - OpenNbtTagVisitor(String key) { - root = new com.github.steveice10.opennbt.tag.builtin.CompoundTag(key); + private static int getPageCount(ItemStack itemStack) { + WrittenBookContent writtenBookContent = itemStack.get(DataComponents.WRITTEN_BOOK_CONTENT); + if (writtenBookContent != null) { + return writtenBookContent.pages().size(); + } else { + WritableBookContent writableBookContent = itemStack.get(DataComponents.WRITABLE_BOOK_CONTENT); + return writableBookContent != null ? writableBookContent.pages().size() : 0; } + } - @Override - public void visitString(StringTag stringTag) { - currentTag = new com.github.steveice10.opennbt.tag.builtin.StringTag(currentKey, stringTag.getAsString()); - } - - @Override - public void visitByte(ByteTag byteTag) { - currentTag = new com.github.steveice10.opennbt.tag.builtin.ByteTag(currentKey, byteTag.getAsByte()); - } - - @Override - public void visitShort(ShortTag shortTag) { - currentTag = new com.github.steveice10.opennbt.tag.builtin.ShortTag(currentKey, shortTag.getAsShort()); - } - - @Override - public void visitInt(IntTag intTag) { - currentTag = new com.github.steveice10.opennbt.tag.builtin.IntTag(currentKey, intTag.getAsInt()); - } - - @Override - public void visitLong(LongTag longTag) { - currentTag = new com.github.steveice10.opennbt.tag.builtin.LongTag(currentKey, longTag.getAsLong()); - } - - @Override - public void visitFloat(FloatTag floatTag) { - currentTag = new com.github.steveice10.opennbt.tag.builtin.FloatTag(currentKey, floatTag.getAsFloat()); - } - - @Override - public void visitDouble(DoubleTag doubleTag) { - currentTag = new com.github.steveice10.opennbt.tag.builtin.DoubleTag(currentKey, doubleTag.getAsDouble()); - } - - @Override - public void visitByteArray(ByteArrayTag byteArrayTag) { - currentTag = new com.github.steveice10.opennbt.tag.builtin.ByteArrayTag(currentKey, byteArrayTag.getAsByteArray()); - } - - @Override - public void visitIntArray(IntArrayTag intArrayTag) { - currentTag = new com.github.steveice10.opennbt.tag.builtin.IntArrayTag(currentKey, intArrayTag.getAsIntArray()); - } - - @Override - public void visitLongArray(LongArrayTag longArrayTag) { - currentTag = new com.github.steveice10.opennbt.tag.builtin.LongArrayTag(currentKey, longArrayTag.getAsLongArray()); - } - - @Override - public void visitList(ListTag listTag) { - var newList = new com.github.steveice10.opennbt.tag.builtin.ListTag(currentKey); - for (Tag tag : listTag) { - currentKey = ""; - tag.accept(this); - newList.add(currentTag); + private static List getPages(ItemStack itemStack) { + WrittenBookContent writtenBookContent = itemStack.get(DataComponents.WRITTEN_BOOK_CONTENT); + if (writtenBookContent != null) { + return writtenBookContent.pages().stream() + .map(Filterable::raw) + .map((component) -> Component.Serializer.toJson(component, RegistryAccess.EMPTY)) + .map((json -> LEGACY_SERIALIZER.serialize(GSON_SERIALIZER.deserializeOr(json, net.kyori.adventure.text.Component.empty())))) + .toList(); + } else { + WritableBookContent writableBookContent = itemStack.get(DataComponents.WRITABLE_BOOK_CONTENT); + if (writableBookContent == null) { + return List.of(); } - currentTag = newList; - } - - @Override - public void visitCompound(@NonNull CompoundTag compoundTag) { - currentTag = convert(currentKey, compoundTag); - } - - private static com.github.steveice10.opennbt.tag.builtin.CompoundTag convert(String name, CompoundTag compoundTag) { - OpenNbtTagVisitor visitor = new OpenNbtTagVisitor(name); - for (String key : compoundTag.getAllKeys()) { - visitor.currentKey = key; - Tag tag = Objects.requireNonNull(compoundTag.get(key)); - tag.accept(visitor); - visitor.root.put(visitor.currentTag); - } - return visitor.root; - } - - @Override - public void visitEnd(@NonNull EndTag endTag) { + return writableBookContent.pages().stream() + .map(Filterable::raw) + .toList(); } } } diff --git a/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts b/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts index 3d41dbbb4..c83ea2911 100644 --- a/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts @@ -46,6 +46,12 @@ loom { silentMojangMappingsLicense() } +indra { + javaVersions { + target(21) + } +} + configurations { create("includeTransitive").isTransitive = true } @@ -104,7 +110,7 @@ afterEvaluate { } dependencies { - minecraft("com.mojang:minecraft:1.20.4") + minecraft("com.mojang:minecraft:1.20.5-rc3") mappings(loom.officialMojangMappings()) } @@ -128,6 +134,6 @@ modrinth { syncBodyFrom.set(rootProject.file("README.md").readText()) uploadFile.set(tasks.getByPath("remapModrinthJar")) - gameVersions.addAll("1.20.4") + gameVersions.addAll("1.20.5") failSilently.set(true) } \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index dfdff2187..fdacd5538 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -22,7 +22,7 @@ val basePlatforms = setOf( val moddedPlatforms = setOf( projects.fabric, - projects.neoforge, + //projects.neoforge, // todo 1.20.5 projects.mod ).map { it.dependencyProject } diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java index 9d0661b08..7dff2647c 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java @@ -26,10 +26,11 @@ package org.geysermc.geyser.translator.inventory; import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; +import com.github.steveice10.mc.protocol.data.game.item.component.WritableBookContent; +import com.github.steveice10.mc.protocol.data.game.item.component.WrittenBookContent; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClosePacket; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.ListTag; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; @@ -152,7 +153,6 @@ public class LecternInventoryTranslator extends AbstractBlockInventoryTranslator session.setDroppingLecternBook(false); InventoryUtils.closeInventory(session, inventory.getJavaId(), false); } else if (lecternContainer.getBlockEntityTag() == null) { - CompoundTag tag = book.getNbt(); Vector3i position = lecternContainer.isUsingRealBlock() ? session.getLastInteractionBlockPosition() : inventory.getHolderPosition(); // If shouldExpectLecternHandled returns true, this is already handled for us @@ -163,10 +163,20 @@ public class LecternInventoryTranslator extends AbstractBlockInventoryTranslator && !GameProtocol.is1_20_60orHigher(session.getUpstream().getProtocolVersion()); NbtMap blockEntityTag; - if (tag != null) { - int pagesSize = ((ListTag) tag.get("pages")).size(); + if (book.getComponents() != null) { + int pages = 0; + WrittenBookContent writtenBookComponents = book.getComponents().get(DataComponentType.WRITTEN_BOOK_CONTENT); + if (writtenBookComponents != null) { + pages = writtenBookComponents.getPages().size(); + } else { + WritableBookContent writableBookComponents = book.getComponents().get(DataComponentType.WRITABLE_BOOK_CONTENT); + if (writableBookComponents != null) { + pages = writableBookComponents.getPages().size(); + } + } + ItemData itemData = book.getItemData(session); - NbtMapBuilder lecternTag = LecternUtils.getBaseLecternTag(position.getX(), position.getY(), position.getZ(), pagesSize); + NbtMapBuilder lecternTag = LecternUtils.getBaseLecternTag(position.getX(), position.getY(), position.getZ(), pages); lecternTag.putCompound("book", NbtMap.builder() .putByte("Count", (byte) itemData.getCount()) .putShort("Damage", (short) 0) diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockDestructionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockDestructionTranslator.java index 2a9af8fbf..2fdba716b 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockDestructionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockDestructionTranslator.java @@ -26,7 +26,6 @@ package org.geysermc.geyser.translator.protocol.java.level; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundBlockDestructionPacket; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.cloudburstmc.protocol.bedrock.data.LevelEvent; import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket; import org.geysermc.geyser.registry.BlockRegistries; @@ -43,7 +42,7 @@ public class JavaBlockDestructionTranslator extends PacketTranslator session.getTagCache().isAxeEffective(blockMapping); + case "hoe" -> session.getTagCache().isHoeEffective(blockMapping); + case "pickaxe" -> session.getTagCache().isPickaxeEffective(blockMapping); + case "shears" -> session.getTagCache().isShearsEffective(blockMapping); + case "shovel" -> session.getTagCache().isShovelEffective(blockMapping); + case "sword" -> blockMapping.getJavaBlockId() == BlockStateValues.JAVA_COBWEB_ID; + default -> { session.getGeyser().getLogger().warning("Unknown tool type: " + itemToolType); - return false; - } + yield false; + } + }; } private static double toolBreakTimeBonus(String toolType, String toolTier, boolean isShearsEffective) { if (toolType.equals("shears")) return isShearsEffective ? 5.0 : 15.0; - if (toolType.equals("")) return 1.0; + if (toolType.isEmpty()) return 1.0; return switch (toolTier) { // https://minecraft.wiki/w/Breaking#Speed case "wooden" -> 2.0; @@ -134,7 +130,7 @@ public final class BlockUtils { return 1.0 / speed; } - public static double getBreakTime(GeyserSession session, BlockMapping blockMapping, ItemMapping item, @Nullable CompoundTag nbtData, boolean isSessionPlayer) { + public static double getBreakTime(GeyserSession session, BlockMapping blockMapping, ItemMapping item, @Nullable DataComponents components, boolean isSessionPlayer) { boolean isShearsEffective = session.getTagCache().isShearsEffective(blockMapping); //TODO called twice boolean canHarvestWithHand = blockMapping.isCanBreakWithHand(); String toolType = ""; @@ -147,7 +143,8 @@ public final class BlockUtils { correctTool = correctTool(session, blockMapping, toolType); toolCanBreak = canToolTierBreakBlock(session, blockMapping, toolTier); } - int toolEfficiencyLevel = ItemUtils.getEnchantmentLevel(nbtData, "minecraft:efficiency"); + + int toolEfficiencyLevel = ItemUtils.getEnchantmentLevel(components, Enchantment.JavaEnchantment.EFFICIENCY.ordinal()); int hasteLevel = 0; int miningFatigueLevel = 0; @@ -162,7 +159,7 @@ public final class BlockUtils { boolean waterInEyes = session.getCollisionManager().isWaterInEyes(); boolean insideOfWaterWithoutAquaAffinity = waterInEyes && - ItemUtils.getEnchantmentLevel(session.getPlayerInventory().getItem(5).getNbt(), "minecraft:aqua_affinity") < 1; + ItemUtils.getEnchantmentLevel(session.getPlayerInventory().getItem(5).getComponents(), Enchantment.JavaEnchantment.AQUA_AFFINITY.ordinal()) < 1; return calculateBreakTime(blockMapping.getHardness(), toolTier, canHarvestWithHand, correctTool, toolCanBreak, toolType, isShearsEffective, toolEfficiencyLevel, hasteLevel, miningFatigueLevel, insideOfWaterWithoutAquaAffinity, session.getPlayerEntity().isOnGround()); @@ -172,12 +169,12 @@ public final class BlockUtils { PlayerInventory inventory = session.getPlayerInventory(); GeyserItemStack item = inventory.getItemInHand(); ItemMapping mapping = ItemMapping.AIR; - CompoundTag nbtData = null; + DataComponents components = null; if (item != null) { mapping = item.getMapping(session); - nbtData = item.getNbt(); + components = item.getComponents(); } - return getBreakTime(session, blockMapping, mapping, nbtData, true); + return getBreakTime(session, blockMapping, mapping, components, true); } /** diff --git a/core/src/main/java/org/geysermc/geyser/util/ItemUtils.java b/core/src/main/java/org/geysermc/geyser/util/ItemUtils.java index 2138103d4..b1591e911 100644 --- a/core/src/main/java/org/geysermc/geyser/util/ItemUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/ItemUtils.java @@ -27,10 +27,7 @@ package org.geysermc.geyser.util; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.ListTag; -import com.github.steveice10.opennbt.tag.builtin.StringTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; +import com.github.steveice10.mc.protocol.data.game.item.component.ItemEnchantments; import net.kyori.adventure.text.Component; import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.item.Items; @@ -39,24 +36,17 @@ import org.geysermc.geyser.item.type.Item; public class ItemUtils { - public static int getEnchantmentLevel(@Nullable CompoundTag itemNBTData, String enchantmentId) { - if (itemNBTData == null) { + public static int getEnchantmentLevel(@Nullable DataComponents components, int enchantmentId) { + if (components == null) { return 0; } - ListTag enchantments = itemNBTData.get("Enchantments"); - if (enchantments != null) { - for (Tag tag : enchantments) { - CompoundTag enchantment = (CompoundTag) tag; - StringTag enchantId = enchantment.get("id"); - if (enchantId.getValue().equals(enchantmentId)) { - Tag lvl = enchantment.get("lvl"); - if (lvl != null && lvl.getValue() instanceof Number number) { - return number.intValue(); - } - } - } + + ItemEnchantments enchantmentData = components.get(DataComponentType.ENCHANTMENTS); + if (enchantmentData == null) { + return 0; } - return 0; + + return enchantmentData.getEnchantments().getOrDefault(enchantmentId, 0); } /** diff --git a/settings.gradle.kts b/settings.gradle.kts index a39bfa3d2..3867d7a84 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -66,7 +66,7 @@ include(":ap") include(":api") include(":bungeecord") include(":fabric") -include(":neoforge") +//include(":neoforge") // todo 1.20.5 include(":mod") include(":spigot") include(":standalone") @@ -78,7 +78,7 @@ include(":core") // Specify project dirs project(":bungeecord").projectDir = file("bootstrap/bungeecord") project(":fabric").projectDir = file("bootstrap/mod/fabric") -project(":neoforge").projectDir = file("bootstrap/mod/neoforge") +//project(":neoforge").projectDir = file("bootstrap/mod/neoforge") // todo 1.20.5 project(":mod").projectDir = file("bootstrap/mod") project(":spigot").projectDir = file("bootstrap/spigot") project(":standalone").projectDir = file("bootstrap/standalone") From 11f79d4e2c955b35f353eb7bacd5b354a9ca9278 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Mon, 22 Apr 2024 19:40:50 -0400 Subject: [PATCH 274/344] Refactor Java registry storage; implement trim support --- .../geyser/inventory/recipe/TrimRecipe.java | 91 ++++++----- .../geysermc/geyser/item/type/ArmorItem.java | 19 +-- .../geysermc/geyser/level/JavaDimension.java | 14 ++ .../geyser/session/GeyserSession.java | 35 +--- .../geyser/session/cache/RegistryCache.java | 153 ++++++++++++++++++ .../geysermc/geyser/text/TextDecoration.java | 12 ++ .../translator/level/BiomeTranslator.java | 58 ++----- .../java/JavaRegistryDataTranslator.java | 35 +--- .../java/JavaUpdateRecipesTranslator.java | 4 +- .../translator/text/MessageTranslator.java | 2 +- .../org/geysermc/geyser/util/ChunkUtils.java | 2 +- 11 files changed, 253 insertions(+), 172 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java diff --git a/core/src/main/java/org/geysermc/geyser/inventory/recipe/TrimRecipe.java b/core/src/main/java/org/geysermc/geyser/inventory/recipe/TrimRecipe.java index 584928e65..441f050a7 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/recipe/TrimRecipe.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/recipe/TrimRecipe.java @@ -25,63 +25,68 @@ package org.geysermc.geyser.inventory.recipe; +import com.github.steveice10.mc.protocol.data.game.RegistryEntry; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.StringTag; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.TextColor; import org.cloudburstmc.protocol.bedrock.data.TrimMaterial; import org.cloudburstmc.protocol.bedrock.data.TrimPattern; import org.cloudburstmc.protocol.bedrock.data.inventory.descriptor.ItemDescriptorWithCount; import org.cloudburstmc.protocol.bedrock.data.inventory.descriptor.ItemTagDescriptor; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; +import org.geysermc.geyser.registry.type.ItemMapping; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.text.MessageTranslator; /** - * Hardcoded recipe information about armor trims until further improvements can be made. This information was scraped - * from BDS 1.19.81 with a world with the next_major_update and sniffer features enabled, using ProxyPass. + * Stores information on trim materials and patterns, including smithing armor hacks for pre-1.20. */ -public class TrimRecipe { - - // For TrimDataPacket, which BDS sends just before the CraftingDataPacket - public static final List PATTERNS; - public static final List MATERIALS; - +public final class TrimRecipe { // For CraftingDataPacket public static final String ID = "minecraft:smithing_armor_trim"; public static final ItemDescriptorWithCount BASE = tagDescriptor("minecraft:trimmable_armors"); public static final ItemDescriptorWithCount ADDITION = tagDescriptor("minecraft:trim_materials"); public static final ItemDescriptorWithCount TEMPLATE = tagDescriptor("minecraft:trim_templates"); - static { - List patterns = new ArrayList<>(16); - patterns.add(new TrimPattern("minecraft:ward_armor_trim_smithing_template", "ward")); - patterns.add(new TrimPattern("minecraft:sentry_armor_trim_smithing_template", "sentry")); - patterns.add(new TrimPattern("minecraft:snout_armor_trim_smithing_template", "snout")); - patterns.add(new TrimPattern("minecraft:dune_armor_trim_smithing_template", "dune")); - patterns.add(new TrimPattern("minecraft:spire_armor_trim_smithing_template", "spire")); - patterns.add(new TrimPattern("minecraft:tide_armor_trim_smithing_template", "tide")); - patterns.add(new TrimPattern("minecraft:wild_armor_trim_smithing_template", "wild")); - patterns.add(new TrimPattern("minecraft:rib_armor_trim_smithing_template", "rib")); - patterns.add(new TrimPattern("minecraft:coast_armor_trim_smithing_template", "coast")); - patterns.add(new TrimPattern("minecraft:shaper_armor_trim_smithing_template", "shaper")); - patterns.add(new TrimPattern("minecraft:eye_armor_trim_smithing_template", "eye")); - patterns.add(new TrimPattern("minecraft:vex_armor_trim_smithing_template", "vex")); - patterns.add(new TrimPattern("minecraft:silence_armor_trim_smithing_template", "silence")); - patterns.add(new TrimPattern("minecraft:wayfinder_armor_trim_smithing_template", "wayfinder")); - patterns.add(new TrimPattern("minecraft:raiser_armor_trim_smithing_template", "raiser")); - patterns.add(new TrimPattern("minecraft:host_armor_trim_smithing_template", "host")); - PATTERNS = Collections.unmodifiableList(patterns); + public static TrimMaterial readTrimMaterial(GeyserSession session, RegistryEntry entry) { + String key = stripNamespace(entry.getId()); - List materials = new ArrayList<>(10); - materials.add(new TrimMaterial("quartz", "§h", "minecraft:quartz")); - materials.add(new TrimMaterial("iron", "§i", "minecraft:iron_ingot")); - materials.add(new TrimMaterial("netherite", "§j", "minecraft:netherite_ingot")); - materials.add(new TrimMaterial("redstone", "§m", "minecraft:redstone")); - materials.add(new TrimMaterial("copper", "§n", "minecraft:copper_ingot")); - materials.add(new TrimMaterial("gold", "§p", "minecraft:gold_ingot")); - materials.add(new TrimMaterial("emerald", "§q", "minecraft:emerald")); - materials.add(new TrimMaterial("diamond", "§s", "minecraft:diamond")); - materials.add(new TrimMaterial("lapis", "§t", "minecraft:lapis_lazuli")); - materials.add(new TrimMaterial("amethyst", "§u", "minecraft:amethyst_shard")); - MATERIALS = Collections.unmodifiableList(materials); + // Color is used when hovering over the item + // Find the nearest legacy color from the RGB Java gives us to work with + // Also yes this is a COMPLETE hack but it works ok!!!!! + StringTag colorTag = ((CompoundTag) entry.getData().get("description")).get("color"); + TextColor color = TextColor.fromHexString(colorTag.getValue()); + String legacy = MessageTranslator.convertMessage(Component.space().color(color)); + + String itemIdentifier = ((StringTag) entry.getData().get("ingredient")).getValue(); + ItemMapping itemMapping = session.getItemMappings().getMapping(itemIdentifier); + if (itemMapping == null) { + // This should never happen so not sure what to do here. + itemMapping = ItemMapping.AIR; + } + // Just pick out the resulting color code, without RESET in front. + return new TrimMaterial(key, legacy.substring(2).trim(), itemMapping.getBedrockIdentifier()); + } + + public static TrimPattern readTrimPattern(GeyserSession session, RegistryEntry entry) { + String key = stripNamespace(entry.getId()); + + String itemIdentifier = ((StringTag) entry.getData().get("template_item")).getValue(); + ItemMapping itemMapping = session.getItemMappings().getMapping(itemIdentifier); + if (itemMapping == null) { + // This should never happen so not sure what to do here. + itemMapping = ItemMapping.AIR; + } + return new TrimPattern(itemMapping.getBedrockIdentifier(), key); + } + + // TODO find a good place for a stripNamespace util method + private static String stripNamespace(String identifier) { + int i = identifier.indexOf(':'); + if (i >= 0) { + return identifier.substring(i + 1); + } + return identifier; } private TrimRecipe() { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java index ab936bd08..773b850c0 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java @@ -33,6 +33,8 @@ import com.github.steveice10.opennbt.tag.builtin.StringTag; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; +import org.cloudburstmc.protocol.bedrock.data.TrimMaterial; +import org.cloudburstmc.protocol.bedrock.data.TrimPattern; import org.geysermc.geyser.item.ArmorMaterial; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; @@ -57,14 +59,13 @@ public class ArmorItem extends Item { return; } - // TODO material IDs - String material = trim.material().custom().assetName(); - String pattern = trim.pattern().custom().assetId(); + TrimMaterial material = session.getRegistryCache().trimMaterials().get(trim.material().id()); + TrimPattern pattern = session.getRegistryCache().trimPatterns().get(trim.pattern().id()); NbtMapBuilder trimBuilder = NbtMap.builder(); // bedrock has an uppercase first letter key, and the value is not namespaced - trimBuilder.put("Material", stripNamespace(material)); - trimBuilder.put("Pattern", stripNamespace(pattern)); + trimBuilder.put("Material", material.getMaterialId()); + trimBuilder.put("Pattern", pattern.getPatternId()); builder.putCompound("Trim", trimBuilder.build()); } } @@ -86,12 +87,4 @@ public class ArmorItem extends Item { public boolean isValidRepairItem(Item other) { return material.getRepairIngredient() == other; } - - private static String stripNamespace(String identifier) { - int i = identifier.indexOf(':'); - if (i >= 0) { - return identifier.substring(i + 1); - } - return identifier; - } } diff --git a/core/src/main/java/org/geysermc/geyser/level/JavaDimension.java b/core/src/main/java/org/geysermc/geyser/level/JavaDimension.java index 6e7223da0..4babc3af0 100644 --- a/core/src/main/java/org/geysermc/geyser/level/JavaDimension.java +++ b/core/src/main/java/org/geysermc/geyser/level/JavaDimension.java @@ -55,4 +55,18 @@ public record JavaDimension(int minY, int maxY, boolean piglinSafe, double world map.put(i, new JavaDimension(minY, maxY, piglinSafe, coordinateScale)); } } + + public static JavaDimension read(RegistryEntry entry) { + CompoundTag dimension = entry.getData(); + int minY = ((IntTag) dimension.get("min_y")).getValue(); + int maxY = ((IntTag) dimension.get("height")).getValue(); + // Logical height can be ignored probably - seems to be for artificial limits like the Nether. + + // Set if piglins/hoglins should shake + boolean piglinSafe = ((Number) dimension.get("piglin_safe").getValue()).byteValue() != (byte) 0; + // Load world coordinate scale for the world border + double coordinateScale = ((Number) dimension.get("coordinate_scale").getValue()).doubleValue(); + + return new JavaDimension(minY, maxY, piglinSafe, coordinateScale); + } } diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 994879f82..9ae1f6f49 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -44,7 +44,6 @@ import com.github.steveice10.mc.protocol.data.game.statistic.CustomStatistic; import com.github.steveice10.mc.protocol.data.game.statistic.Statistic; import com.github.steveice10.mc.protocol.packet.common.serverbound.ServerboundClientInformationPacket; import com.github.steveice10.mc.protocol.packet.handshake.serverbound.ClientIntentionPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatCommandPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatCommandSignedPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosPacket; @@ -54,11 +53,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.Server import com.github.steveice10.mc.protocol.packet.login.serverbound.ServerboundCustomQueryAnswerPacket; import com.github.steveice10.packetlib.BuiltinFlags; import com.github.steveice10.packetlib.Session; -import com.github.steveice10.packetlib.event.session.ConnectedEvent; -import com.github.steveice10.packetlib.event.session.DisconnectedEvent; -import com.github.steveice10.packetlib.event.session.PacketErrorEvent; -import com.github.steveice10.packetlib.event.session.PacketSendingEvent; -import com.github.steveice10.packetlib.event.session.SessionAdapter; +import com.github.steveice10.packetlib.event.session.*; import com.github.steveice10.packetlib.packet.Packet; import com.github.steveice10.packetlib.tcp.TcpClientSession; import com.github.steveice10.packetlib.tcp.TcpSession; @@ -66,8 +61,6 @@ import io.netty.channel.Channel; import io.netty.channel.EventLoop; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.longs.Long2ObjectMap; -import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; @@ -146,7 +139,6 @@ import org.geysermc.geyser.session.cache.*; import org.geysermc.geyser.skin.FloodgateSkinUploader; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.text.MinecraftLocale; -import org.geysermc.geyser.text.TextDecoration; import org.geysermc.geyser.translator.inventory.InventoryTranslator; import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.util.ChunkUtils; @@ -158,16 +150,7 @@ import java.net.ConnectException; import java.net.InetSocketAddress; import java.nio.charset.StandardCharsets; import java.time.Instant; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.BitSet; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Queue; -import java.util.Set; -import java.util.UUID; +import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ScheduledFuture; @@ -214,6 +197,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { private final LodestoneCache lodestoneCache; private final PistonCache pistonCache; private final PreferencesCache preferencesCache; + private final RegistryCache registryCache; private final SkullCache skullCache; private final StructureBlockCache structureBlockCache; private final TagCache tagCache; @@ -263,12 +247,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { @Setter private ItemMappings itemMappings; - /** - * Stores the map between Java and Bedrock biome network IDs. - */ - @Setter - private int[] biomeTranslations = null; - /** * A map of Vector3i positions to Java entities. * Used for translating Bedrock block actions to Java entity actions. @@ -360,12 +338,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { @MonotonicNonNull @Setter private JavaDimension dimensionType = null; - /** - * All dimensions that the client could possibly connect to. - */ - private final Int2ObjectMap dimensions = new Int2ObjectOpenHashMap<>(4); - - private final Int2ObjectMap chatTypes = new Int2ObjectOpenHashMap<>(7); @Setter private int breakingBlock; @@ -619,6 +591,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { this.lodestoneCache = new LodestoneCache(); this.pistonCache = new PistonCache(this); this.preferencesCache = new PreferencesCache(this); + this.registryCache = new RegistryCache(this); this.skullCache = new SkullCache(this); this.structureBlockCache = new StructureBlockCache(); this.tagCache = new TagCache(); diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java new file mode 100644 index 000000000..44a5469b8 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2019-2024 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.session.cache; + +import com.github.steveice10.mc.protocol.data.game.RegistryEntry; +import com.github.steveice10.mc.protocol.packet.configuration.clientbound.ClientboundRegistryDataPacket; +import it.unimi.dsi.fastutil.ints.Int2IntMap; +import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.experimental.Accessors; +import org.cloudburstmc.protocol.bedrock.data.TrimMaterial; +import org.cloudburstmc.protocol.bedrock.data.TrimPattern; +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.inventory.recipe.TrimRecipe; +import org.geysermc.geyser.level.JavaDimension; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.text.TextDecoration; +import org.geysermc.geyser.translator.level.BiomeTranslator; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.function.ToIntFunction; + +/** + * Stores any information sent via Java registries. May not contain all data in a given registry - we'll strip what's + * unneeded. + * + * Crafted as of 1.20.5 for easy "add new registry" in the future. + */ +@Accessors(fluent = true) +@Getter +public final class RegistryCache { + private static final Map>> REGISTRIES = new HashMap<>(); + + static { + register("chat_type", cache -> cache.chatTypes, ($, entry) -> TextDecoration.readChatType(entry)); + register("dimension_type", cache -> cache.dimensions, ($, entry) -> JavaDimension.read(entry)); + register("trim_material", cache -> cache.trimMaterials, TrimRecipe::readTrimMaterial); + register("trim_pattern", cache -> cache.trimPatterns, TrimRecipe::readTrimPattern); + register("worldgen/biome", (cache, array) -> cache.biomeTranslations = array, BiomeTranslator::loadServerBiome); + } + + @Getter(AccessLevel.NONE) + private final GeyserSession session; + + /** + * Java -> Bedrock biome network IDs. + */ + private int[] biomeTranslations; + private final Int2ObjectMap chatTypes = new Int2ObjectOpenHashMap<>(7); + /** + * All dimensions that the client could possibly connect to. + */ + private final Int2ObjectMap dimensions = new Int2ObjectOpenHashMap<>(4); + private final Int2ObjectMap trimMaterials = new Int2ObjectOpenHashMap<>(); + private final Int2ObjectMap trimPatterns = new Int2ObjectOpenHashMap<>(); + + public RegistryCache(GeyserSession session) { + this.session = session; + } + + /** + * Loads a registry in, if we are tracking it. + */ + public void load(ClientboundRegistryDataPacket packet) { + var reader = REGISTRIES.get(packet.getRegistry()); + if (reader != null) { + reader.accept(this, packet.getEntries()); + } else { + GeyserImpl.getInstance().getLogger().debug("Ignoring registry of type " + packet.getRegistry()); + } + } + + /** + * @param registry the Java registry resource location, without the "minecraft:" prefix. + * @param localCacheFunction which local field in RegistryCache are we caching entries for this registry? + * @param reader converts the RegistryEntry NBT into a class file + * @param the class that represents these entries. + */ + private static void register(String registry, Function> localCacheFunction, BiFunction reader) { + REGISTRIES.put("minecraft:" + registry, (registryCache, entries) -> { + Int2ObjectMap localCache = localCacheFunction.apply(registryCache); + // Clear each local cache every time a new registry entry is given to us + localCache.clear(); + for (int i = 0; i < entries.size(); i++) { + RegistryEntry entry = entries.get(i); + // This is what Geyser wants to keep as a value for this registry. + T cacheEntry = reader.apply(registryCache.session, entry); + localCache.put(i, cacheEntry); + } + // Trim registry down to needed size + if (localCache instanceof Int2ObjectOpenHashMap hashMap) { + hashMap.trim(); + } + }); + } + + /** + * @param localCacheFunction the int array to set the final values to. + */ + private static void register(String registry, BiConsumer localCacheFunction, ToIntFunction reader) { + REGISTRIES.put("minecraft:" + registry, (registryCache, entries) -> { + Int2IntMap temp = new Int2IntOpenHashMap(); + int greatestId = 0; + for (int i = 0; i < entries.size(); i++) { + RegistryEntry entry = entries.get(i); + // This is what Geyser wants to keep as a value for this registry. + int cacheEntry = reader.applyAsInt(entry); + temp.put(i, cacheEntry); + if (i > greatestId) { + // Maximum registry ID, so far. Make sure the final array is at least this large. + greatestId = i; + } + } + + int[] array = new int[greatestId + 1]; + for (Int2IntMap.Entry entry : temp.int2IntEntrySet()) { + array[entry.getIntKey()] = entry.getIntValue(); + } + localCacheFunction.accept(registryCache, array); + }); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/text/TextDecoration.java b/core/src/main/java/org/geysermc/geyser/text/TextDecoration.java index 121e1b2b9..bad55a5ca 100644 --- a/core/src/main/java/org/geysermc/geyser/text/TextDecoration.java +++ b/core/src/main/java/org/geysermc/geyser/text/TextDecoration.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.text; +import com.github.steveice10.mc.protocol.data.game.RegistryEntry; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; @@ -87,6 +88,17 @@ public final class TextDecoration { '}'; } + public static TextDecoration readChatType(RegistryEntry entry) { + // Note: The ID is NOT ALWAYS THE SAME! ViaVersion as of 1.19 adds two registry entries that do NOT match vanilla. + CompoundTag tag = entry.getData(); + CompoundTag chat = tag.get("chat"); + TextDecoration textDecoration = null; + if (chat != null) { + textDecoration = new TextDecoration(chat); + } + return textDecoration; + } + public enum Parameter { CONTENT, SENDER, 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 f05ed5ed1..fce928bdb 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 @@ -31,7 +31,9 @@ import com.github.steveice10.mc.protocol.data.game.chunk.DataPalette; import com.github.steveice10.mc.protocol.data.game.chunk.palette.GlobalPalette; import com.github.steveice10.mc.protocol.data.game.chunk.palette.Palette; import com.github.steveice10.mc.protocol.data.game.chunk.palette.SingletonPalette; -import it.unimi.dsi.fastutil.ints.*; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; +import it.unimi.dsi.fastutil.ints.IntLists; import org.geysermc.geyser.level.chunk.BlockStorage; import org.geysermc.geyser.level.chunk.bitarray.BitArray; import org.geysermc.geyser.level.chunk.bitarray.BitArrayVersion; @@ -39,58 +41,20 @@ import org.geysermc.geyser.level.chunk.bitarray.SingletonBitArray; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.session.GeyserSession; -import java.util.List; - // Array index formula by https://wiki.vg/Chunk_Format public class BiomeTranslator { - public static void loadServerBiomes(GeyserSession session, List entries) { - Int2IntMap biomeTranslations = new Int2IntOpenHashMap(); - - int greatestBiomeId = 0; - for (int i = 0; i < entries.size(); i++) { - RegistryEntry entry = entries.get(i); - String javaIdentifier = entry.getId(); - int bedrockId = Registries.BIOME_IDENTIFIERS.get().getOrDefault(javaIdentifier, 0); - int javaId = i; - if (javaId > greatestBiomeId) { - greatestBiomeId = javaId; - } - - // TODO - the category tag no longer exists - find a better replacement option -// if (bedrockId == -1) { -// // There is no matching Bedrock variation for this biome; let's set the closest match based on biome category -// String category = ((StringTag) ((CompoundTag) biomeTag.get("element")).get("category")).getValue(); -// String replacementBiome = switch (category) { -// case "extreme_hills" -> "minecraft:mountains"; -// case "icy" -> "minecraft:ice_spikes"; -// case "mesa" -> "minecraft:badlands"; -// case "mushroom" -> "minecraft:mushroom_fields"; -// case "nether" -> "minecraft:nether_wastes"; -// default -> "minecraft:ocean"; // Typically ID 0 so a good default -// case "taiga", "jungle", "plains", "savanna", "the_end", "beach", "ocean", "desert", "river", "swamp" -> "minecraft:" + category; -// }; -// bedrockId = Registries.BIOME_IDENTIFIERS.get().getInt(replacementBiome); -// } - - // When we see the Java ID, we should instead apply the Bedrock ID - biomeTranslations.put(javaId, bedrockId); - - if (javaId == 0) { - // Matches Java behavior when it sees an invalid biome - it just replaces it with ID 0 - biomeTranslations.defaultReturnValue(bedrockId); - } - } - - int[] biomes = new int[greatestBiomeId + 1]; - for (Int2IntMap.Entry entry : biomeTranslations.int2IntEntrySet()) { - biomes[entry.getIntKey()] = entry.getIntValue(); - } - session.setBiomeTranslations(biomes); + public static int loadServerBiome(RegistryEntry entry) { + String javaIdentifier = entry.getId(); + return Registries.BIOME_IDENTIFIERS.get().getOrDefault(javaIdentifier, 0); +// if (javaId == 0) { +// // Matches Java behavior when it sees an invalid biome - it just replaces it with ID 0 +// biomeTranslations.defaultReturnValue(bedrockId); +// } } public static BlockStorage toNewBedrockBiome(GeyserSession session, DataPalette biomeData) { - int[] biomeTranslations = session.getBiomeTranslations(); + int[] biomeTranslations = session.getRegistryCache().biomeTranslations(); // As of 1.17.10: the client expects the same format as a chunk but filled with biomes // As of 1.18 this is the same as Java Edition diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaRegistryDataTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaRegistryDataTranslator.java index 5d9bbff7d..ddb9c76b7 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaRegistryDataTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaRegistryDataTranslator.java @@ -25,49 +25,16 @@ package org.geysermc.geyser.translator.protocol.java; -import com.github.steveice10.mc.protocol.data.game.RegistryEntry; import com.github.steveice10.mc.protocol.packet.configuration.clientbound.ClientboundRegistryDataPacket; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import org.geysermc.geyser.level.JavaDimension; import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.text.TextDecoration; -import org.geysermc.geyser.translator.level.BiomeTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; -import java.util.List; - @Translator(packet = ClientboundRegistryDataPacket.class) public class JavaRegistryDataTranslator extends PacketTranslator { @Override public void translate(GeyserSession session, ClientboundRegistryDataPacket packet) { - if (packet.getRegistry().equals("minecraft:dimension_type")) { - Int2ObjectMap dimensions = session.getDimensions(); - dimensions.clear(); - JavaDimension.load(packet.getEntries(), dimensions); - } - - if (packet.getRegistry().equals("minecraft:chat_type")) { - Int2ObjectMap chatTypes = session.getChatTypes(); - chatTypes.clear(); - List entries = packet.getEntries(); - for (int i = 0; i < entries.size(); i++) { - // The ID is NOT ALWAYS THE SAME! ViaVersion as of 1.19 adds two registry entries that do NOT match vanilla. - RegistryEntry entry = entries.get(i); - CompoundTag tag = entry.getData(); - CompoundTag chat = tag.get("chat"); - TextDecoration textDecoration = null; - if (chat != null) { - textDecoration = new TextDecoration(chat); - } - chatTypes.put(i, textDecoration); - } - } - - if (packet.getRegistry().equals("minecraft:worldgen/biome")) { - BiomeTranslator.loadServerBiomes(session, packet.getEntries()); - } + session.getRegistryCache().load(packet); } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java index aca02feab..20b223248 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java @@ -269,8 +269,8 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator Date: Mon, 22 Apr 2024 22:49:46 -0400 Subject: [PATCH 275/344] Banners --- .../geyser/inventory/item/BannerPattern.java | 104 +++++++++++++ .../geyser/inventory/item/DyeColor.java | 75 +++++++++ .../geysermc/geyser/item/type/BannerItem.java | 145 ++++++++++++------ .../geyser/session/cache/RegistryCache.java | 4 + .../inventory/LoomInventoryTranslator.java | 27 +--- .../entity/BannerBlockEntityTranslator.java | 4 +- .../bedrock/BedrockBookEditTranslator.java | 1 + 7 files changed, 295 insertions(+), 65 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/inventory/item/BannerPattern.java create mode 100644 core/src/main/java/org/geysermc/geyser/inventory/item/DyeColor.java diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/BannerPattern.java b/core/src/main/java/org/geysermc/geyser/inventory/item/BannerPattern.java new file mode 100644 index 000000000..442690d7d --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/inventory/item/BannerPattern.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2019-2024 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.inventory.item; + +import lombok.Getter; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.Locale; + +@Getter +public enum BannerPattern { + BASE("b"), + SQUARE_BOTTOM_LEFT("bl"), + SQUARE_BOTTOM_RIGHT("br"), + SQUARE_TOP_LEFT("tl"), + SQUARE_TOP_RIGHT("tr"), + STRIPE_BOTTOM("bs"), + STRIPE_TOP("ts"), + STRIPE_LEFT("ls"), + STRIPE_RIGHT("rs"), + STRIPE_CENTER("cs"), + STRIPE_MIDDLE("ms"), + STRIPE_DOWNRIGHT("drs"), + STRIPE_DOWNLEFT("dls"), + SMALL_STRIPES("ss"), + CROSS("cr"), + STRAIGHT_CROSS("sc"), + TRIANGLE_BOTTOM("bt"), + TRIANGLE_TOP("tt"), + TRIANGLES_BOTTOM("bts"), + TRIANGLES_TOP("tts"), + DIAGONAL_LEFT("ld"), + DIAGONAL_UP_RIGHT("rd"), + DIAGONAL_UP_LEFT("lud"), + DIAGONAL_RIGHT("rud"), + CIRCLE("mc"), + RHOMBUS("mr"), + HALF_VERTICAL("vh"), + HALF_HORIZONTAL("hh"), + HALF_VERTICAL_RIGHT("vhr"), + HALF_HORIZONTAL_BOTTOM("hhb"), + BORDER("bo"), + CURLY_BORDER("cbo"), + GRADIENT("gra"), + GRADIENT_UP("gru"), + BRICKS("bri"), + GLOBE("glb"), + CREEPER("cre"), + SKULL("sku"), + FLOWER("flo"), + MOJANG("moj"), + PIGLIN("pig"); + + private static final BannerPattern[] VALUES = values(); + + private final String javaIdentifier; + private final String bedrockIdentifier; + + BannerPattern(String bedrockIdentifier) { + this.javaIdentifier = "minecraft:" + this.name().toLowerCase(Locale.ROOT); + this.bedrockIdentifier = bedrockIdentifier; + } + + public static @Nullable BannerPattern getByJavaIdentifier(String javaIdentifier) { + for (BannerPattern bannerPattern : VALUES) { + if (bannerPattern.javaIdentifier.equals(javaIdentifier)) { + return bannerPattern; + } + } + return null; + } + + public static @Nullable BannerPattern getByBedrockIdentifier(String bedrockIdentifier) { + for (BannerPattern bannerPattern : VALUES) { + if (bannerPattern.bedrockIdentifier.equals(bedrockIdentifier)) { + return bannerPattern; + } + } + return null; + } +} diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/DyeColor.java b/core/src/main/java/org/geysermc/geyser/inventory/item/DyeColor.java new file mode 100644 index 000000000..e2649a343 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/inventory/item/DyeColor.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2019-2024 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.inventory.item; + +import lombok.Getter; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.Locale; + +@Getter +public enum DyeColor { + WHITE, + ORANGE, + MAGENTA, + LIGHT_BLUE, + YELLOW, + LIME, + PINK, + GRAY, + LIGHT_GRAY, + CYAN, + PURPLE, + BLUE, + BROWN, + GREEN, + RED, + BLACK; + + private static final DyeColor[] VALUES = values(); + + private final String javaIdentifier; + + DyeColor() { + this.javaIdentifier = this.name().toLowerCase(Locale.ROOT); + } + + public static @Nullable DyeColor getById(int id) { + if (id >= 0 && id < VALUES.length) { + return VALUES[id]; + } + return null; + } + + public static @Nullable DyeColor getByJavaIdentifier(String javaIdentifier) { + for (DyeColor dyeColor : VALUES) { + if (dyeColor.javaIdentifier.equals(javaIdentifier)) { + return dyeColor; + } + } + return null; + } +} diff --git a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java index 32806c3c2..0d8050dec 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java @@ -28,14 +28,14 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.protocol.data.game.item.component.BannerPatternLayer; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.IntTag; -import com.github.steveice10.opennbt.tag.builtin.ListTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; +import com.github.steveice10.opennbt.tag.builtin.*; +import it.unimi.dsi.fastutil.Pair; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtList; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtType; +import org.geysermc.geyser.inventory.item.BannerPattern; +import org.geysermc.geyser.inventory.item.DyeColor; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; @@ -51,20 +51,48 @@ public class BannerItem extends BlockItem { * ominous banners that we set instead. This variable is used to detect Java ominous banner patterns, and apply * the correct ominous banner pattern if Bedrock pulls the item from creative. */ - public static final List OMINOUS_BANNER_PATTERN; + private static final List> OMINOUS_BANNER_PATTERN; + private static final ListTag OMINOUS_BANNER_PATTERN_BLOCK; static { // Construct what an ominous banner is supposed to look like OMINOUS_BANNER_PATTERN = List.of( -// new BannerPatternLayer("mr", 9), -// new BannerPatternLayer("bs", 8), -// new BannerPatternLayer("cs", 7), -// new BannerPatternLayer("bo", 8), -// new BannerPatternLayer("ms", 15), -// new BannerPatternLayer("hh", 8), -// new BannerPatternLayer("mc", 8), -// new BannerPatternLayer("bo", 15) + Pair.of(BannerPattern.RHOMBUS, DyeColor.CYAN), + Pair.of(BannerPattern.STRIPE_BOTTOM, DyeColor.LIGHT_GRAY), + Pair.of(BannerPattern.STRIPE_CENTER, DyeColor.GRAY), + Pair.of(BannerPattern.BORDER, DyeColor.LIGHT_GRAY), + Pair.of(BannerPattern.STRIPE_MIDDLE, DyeColor.BLACK), + Pair.of(BannerPattern.HALF_HORIZONTAL, DyeColor.LIGHT_GRAY), + Pair.of(BannerPattern.CIRCLE, DyeColor.LIGHT_GRAY), + Pair.of(BannerPattern.BORDER, DyeColor.BLACK) ); + + OMINOUS_BANNER_PATTERN_BLOCK = new ListTag("patterns"); + for (Pair pair : OMINOUS_BANNER_PATTERN) { + OMINOUS_BANNER_PATTERN_BLOCK.add(getJavaBannerPatternTag(pair.left(), pair.right())); + } + } + + public static boolean isOminous(GeyserSession session, List patternLayers) { + if (OMINOUS_BANNER_PATTERN.size() != patternLayers.size()) { + return false; + } + for (int i = 0; i < OMINOUS_BANNER_PATTERN.size(); i++) { + BannerPatternLayer patternLayer = patternLayers.get(i); + Pair pair = OMINOUS_BANNER_PATTERN.get(i); + if (!patternLayer.getPattern().isId() || patternLayer.getColorId() != pair.right().ordinal()) { + return false; + } + BannerPattern bannerPattern = session.getRegistryCache().bannerPatterns().get(patternLayer.getPattern().id()); + if (bannerPattern != pair.left()) { + return false; + } + } + return true; + } + + public static boolean isOminous(ListTag blockEntityPatterns) { + return OMINOUS_BANNER_PATTERN_BLOCK.equals(blockEntityPatterns); } /** @@ -76,7 +104,10 @@ public class BannerItem extends BlockItem { public static NbtList convertBannerPattern(ListTag patterns) { List tagsList = new ArrayList<>(); for (Tag patternTag : patterns.getValue()) { - tagsList.add(getBedrockBannerPattern((CompoundTag) patternTag)); + NbtMap bedrockBannerPattern = getBedrockBannerPattern((CompoundTag) patternTag); + if (bedrockBannerPattern != null) { + tagsList.add(bedrockBannerPattern); + } } return new NbtList<>(NbtType.COMPOUND, tagsList); @@ -88,35 +119,41 @@ public class BannerItem extends BlockItem { * @param pattern Java edition pattern nbt * @return The Bedrock edition format pattern nbt */ - @NonNull private static NbtMap getBedrockBannerPattern(CompoundTag pattern) { + BannerPattern bannerPattern = BannerPattern.getByJavaIdentifier((String) pattern.get("pattern").getValue()); + DyeColor dyeColor = DyeColor.getByJavaIdentifier((String) pattern.get("color").getValue()); + if (bannerPattern == null || dyeColor == null) { + return null; + } + return NbtMap.builder() - .putInt("Color", 15 - (int) pattern.get("Color").getValue()) - .putString("Pattern", (String) pattern.get("Pattern").getValue()) + .putString("Pattern", bannerPattern.getBedrockIdentifier()) + .putInt("Color", 15 - dyeColor.ordinal()) .build(); } + public static CompoundTag getJavaBannerPatternTag(BannerPattern bannerPattern, DyeColor dyeColor) { + CompoundTag tag = new CompoundTag(""); + tag.put(new StringTag("pattern", bannerPattern.getJavaIdentifier())); + tag.put(new StringTag("color", dyeColor.getJavaIdentifier())); + return tag; + } + /** * Convert the Bedrock edition banner pattern nbt to Java edition * * @param pattern Bedrock edition pattern nbt - * @return The Java edition format pattern nbt + * @return The Java edition format pattern layer */ - public static CompoundTag getJavaBannerPattern(NbtMap pattern) { - //return new BannerPatternLayer(0/*pattern.getString("Pattern")*/, 15 - pattern.getInt("Color")); - return null; - } - - /** - * Convert a list of patterns from Java nbt to Bedrock nbt, or vice versa (we just need to invert the color) - * - * @param patterns The patterns to convert - */ - private void invertBannerColors(ListTag patterns) { - for (Tag patternTag : patterns.getValue()) { - IntTag color = ((CompoundTag) patternTag).get("Color"); - color.setValue(15 - color.getValue()); + public static BannerPatternLayer getJavaBannerPattern(GeyserSession session, NbtMap pattern) { + return null; // TODO + /*Int2ObjectBiMap registry = session.getRegistryCache().bannerPatterns(); + BannerPattern bannerPattern = BannerPattern.getByBedrockIdentifier(pattern.getString("Pattern")); + DyeColor dyeColor = DyeColor.getById(15 - pattern.getInt("Color")); + if (bannerPattern != null && dyeColor != null && registry.containsValue(bannerPattern)) { + return new BannerPatternLayer(Holder.ofId(registry.get(bannerPattern)), dyeColor.ordinal()); } + return null;*/ } public BannerItem(String javaIdentifier, Builder builder) { @@ -129,31 +166,51 @@ public class BannerItem extends BlockItem { List patterns = components.get(DataComponentType.BANNER_PATTERNS); if (patterns != null) { -// if (patterns.equals(OMINOUS_BANNER_PATTERN)) { -// // Remove the current patterns and set the ominous banner type -// builder.putInt("Type", 1); -// } else { -// invertBannerColors(patterns); -// tag.put(patterns); -// } + if (isOminous(session, patterns)) { + // Remove the current patterns and set the ominous banner type + builder.putInt("Type", 1); + } else { + List patternList = new ArrayList<>(patterns.size()); + for (BannerPatternLayer patternLayer : patterns) { + patternLayer.getPattern().ifId(holder -> { + BannerPattern bannerPattern = session.getRegistryCache().bannerPatterns().get(holder.id()); + if (bannerPattern != null) { + NbtMap tag = NbtMap.builder() + .putString("Pattern", bannerPattern.getBedrockIdentifier()) + .putInt("Color", 15 - patternLayer.getColorId()) + .build(); + patternList.add(tag); + } + }); + } + builder.putList("Patterns", NbtType.COMPOUND, patternList); + } } } @Override - public void translateNbtToJava(@NonNull CompoundTag tag, @NonNull ItemMapping mapping) { + public void translateNbtToJava(@NonNull CompoundTag tag, @NonNull ItemMapping mapping) { // TODO super.translateNbtToJava(tag, mapping); if (tag.get("Type") instanceof IntTag type && type.getValue() == 1) { // Ominous banner pattern tag.remove("Type"); CompoundTag blockEntityTag = new CompoundTag("BlockEntityTag"); - //blockEntityTag.put(OMINOUS_BANNER_PATTERN); + blockEntityTag.put(OMINOUS_BANNER_PATTERN_BLOCK); tag.put(blockEntityTag); - } else if (tag.get("Patterns") instanceof ListTag patterns) { + } else if (tag.get("Patterns") instanceof ListTag patterns && patterns.getElementType() == CompoundTag.class) { CompoundTag blockEntityTag = new CompoundTag("BlockEntityTag"); - invertBannerColors(patterns); - blockEntityTag.put(patterns); + + ListTag javaPatterns = new ListTag("patterns"); + for (Tag pattern : patterns.getValue()) { + BannerPattern bannerPattern = BannerPattern.getByBedrockIdentifier((String) ((CompoundTag) pattern).get("Pattern").getValue()); + DyeColor dyeColor = DyeColor.getById((int) ((CompoundTag) pattern).get("Color").getValue()); + if (bannerPattern != null && dyeColor != null) { + javaPatterns.add(getJavaBannerPatternTag(bannerPattern, dyeColor)); + } + } + blockEntityTag.put(javaPatterns); tag.put(blockEntityTag); tag.remove("Patterns"); // Remove the old Bedrock patterns list diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java index 44a5469b8..6f69574ed 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java @@ -37,6 +37,7 @@ import lombok.experimental.Accessors; import org.cloudburstmc.protocol.bedrock.data.TrimMaterial; import org.cloudburstmc.protocol.bedrock.data.TrimPattern; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.inventory.item.BannerPattern; import org.geysermc.geyser.inventory.recipe.TrimRecipe; import org.geysermc.geyser.level.JavaDimension; import org.geysermc.geyser.session.GeyserSession; @@ -68,6 +69,7 @@ public final class RegistryCache { register("trim_material", cache -> cache.trimMaterials, TrimRecipe::readTrimMaterial); register("trim_pattern", cache -> cache.trimPatterns, TrimRecipe::readTrimPattern); register("worldgen/biome", (cache, array) -> cache.biomeTranslations = array, BiomeTranslator::loadServerBiome); + register("banner_pattern", cache -> cache.bannerPatterns, ($, entry) -> BannerPattern.getByJavaIdentifier(entry.getId())); } @Getter(AccessLevel.NONE) @@ -85,6 +87,8 @@ public final class RegistryCache { private final Int2ObjectMap trimMaterials = new Int2ObjectOpenHashMap<>(); private final Int2ObjectMap trimPatterns = new Int2ObjectOpenHashMap<>(); + private final Int2ObjectMap bannerPatterns = new Int2ObjectOpenHashMap<>(); + public RegistryCache(GeyserSession session) { this.session = session; } diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/LoomInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/LoomInventoryTranslator.java index 6c7a11ff2..636a7982a 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/LoomInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/LoomInventoryTranslator.java @@ -25,10 +25,10 @@ package org.geysermc.geyser.translator.inventory; +import com.github.steveice10.mc.protocol.data.game.item.component.BannerPatternLayer; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.ListTag; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import org.cloudburstmc.nbt.NbtMap; @@ -51,7 +51,7 @@ import org.geysermc.geyser.item.type.BannerItem; import org.geysermc.geyser.item.type.DyeItem; import org.geysermc.geyser.session.GeyserSession; -import java.util.Collections; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -159,23 +159,12 @@ public class LoomInventoryTranslator extends AbstractBlockInventoryTranslator { if (inputCopy.getComponents() == null) { inputCopy.setComponents(new DataComponents(new HashMap<>())); } - //TODO - CompoundTag blockEntityTag = inputCopy.getNbt().get("BlockEntityTag"); - CompoundTag javaBannerPattern = BannerItem.getJavaBannerPattern(pattern); - if (blockEntityTag != null) { - ListTag patternsList = blockEntityTag.get("Patterns"); - if (patternsList != null) { - patternsList.add(javaBannerPattern); - } else { - patternsList = new ListTag("Patterns", Collections.singletonList(javaBannerPattern)); - blockEntityTag.put(patternsList); - } - } else { - blockEntityTag = new CompoundTag("BlockEntityTag"); - ListTag patternsList = new ListTag("Patterns", Collections.singletonList(javaBannerPattern)); - blockEntityTag.put(patternsList); - inputCopy.getNbt().put(blockEntityTag); + BannerPatternLayer bannerPatternLayer = BannerItem.getJavaBannerPattern(session, pattern); // TODO + if (bannerPatternLayer != null) { + List patternsList = inputCopy.getComponents().getOrDefault(DataComponentType.BANNER_PATTERNS, new ArrayList<>()); + patternsList.add(bannerPatternLayer); + inputCopy.getComponents().put(DataComponentType.BANNER_PATTERNS, patternsList); } // Set the new item as the output diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BannerBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BannerBlockEntityTranslator.java index f23433bbe..e0e0130c5 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BannerBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BannerBlockEntityTranslator.java @@ -46,8 +46,8 @@ public class BannerBlockEntityTranslator extends BlockEntityTranslator implement return; } - if (tag.get("Patterns") instanceof ListTag patterns) { - if (patterns.equals(BannerItem.OMINOUS_BANNER_PATTERN)) { + if (tag.get("patterns") instanceof ListTag patterns) { + if (BannerItem.isOminous(patterns)) { // This is an ominous banner; don't try to translate the raw patterns (it doesn't translate correctly) // and tell the Bedrock client that this is an ominous banner builder.putInt("Type", 1); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBookEditTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBookEditTranslator.java index 4350f6a83..10024c02f 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBookEditTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBookEditTranslator.java @@ -105,6 +105,7 @@ public class BedrockBookEditTranslator extends PacketTranslator break; } case SIGN_BOOK: { + // As of JE 1.20.5, client no longer adds title and author on its own break; } default: From 1bdbcab4e8fc8a8373b13cdf962eb17e7fccaa02 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Tue, 23 Apr 2024 00:44:20 -0400 Subject: [PATCH 276/344] Wolf variants --- .../geyser/entity/EntityDefinitions.java | 1 + .../living/animal/tameable/WolfEntity.java | 41 +++++++++++++++++++ .../geysermc/geyser/item/type/BannerItem.java | 3 +- .../geyser/session/cache/RegistryCache.java | 3 ++ 4 files changed, 47 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java index e9d49fbd8..6b243212d 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java +++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java @@ -971,6 +971,7 @@ public final class EntityDefinitions { .addTranslator(MetadataType.BOOLEAN, (wolfEntity, entityMetadata) -> wolfEntity.setFlag(EntityFlag.INTERESTED, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue())) .addTranslator(MetadataType.INT, WolfEntity::setCollarColor) .addTranslator(MetadataType.INT, WolfEntity::setWolfAngerTime) + .addTranslator(MetadataType.WOLF_VARIANT, WolfEntity::setWolfVariant) .build(); // As of 1.18 these don't track entity data at all diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java index c75247fdf..ee7281772 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java @@ -29,6 +29,7 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEnti import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; @@ -43,6 +44,7 @@ import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; import java.util.Collections; +import java.util.Locale; import java.util.Set; import java.util.UUID; @@ -102,6 +104,15 @@ public class WolfEntity extends TameableEntity { dirtyMetadata.put(EntityDataTypes.COLOR, time != 0 ? (byte) 0 : collarColor); } + // 1.20.5+ + public void setWolfVariant(IntEntityMetadata entityMetadata) { + WolfVariant wolfVariant = session.getRegistryCache().wolfVariants().get(entityMetadata.getPrimitiveValue()); + if (wolfVariant == null) { + wolfVariant = WolfVariant.PALE; + } + dirtyMetadata.put(EntityDataTypes.VARIANT, wolfVariant.ordinal()); + } + @Override public boolean canEat(Item item) { // Cannot be a baby to eat these foods @@ -147,4 +158,34 @@ public class WolfEntity extends TameableEntity { return InteractionResult.PASS; } } + + // Ordered by bedrock id + public enum WolfVariant { + PALE, + ASHEN, + BLACK, + CHESTNUT, + RUSTY, + SNOWY, + SPOTTED, + STRIPED, + WOODS; + + private static final WolfVariant[] VALUES = values(); + + private final String javaIdentifier; + + WolfVariant() { + this.javaIdentifier = "minecraft:" + this.name().toLowerCase(Locale.ROOT); + } + + public static @Nullable WolfVariant getByJavaIdentifier(String javaIdentifier) { + for (WolfVariant wolfVariant : VALUES) { + if (wolfVariant.javaIdentifier.equals(javaIdentifier)) { + return wolfVariant; + } + } + return null; + } + } } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java index 0d8050dec..fe378d4c6 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java @@ -80,7 +80,8 @@ public class BannerItem extends BlockItem { for (int i = 0; i < OMINOUS_BANNER_PATTERN.size(); i++) { BannerPatternLayer patternLayer = patternLayers.get(i); Pair pair = OMINOUS_BANNER_PATTERN.get(i); - if (!patternLayer.getPattern().isId() || patternLayer.getColorId() != pair.right().ordinal()) { + if (patternLayer.getColorId() != pair.right().ordinal() || + !patternLayer.getPattern().isId()) { return false; } BannerPattern bannerPattern = session.getRegistryCache().bannerPatterns().get(patternLayer.getPattern().id()); diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java index 6f69574ed..d5293c5c3 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java @@ -37,6 +37,7 @@ import lombok.experimental.Accessors; import org.cloudburstmc.protocol.bedrock.data.TrimMaterial; import org.cloudburstmc.protocol.bedrock.data.TrimPattern; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.entity.type.living.animal.tameable.WolfEntity; import org.geysermc.geyser.inventory.item.BannerPattern; import org.geysermc.geyser.inventory.recipe.TrimRecipe; import org.geysermc.geyser.level.JavaDimension; @@ -70,6 +71,7 @@ public final class RegistryCache { register("trim_pattern", cache -> cache.trimPatterns, TrimRecipe::readTrimPattern); register("worldgen/biome", (cache, array) -> cache.biomeTranslations = array, BiomeTranslator::loadServerBiome); register("banner_pattern", cache -> cache.bannerPatterns, ($, entry) -> BannerPattern.getByJavaIdentifier(entry.getId())); + register("wolf_variant", cache -> cache.wolfVariants, ($, entry) -> WolfEntity.WolfVariant.getByJavaIdentifier(entry.getId())); } @Getter(AccessLevel.NONE) @@ -88,6 +90,7 @@ public final class RegistryCache { private final Int2ObjectMap trimPatterns = new Int2ObjectOpenHashMap<>(); private final Int2ObjectMap bannerPatterns = new Int2ObjectOpenHashMap<>(); + private final Int2ObjectMap wolfVariants = new Int2ObjectOpenHashMap<>(); public RegistryCache(GeyserSession session) { this.session = session; From 3f499e3ec05592510a9cdeca0e642478a435cf17 Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Tue, 23 Apr 2024 03:09:42 -0700 Subject: [PATCH 277/344] Start on custom skulls Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .../geyser/skin/FakeHeadProvider.java | 86 ++++++++++++------- .../inventory/InventoryTranslator.java | 2 +- .../inventory/PlayerInventoryTranslator.java | 4 +- .../translator/item/ItemTranslator.java | 36 +++++--- .../entity/SkullBlockEntityTranslator.java | 1 + .../entity/JavaSetEquipmentTranslator.java | 20 +++-- .../JavaLevelChunkWithLightTranslator.java | 1 + 7 files changed, 96 insertions(+), 54 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/skin/FakeHeadProvider.java b/core/src/main/java/org/geysermc/geyser/skin/FakeHeadProvider.java index c7bd235b2..2d6345bfa 100644 --- a/core/src/main/java/org/geysermc/geyser/skin/FakeHeadProvider.java +++ b/core/src/main/java/org/geysermc/geyser/skin/FakeHeadProvider.java @@ -25,9 +25,13 @@ package org.geysermc.geyser.skin; -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.github.steveice10.mc.auth.data.GameProfile; +import com.github.steveice10.mc.auth.data.GameProfile.Texture; +import com.github.steveice10.mc.auth.data.GameProfile.TextureModel; +import com.github.steveice10.mc.auth.data.GameProfile.TextureType; +import com.github.steveice10.mc.auth.exception.property.PropertyException; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; @@ -39,11 +43,13 @@ import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.entity.type.LivingEntity; import org.geysermc.geyser.entity.type.player.PlayerEntity; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.skin.SkinManager.GameProfileData; import org.geysermc.geyser.text.GeyserLocale; import java.awt.*; import java.awt.image.BufferedImage; import java.io.IOException; +import java.util.Map; import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; @@ -95,38 +101,60 @@ public class FakeHeadProvider { } }); - public static void setHead(GeyserSession session, PlayerEntity entity, Tag skullOwner) { - if (skullOwner == null) { + public static void setHead(GeyserSession session, PlayerEntity entity, DataComponents components) { + GameProfile profile = components.get(DataComponentType.PROFILE); + + if (profile == null) { return; } - if (skullOwner instanceof CompoundTag profileTag) { - SkinManager.GameProfileData gameProfileData = SkinManager.GameProfileData.from(profileTag); - if (gameProfileData == null) { + + Map textures = null; + try { + textures = profile.getTextures(false); + } catch (PropertyException e) { + session.getGeyser().getLogger().debug("Failed to get textures from GameProfile: " + e); + } + + if (textures == null || textures.isEmpty()) { + loadHead(session, entity, profile.getName()); + return; + } + + Texture skinTexture = textures.get(TextureType.SKIN); + + if (skinTexture == null) { + return; + } + + Texture capeTexture = textures.get(TextureType.CAPE); + String capeUrl = capeTexture != null ? capeTexture.getURL() : null; + + boolean isAlex = skinTexture.getModel() == TextureModel.SLIM; + + loadHead(session, entity, new GameProfileData(skinTexture.getURL(), capeUrl, isAlex)); + } + + public static void loadHead(GeyserSession session, PlayerEntity entity, String owner) { + if (owner == null || owner.isEmpty()) { + return; + } + + CompletableFuture completableFuture = SkinProvider.requestTexturesFromUsername(owner); + completableFuture.whenCompleteAsync((encodedJson, throwable) -> { + if (throwable != null) { + GeyserImpl.getInstance().getLogger().error(GeyserLocale.getLocaleStringLog("geyser.skin.fail", entity.getUuid()), throwable); return; } - loadHead(session, entity, gameProfileData); - } else if (skullOwner instanceof StringTag ownerTag) { - String owner = ownerTag.getValue(); - if (owner.isEmpty()) { - return; - } - CompletableFuture completableFuture = SkinProvider.requestTexturesFromUsername(owner); - completableFuture.whenCompleteAsync((encodedJson, throwable) -> { - if (throwable != null) { - GeyserImpl.getInstance().getLogger().error(GeyserLocale.getLocaleStringLog("geyser.skin.fail", entity.getUuid()), throwable); + try { + SkinManager.GameProfileData gameProfileData = SkinManager.GameProfileData.loadFromJson(encodedJson); + if (gameProfileData == null) { return; } - try { - SkinManager.GameProfileData gameProfileData = SkinManager.GameProfileData.loadFromJson(encodedJson); - if (gameProfileData == null) { - return; - } - loadHead(session, entity, gameProfileData); - } catch (IOException e) { - GeyserImpl.getInstance().getLogger().error(GeyserLocale.getLocaleStringLog("geyser.skin.fail", entity.getUuid(), e.getMessage())); - } - }); - } + loadHead(session, entity, gameProfileData); + } catch (IOException e) { + GeyserImpl.getInstance().getLogger().error(GeyserLocale.getLocaleStringLog("geyser.skin.fail", entity.getUuid(), e.getMessage())); + } + }); } public static void loadHead(GeyserSession session, PlayerEntity entity, SkinManager.GameProfileData gameProfileData) { diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java index 2d7a1ae5a..4a3e31b30 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java @@ -225,7 +225,7 @@ public abstract class InventoryTranslator { GeyserItemStack javaItem = inventory.getItem(sourceSlot); if (javaItem.asItem() == Items.PLAYER_HEAD && javaItem.getNbt() != null) { - FakeHeadProvider.setHead(session, session.getPlayerEntity(), javaItem.getNbt().get("SkullOwner")); + FakeHeadProvider.setHead(session, session.getPlayerEntity(), javaItem.getComponents()); } } else if (sourceSlot == 5) { //we are probably removing the head, so restore the original skin diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java index b461c7afc..36d10aa54 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java @@ -100,7 +100,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { if (i == 5 && item.asItem() == Items.PLAYER_HEAD && item.getNbt() != null) { - FakeHeadProvider.setHead(session, session.getPlayerEntity(), item.getNbt().get("SkullOwner")); + FakeHeadProvider.setHead(session, session.getPlayerEntity(), item.getComponents()); } } armorContentPacket.setContents(Arrays.asList(contents)); @@ -144,7 +144,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { // Check for custom skull if (javaItem.asItem() == Items.PLAYER_HEAD && javaItem.getNbt() != null) { - FakeHeadProvider.setHead(session, session.getPlayerEntity(), javaItem.getNbt().get("SkullOwner")); + FakeHeadProvider.setHead(session, session.getPlayerEntity(), javaItem.getComponents()); } else { FakeHeadProvider.restoreOriginalSkin(session, session.getPlayerEntity()); } diff --git a/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java index c96542fc1..a8e9e1c52 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java @@ -26,6 +26,9 @@ package org.geysermc.geyser.translator.item; import com.github.steveice10.mc.auth.data.GameProfile; +import com.github.steveice10.mc.auth.data.GameProfile.Texture; +import com.github.steveice10.mc.auth.data.GameProfile.TextureType; +import com.github.steveice10.mc.auth.exception.property.PropertyException; import com.github.steveice10.mc.protocol.data.game.Identifier; import com.github.steveice10.mc.protocol.data.game.entity.attribute.ModifierOperation; import com.github.steveice10.mc.protocol.data.game.item.ItemStack; @@ -553,21 +556,28 @@ public final class ItemTranslator { if (components == null) { return null; } - //TODO + GameProfile profile = components.get(DataComponentType.PROFILE); if (profile != null) { -// if (!(nbt.get("SkullOwner") instanceof CompoundTag skullOwner)) { -// // It's a username give up d: -// return null; -// } -// SkinManager.GameProfileData data = SkinManager.GameProfileData.from(skullOwner); -// if (data == null) { -// session.getGeyser().getLogger().debug("Not sure how to handle skull head item display. " + nbt); -// return null; -// } -// -// String skinHash = data.skinUrl().substring(data.skinUrl().lastIndexOf('/') + 1); -// return BlockRegistries.CUSTOM_SKULLS.get(skinHash); + Map textures = null; + try { + textures = profile.getTextures(false); + } catch (PropertyException e) { + session.getGeyser().getLogger().debug("Failed to get textures from GameProfile: " + e); + } + + if (textures == null || textures.isEmpty()) { + return null; + } + + Texture skinTexture = textures.get(TextureType.SKIN); + + if (skinTexture == null) { + return null; + } + + String skinHash = skinTexture.getURL().substring(skinTexture.getURL().lastIndexOf('/') + 1); + return BlockRegistries.CUSTOM_SKULLS.get(skinHash); } return null; } diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java index 9ac9126db..e9aceece5 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java @@ -101,6 +101,7 @@ public class SkullBlockEntityTranslator extends BlockEntityTranslator implements } public static @Nullable BlockDefinition translateSkull(GeyserSession session, CompoundTag tag, Vector3i blockPosition, int blockState) { + // TODO: The tag layout follows new format (profille, etc...) CompoundTag owner = tag.get("SkullOwner"); if (owner == null) { session.getSkullCache().removeSkull(blockPosition); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEquipmentTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEquipmentTranslator.java index 6178a51e8..b0168a4ce 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEquipmentTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEquipmentTranslator.java @@ -31,7 +31,10 @@ import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.Client import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.LivingEntity; +import org.geysermc.geyser.entity.type.player.PlayerEntity; +import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.skin.FakeHeadProvider; import org.geysermc.geyser.translator.item.ItemTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; @@ -59,15 +62,14 @@ public class JavaSetEquipmentTranslator extends PacketTranslator { ItemStack javaItem = equipment.getItem(); - // TODO -// if (livingEntity instanceof PlayerEntity -// && javaItem != null -// && javaItem.getId() == Items.PLAYER_HEAD.javaId() -// && javaItem.getNbt() != null) { -// FakeHeadProvider.setHead(session, (PlayerEntity) livingEntity, javaItem.getNbt().get("SkullOwner")); -// } else { -// FakeHeadProvider.restoreOriginalSkin(session, livingEntity); -// } + if (livingEntity instanceof PlayerEntity + && javaItem != null + && javaItem.getId() == Items.PLAYER_HEAD.javaId() + && javaItem.getDataComponents() != null) { + FakeHeadProvider.setHead(session, (PlayerEntity) livingEntity, javaItem.getDataComponents()); + } else { + FakeHeadProvider.restoreOriginalSkin(session, livingEntity); + } livingEntity.setHelmet(item); armorUpdated = true; 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 e34c0d96d..fc1d0316c 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 @@ -425,6 +425,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator Date: Tue, 23 Apr 2024 06:13:19 -0400 Subject: [PATCH 278/344] Fix horse inventory --- .../inventory/JavaHorseScreenOpenTranslator.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaHorseScreenOpenTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaHorseScreenOpenTranslator.java index 58deaa0e9..33cfeaf31 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaHorseScreenOpenTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaHorseScreenOpenTranslator.java @@ -112,19 +112,23 @@ public class JavaHorseScreenOpenTranslator extends PacketTranslator slots = new ArrayList<>(); + // Since 1.20.5, the armor slot is not included in the container size, + // but everything is still indexed the same. + int slotCount = packet.getNumberOfSlots() + 1; + InventoryTranslator inventoryTranslator; if (entity instanceof LlamaEntity) { - inventoryTranslator = new LlamaInventoryTranslator(packet.getNumberOfSlots()); + inventoryTranslator = new LlamaInventoryTranslator(slotCount); slots.add(CARPET_SLOT); } else if (entity instanceof ChestedHorseEntity) { - inventoryTranslator = new DonkeyInventoryTranslator(packet.getNumberOfSlots()); + inventoryTranslator = new DonkeyInventoryTranslator(slotCount); slots.add(SADDLE_SLOT); } else if (entity instanceof CamelEntity) { // The camel has an invisible armor slot and needs special handling, same as the donkey - inventoryTranslator = new DonkeyInventoryTranslator(packet.getNumberOfSlots()); + inventoryTranslator = new DonkeyInventoryTranslator(slotCount); slots.add(SADDLE_SLOT); } else { - inventoryTranslator = new HorseInventoryTranslator(packet.getNumberOfSlots()); + inventoryTranslator = new HorseInventoryTranslator(slotCount); slots.add(SADDLE_SLOT); slots.add(ARMOR_SLOT); } @@ -136,6 +140,6 @@ public class JavaHorseScreenOpenTranslator extends PacketTranslator Date: Tue, 23 Apr 2024 17:57:03 +0200 Subject: [PATCH 279/344] init: pick item component change --- .../mod/world/GeyserModWorldManager.java | 50 +++++++++++++++++-- .../manager/GeyserSpigotWorldManager.java | 9 ++-- .../erosion/GeyserboundPacketHandlerImpl.java | 15 ++++-- .../geyser/level/GeyserWorldManager.java | 14 ++++-- .../geysermc/geyser/level/WorldManager.java | 4 +- .../BedrockBlockPickRequestTranslator.java | 27 +++------- gradle/libs.versions.toml | 2 +- 7 files changed, 79 insertions(+), 42 deletions(-) diff --git a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/world/GeyserModWorldManager.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/world/GeyserModWorldManager.java index e9d612976..b9fbd6cdc 100644 --- a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/world/GeyserModWorldManager.java +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/world/GeyserModWorldManager.java @@ -25,7 +25,10 @@ package org.geysermc.geyser.platform.mod.world; +import com.github.steveice10.mc.protocol.data.game.Holder; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; +import com.github.steveice10.mc.protocol.data.game.item.component.BannerPatternLayer; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityInfo; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; @@ -43,6 +46,7 @@ import net.minecraft.world.item.component.WrittenBookContent; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BannerBlockEntity; +import net.minecraft.world.level.block.entity.BannerPatternLayers; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.LecternBlockEntity; import net.minecraft.world.level.chunk.ChunkAccess; @@ -62,6 +66,7 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.BlockEntityUtils; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.concurrent.CompletableFuture; @@ -217,8 +222,8 @@ public class GeyserModWorldManager extends GeyserWorldManager { @NonNull @Override - public CompletableFuture getPickItemNbt(GeyserSession session, int x, int y, int z, boolean addNbtData) { - CompletableFuture future = new CompletableFuture<>(); + public CompletableFuture getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addNbtData) { + CompletableFuture future = new CompletableFuture<>(); server.execute(() -> { ServerPlayer player = getPlayer(session); if (player == null) { @@ -235,7 +240,22 @@ public class GeyserModWorldManager extends GeyserWorldManager { // the banner might have a custom name, both of which a Java client knows and caches ItemStack itemStack = banner.getItem(); - future.complete(null); // todo 1.20.5 + com.github.steveice10.mc.protocol.data.game.item.component.DataComponents components = + new com.github.steveice10.mc.protocol.data.game.item.component.DataComponents(new HashMap<>()); + + components.put(DataComponentType.DAMAGE, itemStack.getDamageValue()); + + Component customName = itemStack.getComponents().get(DataComponents.CUSTOM_NAME); + if (customName != null) { + components.put(DataComponentType.CUSTOM_NAME, toKyoriComponent(customName)); + } + + BannerPatternLayers pattern = itemStack.get(DataComponents.BANNER_PATTERNS); + if (pattern != null) { + components.put(DataComponentType.BANNER_PATTERNS, toPatternList(pattern)); + } + + future.complete(components); return; } future.complete(null); @@ -262,8 +282,7 @@ public class GeyserModWorldManager extends GeyserWorldManager { if (writtenBookContent != null) { return writtenBookContent.pages().stream() .map(Filterable::raw) - .map((component) -> Component.Serializer.toJson(component, RegistryAccess.EMPTY)) - .map((json -> LEGACY_SERIALIZER.serialize(GSON_SERIALIZER.deserializeOr(json, net.kyori.adventure.text.Component.empty())))) + .map(GeyserModWorldManager::fromComponent) .toList(); } else { WritableBookContent writableBookContent = itemStack.get(DataComponents.WRITABLE_BOOK_CONTENT); @@ -275,4 +294,25 @@ public class GeyserModWorldManager extends GeyserWorldManager { .toList(); } } + + private static String fromComponent(Component component) { + String json = Component.Serializer.toJson(component, RegistryAccess.EMPTY); + return LEGACY_SERIALIZER.serialize(GSON_SERIALIZER.deserializeOr(json, net.kyori.adventure.text.Component.empty())); + } + + private static net.kyori.adventure.text.Component toKyoriComponent(Component component) { + String json = Component.Serializer.toJson(component, RegistryAccess.EMPTY); + return GSON_SERIALIZER.deserializeOr(json, net.kyori.adventure.text.Component.empty()); + } + + private static List toPatternList(BannerPatternLayers patternLayers) { + return patternLayers.layers().stream() + .map(layer -> { + BannerPatternLayer.BannerPattern pattern = new BannerPatternLayer.BannerPattern( + layer.pattern().value().assetId().toString(), layer.pattern().value().translationKey() + ); + return new BannerPatternLayer(Holder.ofCustom(pattern), layer.color().getId()); + }) + .toList(); + } } diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java index 42f0d17f4..07a9d489a 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java @@ -26,8 +26,8 @@ package org.geysermc.geyser.platform.spigot.world.manager; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityInfo; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.World; @@ -39,7 +39,6 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.nbt.NbtMap; import org.geysermc.erosion.bukkit.BukkitLecterns; import org.geysermc.erosion.bukkit.BukkitUtils; -import org.geysermc.erosion.bukkit.PickBlockUtils; import org.geysermc.erosion.bukkit.SchedulerUtils; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.level.GameRule; @@ -205,8 +204,8 @@ public class GeyserSpigotWorldManager extends WorldManager { } @Override - public @NonNull CompletableFuture<@Nullable CompoundTag> getPickItemNbt(GeyserSession session, int x, int y, int z, boolean addNbtData) { - CompletableFuture<@Nullable CompoundTag> future = new CompletableFuture<>(); + public @NonNull CompletableFuture<@Nullable DataComponents> getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addNbtData) { + CompletableFuture<@Nullable DataComponents> future = new CompletableFuture<>(); Player bukkitPlayer; if ((bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUuid())) == null) { future.complete(null); @@ -215,7 +214,7 @@ public class GeyserSpigotWorldManager extends WorldManager { Block block = bukkitPlayer.getWorld().getBlockAt(x, y, z); // Paper 1.19.3 complains about async access otherwise. // java.lang.IllegalStateException: Tile is null, asynchronous access? - SchedulerUtils.runTask(this.plugin, () -> future.complete(PickBlockUtils.pickBlock(block)), block); + SchedulerUtils.runTask(this.plugin, () -> future.complete(/*PickBlockUtils.pickBlock(block)*/ null), block); // TODO fix erosion once clear how to handle this return future; } diff --git a/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java b/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java index 3ae458f63..57147fc49 100644 --- a/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java +++ b/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java @@ -25,8 +25,8 @@ package org.geysermc.geyser.erosion; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.mc.protocol.data.game.level.block.value.PistonValueType; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import io.netty.channel.Channel; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; @@ -43,7 +43,14 @@ import org.geysermc.erosion.packet.ErosionPacketHandler; import org.geysermc.erosion.packet.ErosionPacketSender; import org.geysermc.erosion.packet.backendbound.BackendboundInitializePacket; import org.geysermc.erosion.packet.backendbound.BackendboundPacket; -import org.geysermc.erosion.packet.geyserbound.*; +import org.geysermc.erosion.packet.geyserbound.GeyserboundBatchBlockIdPacket; +import org.geysermc.erosion.packet.geyserbound.GeyserboundBlockEntityPacket; +import org.geysermc.erosion.packet.geyserbound.GeyserboundBlockIdPacket; +import org.geysermc.erosion.packet.geyserbound.GeyserboundBlockLookupFailPacket; +import org.geysermc.erosion.packet.geyserbound.GeyserboundBlockPlacePacket; +import org.geysermc.erosion.packet.geyserbound.GeyserboundHandshakePacket; +import org.geysermc.erosion.packet.geyserbound.GeyserboundPickBlockPacket; +import org.geysermc.erosion.packet.geyserbound.GeyserboundPistonEventPacket; import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.physics.Direction; import org.geysermc.geyser.network.GameProtocol; @@ -64,7 +71,7 @@ public final class GeyserboundPacketHandlerImpl extends AbstractGeyserboundPacke @Setter private CompletableFuture pendingBatchLookup = null; @Setter - private CompletableFuture pickBlockLookup = null; + private CompletableFuture pickBlockLookup = null; private final AtomicInteger nextTransactionId = new AtomicInteger(1); @@ -140,7 +147,7 @@ public final class GeyserboundPacketHandlerImpl extends AbstractGeyserboundPacke @Override public void handlePickBlock(GeyserboundPickBlockPacket packet) { if (this.pickBlockLookup != null) { - this.pickBlockLookup.complete(packet.getTag()); + //this.pickBlockLookup.complete(packet.getTag()); // TODO 1.20.5 } } diff --git a/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java b/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java index 44c3b94b3..9a9eac2df 100644 --- a/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java +++ b/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java @@ -26,8 +26,8 @@ package org.geysermc.geyser.level; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityInfo; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; @@ -36,7 +36,11 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; -import org.geysermc.erosion.packet.backendbound.*; +import org.geysermc.erosion.packet.backendbound.BackendboundBatchBlockEntityPacket; +import org.geysermc.erosion.packet.backendbound.BackendboundBatchBlockRequestPacket; +import org.geysermc.erosion.packet.backendbound.BackendboundBlockEntityPacket; +import org.geysermc.erosion.packet.backendbound.BackendboundBlockRequestPacket; +import org.geysermc.erosion.packet.backendbound.BackendboundPickBlockPacket; import org.geysermc.erosion.util.BlockPositionIterator; import org.geysermc.erosion.util.LecternUtils; import org.geysermc.geyser.session.GeyserSession; @@ -174,12 +178,12 @@ public class GeyserWorldManager extends WorldManager { @NonNull @Override - public CompletableFuture<@Nullable CompoundTag> getPickItemNbt(GeyserSession session, int x, int y, int z, boolean addNbtData) { + public CompletableFuture<@Nullable DataComponents> getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addNbtData) { var erosionHandler = session.getErosionHandler().getAsActive(); if (erosionHandler == null) { - return super.getPickItemNbt(session, x, y, z, addNbtData); + return super.getPickItemComponents(session, x, y, z, addNbtData); } - CompletableFuture future = new CompletableFuture<>(); + CompletableFuture future = new CompletableFuture<>(); erosionHandler.setPickBlockLookup(future); erosionHandler.sendPacket(new BackendboundPickBlockPacket(Vector3i.from(x, y, z))); return future; diff --git a/core/src/main/java/org/geysermc/geyser/level/WorldManager.java b/core/src/main/java/org/geysermc/geyser/level/WorldManager.java index be7e2c139..aa0b43b80 100644 --- a/core/src/main/java/org/geysermc/geyser/level/WorldManager.java +++ b/core/src/main/java/org/geysermc/geyser/level/WorldManager.java @@ -26,9 +26,9 @@ package org.geysermc.geyser.level; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityInfo; import com.github.steveice10.mc.protocol.data.game.setting.Difficulty; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3i; @@ -220,7 +220,7 @@ public abstract class WorldManager { * @return expected NBT for this item. */ @NonNull - public CompletableFuture<@Nullable CompoundTag> getPickItemNbt(GeyserSession session, int x, int y, int z, boolean addNbtData) { + public CompletableFuture<@Nullable DataComponents> getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addExtraData) { return CompletableFuture.completedFuture(null); } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java index 3781ef3c0..f4116ec0c 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java @@ -26,9 +26,6 @@ package org.geysermc.geyser.translator.protocol.bedrock; import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.ListTag; -import com.github.steveice10.opennbt.tag.builtin.StringTag; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.packet.BlockPickRequestPacket; import org.geysermc.geyser.entity.EntityDefinitions; @@ -68,33 +65,23 @@ public class BedrockBlockPickRequestTranslator extends PacketTranslator session.ensureInEventLoop(() -> { - if (tag == null) { + boolean addExtraData = packet.isAddUserData() && blockMapping.isBlockEntity(); // Holding down CTRL + if (BlockStateValues.getBannerColor(blockToPick) != -1 || addExtraData) { //TODO + session.getGeyser().getWorldManager().getPickItemComponents(session, vector.getX(), vector.getY(), vector.getZ(), addExtraData) + .whenComplete((components, ex) -> session.ensureInEventLoop(() -> { + if (components == null) { pickItem(session, blockMapping); return; } - if (addNbtData) { - ListTag lore = new ListTag("Lore"); - lore.add(new StringTag("", "\"(+NBT)\"")); - CompoundTag display = tag.get("display"); - if (display == null) { - display = new CompoundTag("display"); - tag.put(display); - } - display.put(lore); - } // I don't really like this... I'd rather get an ID from the block mapping I think ItemMapping mapping = session.getItemMappings().getMapping(blockMapping.getPickItem()); - ItemStack itemStack = new ItemStack(mapping.getJavaItem().javaId(), 1, tag); + ItemStack itemStack = new ItemStack(mapping.getJavaItem().javaId(), 1, components); InventoryUtils.findOrCreateItem(session, itemStack); })); return; - }*/ + } pickItem(session, blockMapping); } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b7e692ab7..f2e068c22 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ protocol-connection = "3.0.0.Beta1-20240411.165033-128" raknet = "1.0.0.CR3-20240416.144209-1" blockstateupdater="1.20.80-20240411.142413-1" mcauthlib = "d9d773e" -mcprotocollib = "4ee05b62" # Revert from jitpack after release +mcprotocollib = "7026b600" # Revert from jitpack after release adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" From b81408820b7308c6fa8a6bb218ff3627d4f70b93 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Tue, 23 Apr 2024 12:33:06 -0400 Subject: [PATCH 280/344] Refactor TagCache to be extensible Previously, for any new tag, we would have to add a field, add the line to load it, add the line to clear it, and make a method for that tag. Now, you just add an enum. --- .../entity/type/living/DolphinEntity.java | 5 +- .../type/living/animal/AxolotlEntity.java | 3 +- .../entity/type/living/animal/BeeEntity.java | 3 +- .../entity/type/living/animal/FoxEntity.java | 3 +- .../type/living/animal/MooshroomEntity.java | 4 +- .../type/living/animal/SnifferEntity.java | 3 +- .../type/living/monster/CreeperEntity.java | 5 +- .../type/living/monster/PiglinEntity.java | 3 +- .../geyser/session/cache/RegistryCache.java | 3 +- .../geyser/session/cache/TagCache.java | 188 +++++------------- .../geyser/session/cache/tags/BlockTag.java | 48 +++++ .../geyser/session/cache/tags/ItemTag.java | 47 +++++ .../translator/level/BiomeTranslator.java | 4 - .../org/geysermc/geyser/util/BlockUtils.java | 19 +- 14 files changed, 177 insertions(+), 161 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/session/cache/tags/BlockTag.java create mode 100644 core/src/main/java/org/geysermc/geyser/session/cache/tags/ItemTag.java diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/DolphinEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/DolphinEntity.java index f0348bcaf..a43bb666f 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/DolphinEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/DolphinEntity.java @@ -31,6 +31,7 @@ import org.cloudburstmc.math.vector.Vector3f; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; @@ -49,7 +50,7 @@ public class DolphinEntity extends WaterEntity { @NonNull @Override protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { - if (!itemInHand.isEmpty() && session.getTagCache().isFish(itemInHand)) { + if (!itemInHand.isEmpty() && session.getTagCache().is(ItemTag.FISHES, itemInHand)) { return InteractiveTag.FEED; } return super.testMobInteraction(hand, itemInHand); @@ -58,7 +59,7 @@ public class DolphinEntity extends WaterEntity { @NonNull @Override protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { - if (!itemInHand.isEmpty() && session.getTagCache().isFish(itemInHand)) { + if (!itemInHand.isEmpty() && session.getTagCache().is(ItemTag.FISHES, itemInHand)) { // Feed return InteractionResult.SUCCESS; } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java index 97753f63f..c4f95e546 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java @@ -36,6 +36,7 @@ import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.util.EntityUtils; import org.geysermc.geyser.util.InteractionResult; @@ -61,7 +62,7 @@ public class AxolotlEntity extends AnimalEntity { @Override public boolean canEat(Item item) { - return session.getTagCache().isAxolotlFood(item); + return session.getTagCache().is(ItemTag.AXOLOTL_FOOD, item); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/BeeEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/BeeEntity.java index e05b44cf0..7f1a88d7b 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/BeeEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/BeeEntity.java @@ -35,6 +35,7 @@ import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.ItemTag; import java.util.UUID; @@ -67,6 +68,6 @@ public class BeeEntity extends AnimalEntity { @Override public boolean canEat(Item item) { - return session.getTagCache().isFlower(item); + return session.getTagCache().is(ItemTag.FLOWERS, item); } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FoxEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FoxEntity.java index 98c73cbce..200505f14 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FoxEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FoxEntity.java @@ -33,6 +33,7 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.ItemTag; import java.util.UUID; @@ -56,6 +57,6 @@ public class FoxEntity extends AnimalEntity { @Override public boolean canEat(Item item) { - return session.getTagCache().isFoxFood(item); + return session.getTagCache().is(ItemTag.FOX_FOOD, item); } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/MooshroomEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/MooshroomEntity.java index 1c347bf31..8673eb18e 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/MooshroomEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/MooshroomEntity.java @@ -33,8 +33,8 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.Items; -import org.geysermc.geyser.item.type.FlowerItem; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; @@ -77,7 +77,7 @@ public class MooshroomEntity extends AnimalEntity { } else if (!isBaby && isAlive() && itemInHand.asItem() == Items.SHEARS) { // Shear items return InteractionResult.SUCCESS; - } else if (isBrown && session.getTagCache().isSmallFlower(itemInHand) && itemInHand.asItem() instanceof FlowerItem) { + } else if (isBrown && session.getTagCache().is(ItemTag.SMALL_FLOWERS, itemInHand)) { // ? return InteractionResult.SUCCESS; } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SnifferEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SnifferEntity.java index a97756e39..0e6fffbc0 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SnifferEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SnifferEntity.java @@ -39,6 +39,7 @@ import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.type.Tickable; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.ItemTag; import java.util.UUID; @@ -72,7 +73,7 @@ public class SnifferEntity extends AnimalEntity implements Tickable { @Override public boolean canEat(Item item) { - return session.getTagCache().isSnifferFood(item); + return session.getTagCache().is(ItemTag.SNIFFER_FOOD, item); } public void setSnifferState(ObjectEntityMetadata entityMetadata) { diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/CreeperEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/CreeperEntity.java index 33ea4e544..f134c31b3 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/CreeperEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/CreeperEntity.java @@ -35,6 +35,7 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; @@ -65,7 +66,7 @@ public class CreeperEntity extends MonsterEntity { @NonNull @Override protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { - if (session.getTagCache().isCreeperIgniter(itemInHand.asItem())) { + if (session.getTagCache().is(ItemTag.CREEPER_IGNITERS, itemInHand)) { return InteractiveTag.IGNITE_CREEPER; } else { return super.testMobInteraction(hand, itemInHand); @@ -75,7 +76,7 @@ public class CreeperEntity extends MonsterEntity { @NonNull @Override protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { - if (session.getTagCache().isCreeperIgniter(itemInHand.asItem())) { + if (session.getTagCache().is(ItemTag.CREEPER_IGNITERS, itemInHand)) { // Ignite creeper - as of 1.19.3 session.playSoundEvent(SoundEvent.IGNITE, position); return InteractionResult.SUCCESS; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java index 450c546ec..696982a33 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java @@ -35,6 +35,7 @@ import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; @@ -65,7 +66,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 - setFlag(EntityFlag.ADMIRING, session.getTagCache().shouldPiglinAdmire(session.getItemMappings().getMapping(this.offHand).getJavaItem())); + setFlag(EntityFlag.ADMIRING, session.getTagCache().is(ItemTag.PIGLIN_LOVED, session.getItemMappings().getMapping(this.offHand).getJavaItem())); super.updateBedrockMetadata(); super.updateOffHand(session); diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java index d5293c5c3..d6d5ae292 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java @@ -57,7 +57,7 @@ import java.util.function.ToIntFunction; * Stores any information sent via Java registries. May not contain all data in a given registry - we'll strip what's * unneeded. * - * Crafted as of 1.20.5 for easy "add new registry" in the future. + * Crafted as of 1.20.5 for easy "add new registry" functionality in the future. */ @Accessors(fluent = true) @Getter @@ -118,6 +118,7 @@ public final class RegistryCache { REGISTRIES.put("minecraft:" + registry, (registryCache, entries) -> { Int2ObjectMap localCache = localCacheFunction.apply(registryCache); // Clear each local cache every time a new registry entry is given to us + // (e.g. proxy server switches) localCache.clear(); for (int i = 0; i < entries.size(); i++) { RegistryEntry entry = entries.get(i); diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java index 57000bf8b..b2f43f180 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java @@ -27,64 +27,45 @@ package org.geysermc.geyser.session.cache; import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundUpdateTagsPacket; import it.unimi.dsi.fastutil.ints.IntList; -import it.unimi.dsi.fastutil.ints.IntLists; -import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.GeyserLogger; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.registry.type.BlockMapping; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.BlockTag; +import org.geysermc.geyser.session.cache.tags.ItemTag; import javax.annotation.ParametersAreNonnullByDefault; +import java.util.EnumMap; +import java.util.HashMap; import java.util.Map; /** * Manages information sent from the {@link ClientboundUpdateTagsPacket}. If that packet is not sent, all lists here * will remain empty, matching Java Edition behavior. + * + * This system is designed for easy extensibility - just add an enum to {@link BlockTag} or {@link ItemTag}. */ @ParametersAreNonnullByDefault -public class TagCache { - /* Blocks */ - private IntList leaves; - private IntList wool; +public final class TagCache { + // Put these here so the enums can load without a static map + public static final Map ALL_BLOCK_TAGS = new HashMap<>(); + public static final Map ALL_ITEM_TAGS = new HashMap<>(); - private IntList axeEffective; - private IntList hoeEffective; - private IntList pickaxeEffective; - private IntList shovelEffective; - - private IntList requiresStoneTool; - private IntList requiresIronTool; - private IntList requiresDiamondTool; - - /* Items */ - private IntList axolotlFood; - private IntList creeperIgniters; - private IntList fishes; - private IntList flowers; - private IntList foxFood; - private IntList piglinLoved; - private IntList smallFlowers; - private IntList snifferFood; - - public TagCache() { - // Ensure all lists are non-null - clear(); - } + private final Map blocks = new EnumMap<>(BlockTag.class); + private final Map items = new EnumMap<>(ItemTag.class); public void loadPacket(GeyserSession session, ClientboundUpdateTagsPacket packet) { Map blockTags = packet.getTags().get("minecraft:block"); - this.leaves = IntList.of(blockTags.get("minecraft:leaves")); - this.wool = IntList.of(blockTags.get("minecraft:wool")); - - this.axeEffective = IntList.of(blockTags.get("minecraft:mineable/axe")); - this.hoeEffective = IntList.of(blockTags.get("minecraft:mineable/hoe")); - this.pickaxeEffective = IntList.of(blockTags.get("minecraft:mineable/pickaxe")); - this.shovelEffective = IntList.of(blockTags.get("minecraft:mineable/shovel")); - - this.requiresStoneTool = IntList.of(blockTags.get("minecraft:needs_stone_tool")); - this.requiresIronTool = IntList.of(blockTags.get("minecraft:needs_iron_tool")); - this.requiresDiamondTool = IntList.of(blockTags.get("minecraft:needs_diamond_tool")); + this.blocks.clear(); + ALL_BLOCK_TAGS.forEach((location, tag) -> { + int[] values = blockTags.get(location); + if (values != null) { + this.blocks.put(tag, IntList.of(values)); + } else { + session.getGeyser().getLogger().debug("Block tag not found from server: " + location); + } + }); // Hack btw GeyserLogger logger = session.getGeyser().getLogger(); @@ -96,14 +77,15 @@ public class TagCache { } Map itemTags = packet.getTags().get("minecraft:item"); - this.axolotlFood = IntList.of(itemTags.get("minecraft:axolotl_food")); - this.creeperIgniters = load(itemTags.get("minecraft:creeper_igniters")); - this.fishes = IntList.of(itemTags.get("minecraft:fishes")); - this.flowers = IntList.of(itemTags.get("minecraft:flowers")); - this.foxFood = IntList.of(itemTags.get("minecraft:fox_food")); - this.piglinLoved = IntList.of(itemTags.get("minecraft:piglin_loved")); - this.smallFlowers = IntList.of(itemTags.get("minecraft:small_flowers")); - this.snifferFood = load(itemTags.get("minecraft:sniffer_food")); + this.items.clear(); + ALL_ITEM_TAGS.forEach((location, tag) -> { + int[] values = itemTags.get(location); + if (values != null) { + this.items.put(tag, IntList.of(values)); + } else { + session.getGeyser().getLogger().debug("Item tag not found from server: " + location); + } + }); // Hack btw boolean emulatePost1_13Logic = itemTags.get("minecraft:signs").length > 1; @@ -113,98 +95,32 @@ public class TagCache { } } - private IntList load(int @Nullable[] tags) { - if (tags == null) { - return IntLists.EMPTY_LIST; + /** + * @return true if the block tag is present and contains this block mapping's Java ID. + */ + public boolean is(BlockTag tag, BlockMapping mapping) { + IntList values = this.blocks.get(tag); + if (values != null) { + return values.contains(mapping.getJavaBlockId()); } - return IntList.of(tags); + return false; } - public void clear() { - this.leaves = IntLists.emptyList(); - this.wool = IntLists.emptyList(); - - this.axeEffective = IntLists.emptyList(); - this.hoeEffective = IntLists.emptyList(); - this.pickaxeEffective = IntLists.emptyList(); - this.shovelEffective = IntLists.emptyList(); - - this.requiresStoneTool = IntLists.emptyList(); - this.requiresIronTool = IntLists.emptyList(); - this.requiresDiamondTool = IntLists.emptyList(); - - this.axolotlFood = IntLists.emptyList(); - this.creeperIgniters = IntLists.emptyList(); - this.fishes = IntLists.emptyList(); - this.flowers = IntLists.emptyList(); - this.foxFood = IntLists.emptyList(); - this.piglinLoved = IntLists.emptyList(); - this.smallFlowers = IntLists.emptyList(); - this.snifferFood = IntLists.emptyList(); + /** + * @return true if the item tag is present and contains this item stack's Java ID. + */ + public boolean is(ItemTag tag, GeyserItemStack itemStack) { + return is(tag, itemStack.asItem()); } - public boolean isAxolotlFood(Item item) { - return axolotlFood.contains(item.javaId()); - } - - public boolean isCreeperIgniter(Item item) { - return creeperIgniters.contains(item.javaId()); - } - - public boolean isFish(GeyserItemStack itemStack) { - return fishes.contains(itemStack.getJavaId()); - } - - public boolean isFlower(Item item) { - return flowers.contains(item.javaId()); - } - - public boolean isFoxFood(Item item) { - return foxFood.contains(item.javaId()); - } - - public boolean shouldPiglinAdmire(Item item) { - return piglinLoved.contains(item.javaId()); - } - - public boolean isSmallFlower(GeyserItemStack itemStack) { - return smallFlowers.contains(itemStack.getJavaId()); - } - - public boolean isSnifferFood(Item item) { - return snifferFood.contains(item.javaId()); - } - - public boolean isAxeEffective(BlockMapping blockMapping) { - return axeEffective.contains(blockMapping.getJavaBlockId()); - } - - public boolean isHoeEffective(BlockMapping blockMapping) { - return hoeEffective.contains(blockMapping.getJavaBlockId()); - } - - public boolean isPickaxeEffective(BlockMapping blockMapping) { - return pickaxeEffective.contains(blockMapping.getJavaBlockId()); - } - - public boolean isShovelEffective(BlockMapping blockMapping) { - return shovelEffective.contains(blockMapping.getJavaBlockId()); - } - - public boolean isShearsEffective(BlockMapping blockMapping) { - int javaBlockId = blockMapping.getJavaBlockId(); - return leaves.contains(javaBlockId) || wool.contains(javaBlockId); - } - - public boolean requiresStoneTool(BlockMapping blockMapping) { - return requiresStoneTool.contains(blockMapping.getJavaBlockId()); - } - - public boolean requiresIronTool(BlockMapping blockMapping) { - return requiresIronTool.contains(blockMapping.getJavaBlockId()); - } - - public boolean requiresDiamondTool(BlockMapping blockMapping) { - return requiresDiamondTool.contains(blockMapping.getJavaBlockId()); + /** + * @return true if the item tag is present and contains this item's Java ID. + */ + public boolean is(ItemTag tag, Item item) { + IntList values = this.items.get(tag); + if (values != null) { + return values.contains(item.javaId()); + } + return false; } } diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/tags/BlockTag.java b/core/src/main/java/org/geysermc/geyser/session/cache/tags/BlockTag.java new file mode 100644 index 000000000..7017ad55c --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/session/cache/tags/BlockTag.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2019-2024 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.session.cache.tags; + +import org.geysermc.geyser.session.cache.TagCache; + +public enum BlockTag { + LEAVES("leaves"), + WOOL("wool"), + AXE_EFFECTIVE("mineable/axe"), + HOE_EFFECTIVE("mineable/hoe"), + PICKAXE_EFFECTIVE("mineable/pickaxe"), + SHOVEL_EFFECTIVE("mineable/shovel"), + NEEDS_STONE_TOOL("needs_stone_tool"), + NEEDS_IRON_TOOL("needs_iron_tool"), + NEEDS_DIAMOND_TOOL("needs_diamond_tool"); + + BlockTag(String identifier) { + register(identifier, this); + } + + private static void register(String name, BlockTag tag) { + TagCache.ALL_BLOCK_TAGS.put("minecraft:" + name, tag); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/tags/ItemTag.java b/core/src/main/java/org/geysermc/geyser/session/cache/tags/ItemTag.java new file mode 100644 index 000000000..df9a423ed --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/session/cache/tags/ItemTag.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2019-2024 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.session.cache.tags; + +import org.geysermc.geyser.session.cache.TagCache; + +public enum ItemTag { + AXOLOTL_FOOD("axolotl_food"), + CREEPER_IGNITERS("creeper_igniters"), + FISHES("fishes"), + FLOWERS("flowers"), + FOX_FOOD("fox_food"), + PIGLIN_LOVED("piglin_loved"), + SMALL_FLOWERS("small_flowers"), + SNIFFER_FOOD("sniffer_food"); + + ItemTag(String identifier) { + register(identifier, this); + } + + private static void register(String name, ItemTag tag) { + TagCache.ALL_ITEM_TAGS.put("minecraft:" + name, tag); + } +} 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 fce928bdb..450c786f2 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 @@ -47,10 +47,6 @@ public class BiomeTranslator { public static int loadServerBiome(RegistryEntry entry) { String javaIdentifier = entry.getId(); return Registries.BIOME_IDENTIFIERS.get().getOrDefault(javaIdentifier, 0); -// if (javaId == 0) { -// // Matches Java behavior when it sees an invalid biome - it just replaces it with ID 0 -// biomeTranslations.defaultReturnValue(bedrockId); -// } } public static BlockStorage toNewBedrockBiome(GeyserSession session, DataPalette biomeData) { diff --git a/core/src/main/java/org/geysermc/geyser/util/BlockUtils.java b/core/src/main/java/org/geysermc/geyser/util/BlockUtils.java index da98f45c7..8392f9fcd 100644 --- a/core/src/main/java/org/geysermc/geyser/util/BlockUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/BlockUtils.java @@ -36,17 +36,18 @@ import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.type.BlockMapping; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.BlockTag; import org.geysermc.geyser.translator.collision.BlockCollision; public final class BlockUtils { private static boolean correctTool(GeyserSession session, BlockMapping blockMapping, String itemToolType) { return switch (itemToolType) { - case "axe" -> session.getTagCache().isAxeEffective(blockMapping); - case "hoe" -> session.getTagCache().isHoeEffective(blockMapping); - case "pickaxe" -> session.getTagCache().isPickaxeEffective(blockMapping); - case "shears" -> session.getTagCache().isShearsEffective(blockMapping); - case "shovel" -> session.getTagCache().isShovelEffective(blockMapping); + case "axe" -> session.getTagCache().is(BlockTag.AXE_EFFECTIVE, blockMapping); + case "hoe" -> session.getTagCache().is(BlockTag.HOE_EFFECTIVE, blockMapping); + case "pickaxe" -> session.getTagCache().is(BlockTag.PICKAXE_EFFECTIVE, blockMapping); + case "shears" -> session.getTagCache().is(BlockTag.LEAVES, blockMapping) || session.getTagCache().is(BlockTag.WOOL, blockMapping); + case "shovel" -> session.getTagCache().is(BlockTag.SHOVEL_EFFECTIVE, blockMapping); case "sword" -> blockMapping.getJavaBlockId() == BlockStateValues.JAVA_COBWEB_ID; default -> { session.getGeyser().getLogger().warning("Unknown tool type: " + itemToolType); @@ -79,15 +80,15 @@ public final class BlockUtils { switch (toolTier) { // Use intentional fall-throughs to check each tier with this block default: - if (session.getTagCache().requiresStoneTool(blockMapping)) { + if (session.getTagCache().is(BlockTag.NEEDS_STONE_TOOL, blockMapping)) { return false; } case "stone": - if (session.getTagCache().requiresIronTool(blockMapping)) { + if (session.getTagCache().is(BlockTag.NEEDS_IRON_TOOL, blockMapping)) { return false; } case "iron": - if (session.getTagCache().requiresDiamondTool(blockMapping)) { + if (session.getTagCache().is(BlockTag.NEEDS_DIAMOND_TOOL, blockMapping)) { return false; } } @@ -131,7 +132,7 @@ public final class BlockUtils { } public static double getBreakTime(GeyserSession session, BlockMapping blockMapping, ItemMapping item, @Nullable DataComponents components, boolean isSessionPlayer) { - boolean isShearsEffective = session.getTagCache().isShearsEffective(blockMapping); //TODO called twice + boolean isShearsEffective = session.getTagCache().is(BlockTag.LEAVES, blockMapping) || session.getTagCache().is(BlockTag.WOOL, blockMapping); //TODO called twice boolean canHarvestWithHand = blockMapping.isCanBreakWithHand(); String toolType = ""; String toolTier = ""; From d105dadf62a79d6f81e6829f1919545dce745c4a Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Tue, 23 Apr 2024 12:36:39 -0400 Subject: [PATCH 281/344] Update for release. STILL NOT READY YET THOUGH --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f2e068c22..bbb6045f5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ protocol-connection = "3.0.0.Beta1-20240411.165033-128" raknet = "1.0.0.CR3-20240416.144209-1" blockstateupdater="1.20.80-20240411.142413-1" mcauthlib = "d9d773e" -mcprotocollib = "7026b600" # Revert from jitpack after release +mcprotocollib = "3c81cc80" # Revert from jitpack after release adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" From abea0131e41e62fe76f750f8e7a1e08a73b32eb2 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Tue, 23 Apr 2024 16:08:26 -0400 Subject: [PATCH 282/344] Fix llama carpets --- .../geyser/entity/EntityDefinitions.java | 1 - .../type/living/animal/horse/LlamaEntity.java | 27 ------------------- .../populator/ItemRegistryPopulator.java | 10 ------- .../geyser/registry/type/ItemMappings.java | 1 - .../entity/JavaSetEquipmentTranslator.java | 3 ++- 5 files changed, 2 insertions(+), 40 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java index 6b243212d..d825daa8a 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java +++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java @@ -938,7 +938,6 @@ public final class EntityDefinitions { .type(EntityType.LLAMA) .height(1.87f).width(0.9f) .addTranslator(MetadataType.INT, (entity, entityMetadata) -> entity.getDirtyMetadata().put(EntityDataTypes.STRENGTH, entityMetadata.getValue())) - .addTranslator(MetadataType.INT, LlamaEntity::setCarpetedColor) .addTranslator(MetadataType.INT, (entity, entityMetadata) -> entity.getDirtyMetadata().put(EntityDataTypes.VARIANT, entityMetadata.getValue())) .build(); TRADER_LLAMA = EntityDefinition.inherited(TraderLlamaEntity::new, LLAMA) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/LlamaEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/LlamaEntity.java index a32d7b1b5..7fcada504 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/LlamaEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/LlamaEntity.java @@ -25,11 +25,8 @@ package org.geysermc.geyser.entity.type.living.animal.horse; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; -import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; -import org.cloudburstmc.protocol.bedrock.packet.MobArmorEquipmentPacket; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.Item; @@ -45,30 +42,6 @@ public class LlamaEntity extends ChestedHorseEntity { dirtyMetadata.put(EntityDataTypes.CONTAINER_STRENGTH_MODIFIER, 3); // Presumably 3 slots for every 1 strength } - /** - * Color equipped on the llama - */ - public void setCarpetedColor(IntEntityMetadata entityMetadata) { - // Bedrock treats llama decoration as armor - MobArmorEquipmentPacket equipmentPacket = new MobArmorEquipmentPacket(); - equipmentPacket.setRuntimeEntityId(geyserId); - // -1 means no armor - int carpetIndex = entityMetadata.getPrimitiveValue(); - if (carpetIndex > -1 && carpetIndex <= 15) { - // The damage value is the dye color that Java sends us, for pre-1.16.220 - // The item is always going to be a carpet - equipmentPacket.setChestplate(session.getItemMappings().getCarpets().get(carpetIndex)); - } else { - equipmentPacket.setChestplate(ItemData.AIR); - } - // Required to fill out the rest of the equipment or Bedrock ignores it, including above else statement if removing armor - equipmentPacket.setBoots(ItemData.AIR); - equipmentPacket.setHelmet(ItemData.AIR); - equipmentPacket.setLeggings(ItemData.AIR); - - session.sendUpstreamPacket(equipmentPacket); - } - @Override public boolean canEat(Item item) { return item == Items.WHEAT || item == Items.HAY_BLOCK; 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 5b64da7a1..d3a4bed84 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 @@ -159,7 +159,6 @@ public class ItemRegistryPopulator { Object2ObjectMap customBlockItemDefinitions = new Object2ObjectOpenHashMap<>(); List buckets = new ObjectArrayList<>(); - List carpets = new ObjectArrayList<>(); List mappings = new ObjectArrayList<>(); // Temporary mapping to create stored items @@ -458,14 +457,6 @@ public class ItemRegistryPopulator { if (javaItem.javaIdentifier().contains("bucket") && !javaItem.javaIdentifier().contains("milk")) { buckets.add(definition); - } else if (javaItem.javaIdentifier().contains("_carpet") && !javaItem.javaIdentifier().contains("moss")) { - // This should be the numerical order Java sends as an integer value for llamas - carpets.add(ItemData.builder() - .definition(definition) - .damage(mapping.getBedrockData()) - .count(1) - .blockDefinition(mapping.getBedrockBlockDefinition()) - .build()); } else if (javaItem.javaIdentifier().startsWith("minecraft:music_disc_")) { // The Java record level event uses the item ID as the "key" to play the record Registries.RECORDS.register(javaItem.javaId(), SoundEvent.valueOf("RECORD_" + @@ -589,7 +580,6 @@ public class ItemRegistryPopulator { .storedItems(new StoredItemMappings(javaItemToMapping)) .javaOnlyItems(javaOnlyItems) .buckets(buckets) - .carpets(carpets) .componentItemData(componentItemData) .lodestoneCompass(lodestoneEntry) .customIdMappings(customIdMappings) 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 33908a7e7..5df969111 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 @@ -69,7 +69,6 @@ public class ItemMappings implements DefinitionRegistry { List buckets; List boats; - List carpets; List componentItemData; Int2ObjectMap customIdMappings; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEquipmentTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEquipmentTranslator.java index b0168a4ce..7c93725e0 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEquipmentTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEquipmentTranslator.java @@ -74,7 +74,8 @@ public class JavaSetEquipmentTranslator extends PacketTranslator { + case CHESTPLATE, BODY -> { + // BODY is sent for llamas with a carpet equipped, as of 1.20.5 livingEntity.setChestplate(item); armorUpdated = true; } From c54624fb2632dd5dc60626eb55ea830b3818836c Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Tue, 23 Apr 2024 16:14:18 -0400 Subject: [PATCH 283/344] Fix some cases of empty tags being needed --- .../level/block/entity/BlockEntityTranslator.java | 8 ++++++-- .../level/JavaLevelChunkWithLightTranslator.java | 12 ++++++++---- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BlockEntityTranslator.java index 7566e0d90..053e2c8f3 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BlockEntityTranslator.java @@ -43,12 +43,16 @@ public abstract class BlockEntityTranslator { public abstract void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState); public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, CompoundTag tag, int blockState) { - NbtMapBuilder tagBuilder = getConstantBedrockTag(BlockEntityUtils.getBedrockBlockEntityId(type), x, y, z); + NbtMapBuilder tagBuilder = getConstantBedrockTag(type, x, y, z); translateTag(tagBuilder, tag, blockState); return tagBuilder.build(); } - protected NbtMapBuilder getConstantBedrockTag(String bedrockId, int x, int y, int z) { + public static NbtMapBuilder getConstantBedrockTag(BlockEntityType type, int x, int y, int z) { + return getConstantBedrockTag(BlockEntityUtils.getBedrockBlockEntityId(type), x, y, z); + } + + public static NbtMapBuilder getConstantBedrockTag(String bedrockId, int x, int y, int z) { return NbtMap.builder() .putInt("x", x) .putInt("y", y) 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 fc1d0316c..1e6534130 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 @@ -393,10 +393,9 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator Date: Tue, 23 Apr 2024 23:04:38 +0200 Subject: [PATCH 284/344] target 1.20.5 release, build neoforge again --- .github/workflows/build-remote.yml | 2 +- .github/workflows/build.yml | 2 +- .github/workflows/preview.yml | 2 +- README.md | 2 +- bootstrap/mod/build.gradle.kts | 3 +-- bootstrap/mod/fabric/src/main/resources/fabric.mod.json | 2 +- .../mod/neoforge/src/main/resources/META-INF/mods.toml | 4 ++-- .../src/main/kotlin/geyser.modded-conventions.gradle.kts | 4 ++-- build.gradle.kts | 2 +- gradle/libs.versions.toml | 8 ++++---- settings.gradle.kts | 4 ++-- 11 files changed, 17 insertions(+), 18 deletions(-) diff --git a/.github/workflows/build-remote.yml b/.github/workflows/build-remote.yml index 09326d429..d49920785 100644 --- a/.github/workflows/build-remote.yml +++ b/.github/workflows/build-remote.yml @@ -64,7 +64,7 @@ jobs: with: name: Geyser NeoForge path: geyser/bootstrap/mod/neoforge/build/libs/Geyser-NeoForge.jar - #if-no-files-found: error // TODO 1.20.5 until neoforge updates + if-no-files-found: error - name: Archive artifacts (Geyser Standalone) uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 if: success() diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cfb509f30..284fa265a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -68,7 +68,7 @@ jobs: with: name: Geyser NeoForge path: bootstrap/mod/neoforge/build/libs/Geyser-NeoForge.jar - #if-no-files-found: error // TODO 1.20.5 - currently no neoforge artifacts + if-no-files-found: error - name: Archive artifacts (Geyser Standalone) uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 if: success() diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index a33c71a79..13712d5ef 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -53,10 +53,10 @@ jobs: with: appID: ${{ secrets.RELEASE_APP_ID }} appPrivateKey: ${{ secrets.RELEASE_APP_PK }} - # neoforge:Geyser-NeoForge.jar // TODO 1.20.5 files: | bungeecord:Geyser-BungeeCord.jar fabric:Geyser-Fabric.jar + neoforge:Geyser-NeoForge.jar spigot:Geyser-Spigot.jar standalone:Geyser-Standalone.jar velocity:Geyser-Velocity.jar diff --git a/README.md b/README.md index e17c9d2bb..314876d60 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,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.20.40 - 1.20.80 and Minecraft Java 1.20.4 +### Currently supporting Minecraft Bedrock 1.20.40 - 1.20.80 and Minecraft Java 1.20.5 ## Setting Up Take a look [here](https://wiki.geysermc.org/geyser/setup/) for how to set up Geyser. diff --git a/bootstrap/mod/build.gradle.kts b/bootstrap/mod/build.gradle.kts index 281fd45e7..7651a2df2 100644 --- a/bootstrap/mod/build.gradle.kts +++ b/bootstrap/mod/build.gradle.kts @@ -1,6 +1,5 @@ architectury { - common("fabric") - //common("neoforge", "fabric") // todo 1.20.5 + common("neoforge", "fabric") } loom { diff --git a/bootstrap/mod/fabric/src/main/resources/fabric.mod.json b/bootstrap/mod/fabric/src/main/resources/fabric.mod.json index 7fb6b302c..93f48b73c 100644 --- a/bootstrap/mod/fabric/src/main/resources/fabric.mod.json +++ b/bootstrap/mod/fabric/src/main/resources/fabric.mod.json @@ -25,6 +25,6 @@ "depends": { "fabricloader": ">=0.15.10", "fabric": "*", - "minecraft": ">=1.20.4" + "minecraft": ">=1.20.5" } } diff --git a/bootstrap/mod/neoforge/src/main/resources/META-INF/mods.toml b/bootstrap/mod/neoforge/src/main/resources/META-INF/mods.toml index 2f9e9b12e..1110568e8 100644 --- a/bootstrap/mod/neoforge/src/main/resources/META-INF/mods.toml +++ b/bootstrap/mod/neoforge/src/main/resources/META-INF/mods.toml @@ -14,12 +14,12 @@ config = "geyser.mixins.json" [[dependencies.geyser_neoforge]] modId="neoforge" type="required" - versionRange="[20.4.48-beta,)" + versionRange="[20.5.0-beta,)" ordering="NONE" side="BOTH" [[dependencies.geyser_neoforge]] modId="minecraft" type="required" - versionRange="[1.20,1.21)" + versionRange="[1.20.4,1.21)" ordering="NONE" side="BOTH" \ No newline at end of file diff --git a/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts b/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts index c83ea2911..afea247a7 100644 --- a/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts @@ -39,7 +39,7 @@ provided("io.netty", "netty-resolver-dns-native-macos") provided("org.ow2.asm", "asm") architectury { - minecraft = "1.20.4" + minecraft = "1.20.5" } loom { @@ -110,7 +110,7 @@ afterEvaluate { } dependencies { - minecraft("com.mojang:minecraft:1.20.5-rc3") + minecraft("com.mojang:minecraft:1.20.5") mappings(loom.officialMojangMappings()) } diff --git a/build.gradle.kts b/build.gradle.kts index fdacd5538..dfdff2187 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -22,7 +22,7 @@ val basePlatforms = setOf( val moddedPlatforms = setOf( projects.fabric, - //projects.neoforge, // todo 1.20.5 + projects.neoforge, projects.mod ).map { it.dependencyProject } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index bbb6045f5..2b6df11a6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -30,11 +30,11 @@ commodore = "2.2" bungeecord = "a7c6ede" velocity = "3.1.1" viaproxy = "3.2.0-SNAPSHOT" -fabric-minecraft = "1.20.4" -fabric-loader = "0.15.2" -fabric-api = "0.91.2+1.20.4" +fabric-minecraft = "1.20.5" +fabric-loader = "0.15.10" +fabric-api = "0.97.6+1.20.5" fabric-permissions = "0.2-SNAPSHOT" -neoforge-minecraft = "20.4.48-beta" +neoforge-minecraft = "20.5.0-beta" mixin = "0.8.5" # plugin versions diff --git a/settings.gradle.kts b/settings.gradle.kts index 3867d7a84..a39bfa3d2 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -66,7 +66,7 @@ include(":ap") include(":api") include(":bungeecord") include(":fabric") -//include(":neoforge") // todo 1.20.5 +include(":neoforge") include(":mod") include(":spigot") include(":standalone") @@ -78,7 +78,7 @@ include(":core") // Specify project dirs project(":bungeecord").projectDir = file("bootstrap/bungeecord") project(":fabric").projectDir = file("bootstrap/mod/fabric") -//project(":neoforge").projectDir = file("bootstrap/mod/neoforge") // todo 1.20.5 +project(":neoforge").projectDir = file("bootstrap/mod/neoforge") project(":mod").projectDir = file("bootstrap/mod") project(":spigot").projectDir = file("bootstrap/spigot") project(":standalone").projectDir = file("bootstrap/standalone") From bbaffb2ab38a825c0ab4ec7a360bf0ac831fa773 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Tue, 23 Apr 2024 19:12:20 -0400 Subject: [PATCH 285/344] Wolf interactions --- .../living/animal/tameable/WolfEntity.java | 25 ++++++++++++++----- .../geysermc/geyser/util/InteractiveTag.java | 5 +++- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java index ee7281772..ff130aeff 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java @@ -133,16 +133,29 @@ public class WolfEntity extends TameableEntity { if (itemInHand.asItem() == Items.BONE && !getFlag(EntityFlag.TAMED)) { // Bone and untamed - can tame return InteractiveTag.TAME; - } else { - if (itemInHand.asItem() instanceof DyeItem item) { + } + if (getFlag(EntityFlag.TAMED) && ownerBedrockId == session.getPlayerEntity().getGeyserId()) { + if (itemInHand.asItem() instanceof DyeItem dyeItem) { // If this fails, as of Java Edition 1.18.1, you cannot toggle sit/stand - if (item.dyeColor() != this.collarColor) { + if (dyeItem.dyeColor() != this.collarColor) { return InteractiveTag.DYE; + } else { + return super.testMobInteraction(hand, itemInHand); } - } else if (getFlag(EntityFlag.TAMED) && ownerBedrockId == session.getPlayerEntity().getGeyserId()) { - // Tamed and owned by player - can sit/stand - return getFlag(EntityFlag.SITTING) ? InteractiveTag.STAND : InteractiveTag.SIT; } + if (itemInHand.asItem() == Items.WOLF_ARMOR && !this.chestplate.isValid() && !getFlag(EntityFlag.BABY)) { + return InteractiveTag.EQUIP_WOLF_ARMOR; + } + if (itemInHand.asItem() == Items.SHEARS && this.chestplate.isValid()) { // TODO: check curse of binding + return InteractiveTag.REMOVE_WOLF_ARMOR; + } + if (Items.WOLF_ARMOR.isValidRepairItem(itemInHand.asItem()) && getFlag(EntityFlag.SITTING) && + this.chestplate.isValid() && this.chestplate.getTag() != null && + this.chestplate.getTag().getInt("Damage") > 0) { + return InteractiveTag.REPAIR_WOLF_ARMOR; + } + // Tamed and owned by player - can sit/stand + return getFlag(EntityFlag.SITTING) ? InteractiveTag.STAND : InteractiveTag.SIT; } return super.testMobInteraction(hand, itemInHand); } diff --git a/core/src/main/java/org/geysermc/geyser/util/InteractiveTag.java b/core/src/main/java/org/geysermc/geyser/util/InteractiveTag.java index 9607ac61e..168c861f5 100644 --- a/core/src/main/java/org/geysermc/geyser/util/InteractiveTag.java +++ b/core/src/main/java/org/geysermc/geyser/util/InteractiveTag.java @@ -70,7 +70,10 @@ public enum InteractiveTag { READ, WAKE_VILLAGER("wakevillager"), BARTER, - GIVE_ITEM_TO_ALLAY("allay"); + GIVE_ITEM_TO_ALLAY("allay"), + EQUIP_WOLF_ARMOR("equipwolfarmor"), + REMOVE_WOLF_ARMOR("removewolfarmor"), + REPAIR_WOLF_ARMOR("repairwolfarmor"); /** * The full string that should be passed on to the client. From a1534e45350f8787f49c8d07aacdfa683b65dbb4 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Tue, 23 Apr 2024 20:11:32 -0400 Subject: [PATCH 286/344] Basic Armadillo structure --- .../geyser/entity/EntityDefinitions.java | 6 +++ .../type/living/animal/ArmadilloEntity.java | 38 +++++++++++++++++++ .../geyser/registry/type/ItemMappings.java | 4 +- 3 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ArmadilloEntity.java diff --git a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java index d825daa8a..9563e6d37 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java +++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java @@ -53,6 +53,7 @@ import org.geysermc.geyser.translator.text.MessageTranslator; public final class EntityDefinitions { public static final EntityDefinition ALLAY; public static final EntityDefinition AREA_EFFECT_CLOUD; + public static final EntityDefinition ARMADILLO; public static final EntityDefinition ARMOR_STAND; public static final EntityDefinition ARROW; public static final EntityDefinition AXOLOTL; @@ -770,6 +771,11 @@ public final class EntityDefinitions { // Extends ageable { + ARMADILLO = EntityDefinition.inherited(ArmadilloEntity::new, ageableEntityBase) + .type(EntityType.ARMADILLO) + .height(0.65f).width(0.7f) + .addTranslator(null) + .build(); AXOLOTL = EntityDefinition.inherited(AxolotlEntity::new, ageableEntityBase) .type(EntityType.AXOLOTL) .height(0.42f).width(0.7f) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ArmadilloEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ArmadilloEntity.java new file mode 100644 index 000000000..d89b4e3f7 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ArmadilloEntity.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2019-2024 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.entity.type.living.animal; + +import org.cloudburstmc.math.vector.Vector3f; +import org.geysermc.geyser.entity.EntityDefinition; +import org.geysermc.geyser.session.GeyserSession; + +import java.util.UUID; + +public class ArmadilloEntity extends AnimalEntity { + public ArmadilloEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { + super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); + } +} 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 5df969111..199481cbc 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 @@ -98,9 +98,9 @@ public class ItemMappings implements DefinitionRegistry { return javaId >= 0 && javaId < this.items.length ? this.items[javaId] : ItemMapping.AIR; } - @Nullable + @NonNull public ItemMapping getMapping(Item javaItem) { - return getMapping(javaItem.javaIdentifier()); + return getMapping(javaItem.javaId()); } /** From 9490a091b576155b8d60a9216a6d0192153143a3 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Tue, 23 Apr 2024 20:43:46 -0400 Subject: [PATCH 287/344] Calculate horse inventory size --- .../geysermc/geyser/entity/EntityDefinitions.java | 2 +- .../type/living/animal/horse/LlamaEntity.java | 13 +++++++++++++ .../inventory/JavaHorseScreenOpenTranslator.java | 14 ++++++++++++-- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java index 9563e6d37..f454bef88 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java +++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java @@ -943,7 +943,7 @@ public final class EntityDefinitions { LLAMA = EntityDefinition.inherited(LlamaEntity::new, chestedHorseEntityBase) .type(EntityType.LLAMA) .height(1.87f).width(0.9f) - .addTranslator(MetadataType.INT, (entity, entityMetadata) -> entity.getDirtyMetadata().put(EntityDataTypes.STRENGTH, entityMetadata.getValue())) + .addTranslator(MetadataType.INT, LlamaEntity::setStrength) .addTranslator(MetadataType.INT, (entity, entityMetadata) -> entity.getDirtyMetadata().put(EntityDataTypes.VARIANT, entityMetadata.getValue())) .build(); TRADER_LLAMA = EntityDefinition.inherited(TraderLlamaEntity::new, LLAMA) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/LlamaEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/LlamaEntity.java index 7fcada504..29da2e0dc 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/LlamaEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/LlamaEntity.java @@ -25,16 +25,24 @@ package org.geysermc.geyser.entity.type.living.animal.horse; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; +import lombok.Getter; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.util.MathUtils; import java.util.UUID; public class LlamaEntity extends ChestedHorseEntity { + /** + * Used to calculate inventory size + */ + @Getter + private int strength = 1; public LlamaEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); @@ -42,6 +50,11 @@ public class LlamaEntity extends ChestedHorseEntity { dirtyMetadata.put(EntityDataTypes.CONTAINER_STRENGTH_MODIFIER, 3); // Presumably 3 slots for every 1 strength } + public void setStrength(IntEntityMetadata entityMetadata) { + strength = MathUtils.constrain(entityMetadata.getPrimitiveValue(), 1, 5); + this.dirtyMetadata.put(EntityDataTypes.STRENGTH, strength); + } + @Override public boolean canEat(Item item) { return item == Items.WHEAT || item == Items.HAY_BLOCK; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaHorseScreenOpenTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaHorseScreenOpenTranslator.java index 33cfeaf31..d2abcb5e3 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaHorseScreenOpenTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaHorseScreenOpenTranslator.java @@ -29,6 +29,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.clientbound.inventory.Cli import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; +import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; import org.cloudburstmc.protocol.bedrock.packet.UpdateEquipPacket; import org.geysermc.geyser.entity.type.Entity; @@ -114,16 +115,25 @@ public class JavaHorseScreenOpenTranslator extends PacketTranslator Date: Wed, 24 Apr 2024 16:39:35 -0400 Subject: [PATCH 288/344] Move MCProtocolLib to dev - package ID change --- .../mod/world/GeyserModWorldManager.java | 18 +++--- .../platform/spigot/GeyserSpigotInjector.java | 2 +- .../platform/spigot/PaperAdventure.java | 2 +- .../spigot/world/GeyserPistonListener.java | 2 +- .../manager/GeyserSpigotWorldManager.java | 6 +- .../java/org/geysermc/geyser/GeyserImpl.java | 2 +- .../command/defaults/StatisticsCommand.java | 4 +- .../geyser/dump/BootstrapDumpInfo.java | 2 +- .../org/geysermc/geyser/dump/DumpInfo.java | 7 +-- .../geyser/entity/EntityDefinition.java | 6 +- .../geyser/entity/EntityDefinitions.java | 8 +-- .../entity/type/AbstractArrowEntity.java | 4 +- .../entity/type/AreaEffectCloudEntity.java | 6 +- .../geyser/entity/type/BoatEntity.java | 9 ++- .../geyser/entity/type/ChestBoatEntity.java | 2 +- .../type/CommandBlockMinecartEntity.java | 2 +- .../type/DefaultBlockMinecartEntity.java | 4 +- .../entity/type/EnderCrystalEntity.java | 2 +- .../geysermc/geyser/entity/type/Entity.java | 27 +++------ .../entity/type/FallingBlockEntity.java | 2 +- .../geyser/entity/type/FireworkEntity.java | 6 +- .../geyser/entity/type/FishingHookEntity.java | 4 +- .../entity/type/FurnaceMinecartEntity.java | 4 +- .../geyser/entity/type/InteractionEntity.java | 8 +-- .../geyser/entity/type/ItemEntity.java | 4 +- .../geyser/entity/type/ItemFrameEntity.java | 14 ++--- .../geyser/entity/type/LeashKnotEntity.java | 2 +- .../geyser/entity/type/LivingEntity.java | 16 ++--- .../geyser/entity/type/MinecartEntity.java | 6 +- .../geyser/entity/type/PaintingEntity.java | 6 +- .../geyser/entity/type/TNTEntity.java | 2 +- .../geyser/entity/type/TextDisplayEntity.java | 4 +- .../geyser/entity/type/ThrowableEntity.java | 2 +- .../entity/type/ThrowableItemEntity.java | 4 +- .../entity/type/ThrownPotionEntity.java | 10 ++-- .../geyser/entity/type/TippedArrowEntity.java | 2 +- .../geyser/entity/type/WitherSkullEntity.java | 2 +- .../type/living/AbstractFishEntity.java | 2 +- .../entity/type/living/AgeableEntity.java | 2 +- .../entity/type/living/AllayEntity.java | 4 +- .../entity/type/living/ArmorStandEntity.java | 8 +-- .../geyser/entity/type/living/BatEntity.java | 2 +- .../entity/type/living/DolphinEntity.java | 2 +- .../entity/type/living/IronGolemEntity.java | 2 +- .../geyser/entity/type/living/MobEntity.java | 4 +- .../entity/type/living/SlimeEntity.java | 2 +- .../entity/type/living/SnowGolemEntity.java | 4 +- .../entity/type/living/TadpoleEntity.java | 2 +- .../type/living/animal/AnimalEntity.java | 2 +- .../type/living/animal/AxolotlEntity.java | 6 +- .../entity/type/living/animal/BeeEntity.java | 4 +- .../entity/type/living/animal/CowEntity.java | 2 +- .../entity/type/living/animal/FoxEntity.java | 4 +- .../entity/type/living/animal/FrogEntity.java | 6 +- .../entity/type/living/animal/GoatEntity.java | 6 +- .../type/living/animal/HoglinEntity.java | 2 +- .../type/living/animal/MooshroomEntity.java | 4 +- .../type/living/animal/OcelotEntity.java | 2 +- .../type/living/animal/PandaEntity.java | 6 +- .../entity/type/living/animal/PigEntity.java | 2 +- .../type/living/animal/PufferFishEntity.java | 2 +- .../type/living/animal/RabbitEntity.java | 2 +- .../type/living/animal/SheepEntity.java | 4 +- .../type/living/animal/SnifferEntity.java | 6 +- .../type/living/animal/StriderEntity.java | 4 +- .../living/animal/TropicalFishEntity.java | 4 +- .../type/living/animal/TurtleEntity.java | 2 +- .../animal/horse/AbstractHorseEntity.java | 4 +- .../type/living/animal/horse/CamelEntity.java | 6 +- .../type/living/animal/horse/HorseEntity.java | 2 +- .../type/living/animal/horse/LlamaEntity.java | 2 +- .../animal/horse/SkeletonHorseEntity.java | 2 +- .../animal/horse/ZombieHorseEntity.java | 2 +- .../living/animal/tameable/CatEntity.java | 8 +-- .../living/animal/tameable/ParrotEntity.java | 2 +- .../animal/tameable/TameableEntity.java | 6 +- .../living/animal/tameable/WolfEntity.java | 6 +- .../merchant/AbstractMerchantEntity.java | 2 +- .../type/living/merchant/VillagerEntity.java | 4 +- .../monster/AbstractSkeletonEntity.java | 2 +- .../type/living/monster/BasePiglinEntity.java | 2 +- .../type/living/monster/BlazeEntity.java | 2 +- .../type/living/monster/CreeperEntity.java | 6 +- .../living/monster/EnderDragonEntity.java | 10 +--- .../type/living/monster/EndermanEntity.java | 4 +- .../type/living/monster/GhastEntity.java | 2 +- .../type/living/monster/GuardianEntity.java | 2 +- .../type/living/monster/PhantomEntity.java | 2 +- .../type/living/monster/PiglinEntity.java | 4 +- .../type/living/monster/ShulkerEntity.java | 6 +- .../type/living/monster/SkeletonEntity.java | 2 +- .../type/living/monster/SpiderEntity.java | 2 +- .../entity/type/living/monster/VexEntity.java | 2 +- .../type/living/monster/WardenEntity.java | 4 +- .../type/living/monster/WitherEntity.java | 2 +- .../type/living/monster/ZoglinEntity.java | 2 +- .../type/living/monster/ZombieEntity.java | 2 +- .../living/monster/ZombieVillagerEntity.java | 8 +-- .../raid/SpellcasterIllagerEntity.java | 2 +- .../living/monster/raid/VindicatorEntity.java | 2 +- .../entity/type/player/PlayerEntity.java | 31 +++++----- .../type/player/SessionPlayerEntity.java | 14 ++--- .../entity/type/player/SkullPlayerEntity.java | 2 +- .../erosion/GeyserboundPacketHandlerImpl.java | 4 +- .../geyser/impl/camera/GeyserCameraData.java | 13 +---- .../geyser/impl/camera/GeyserCameraFade.java | 2 +- .../geyser/inventory/AnvilContainer.java | 4 +- .../geyser/inventory/BeaconContainer.java | 2 +- .../inventory/CartographyContainer.java | 2 +- .../geysermc/geyser/inventory/Container.java | 2 +- .../geyser/inventory/CrafterContainer.java | 2 +- .../geyser/inventory/EnchantingContainer.java | 2 +- .../geyser/inventory/Generic3X3Container.java | 2 +- .../geyser/inventory/GeyserItemStack.java | 6 +- .../geysermc/geyser/inventory/Inventory.java | 6 +- .../geyser/inventory/LecternContainer.java | 2 +- .../geyser/inventory/MerchantContainer.java | 6 +- .../geyser/inventory/PlayerInventory.java | 2 +- .../inventory/StonecutterContainer.java | 2 +- .../geyser/inventory/click/Click.java | 2 +- .../geyser/inventory/click/ClickPlan.java | 10 ++-- .../geyser/inventory/recipe/GeyserRecipe.java | 2 +- .../inventory/recipe/GeyserShapedRecipe.java | 6 +- .../recipe/GeyserShapelessRecipe.java | 6 +- .../recipe/GeyserStonecutterData.java | 2 +- .../geyser/inventory/recipe/TrimRecipe.java | 2 +- .../updater/AnvilInventoryUpdater.java | 6 +- .../geyser/item/DyeableLeatherItem.java | 6 +- .../geysermc/geyser/item/type/ArmorItem.java | 6 +- .../geysermc/geyser/item/type/ArrowItem.java | 2 +- .../geyser/item/type/AxolotlBucketItem.java | 2 +- .../geysermc/geyser/item/type/BannerItem.java | 6 +- .../geysermc/geyser/item/type/ChestItem.java | 2 +- .../geyser/item/type/CompassItem.java | 8 +-- .../geyser/item/type/CrossbowItem.java | 6 +- .../geyser/item/type/DecoratedPotItem.java | 4 +- .../geyser/item/type/DyeableArmorItem.java | 2 +- .../item/type/DyeableHorseArmorItem.java | 2 +- .../geyser/item/type/EnchantedBookItem.java | 6 +- .../geyser/item/type/FilledMapItem.java | 4 +- .../geyser/item/type/FireworkRocketItem.java | 10 ++-- .../geyser/item/type/FireworkStarItem.java | 6 +- .../geyser/item/type/FishingRodItem.java | 2 +- .../geyser/item/type/GoatHornItem.java | 10 ++-- .../org/geysermc/geyser/item/type/Item.java | 10 ++-- .../geysermc/geyser/item/type/MapItem.java | 7 ++- .../geyser/item/type/PlayerHeadItem.java | 4 +- .../geysermc/geyser/item/type/PotionItem.java | 8 +-- .../geysermc/geyser/item/type/ShieldItem.java | 2 +- .../geyser/item/type/ShulkerBoxItem.java | 6 +- .../geyser/item/type/TippedArrowItem.java | 6 +- .../item/type/TropicalFishBucketItem.java | 4 +- .../geyser/item/type/WritableBookItem.java | 8 +-- .../geyser/item/type/WrittenBookItem.java | 8 +-- .../geysermc/geyser/level/BedrockMapIcon.java | 2 +- .../geyser/level/GeyserAdvancement.java | 6 +- .../geyser/level/GeyserWorldManager.java | 12 ++-- .../geysermc/geyser/level/JavaDimension.java | 2 +- .../geysermc/geyser/level/PaintingType.java | 2 +- .../geysermc/geyser/level/WorldManager.java | 8 +-- .../block/GeyserCustomBlockComponents.java | 13 +---- .../geyser/level/chunk/GeyserChunk.java | 2 +- .../geyser/level/physics/BoundingBox.java | 2 +- .../level/physics/CollisionManager.java | 4 +- .../geyser/level/physics/Direction.java | 18 +++--- .../geysermc/geyser/network/GameProtocol.java | 4 +- .../geyser/network/netty/LocalSession.java | 14 ++--- .../geyser/pack/SkullResourcePackManager.java | 4 +- .../ping/GeyserLegacyPingPassthrough.java | 4 +- .../geyser/ping/IGeyserPingPassthrough.java | 1 + .../registry/PacketTranslatorRegistry.java | 8 +-- .../geysermc/geyser/registry/Registries.java | 12 ++-- .../loader/BlockEntityRegistryLoader.java | 2 +- .../loader/ParticleTypesRegistryLoader.java | 2 +- .../loader/SoundEventsRegistryLoader.java | 8 +-- .../mappings/versions/MappingsReader_v1.java | 2 +- .../populator/PacketRegistryPopulator.java | 2 +- .../populator/RecipeRegistryPopulator.java | 6 +- .../geyser/registry/type/ItemMappings.java | 2 +- .../geysermc/geyser/scoreboard/Objective.java | 6 +- .../org/geysermc/geyser/scoreboard/Score.java | 4 +- .../geyser/scoreboard/Scoreboard.java | 7 +-- .../org/geysermc/geyser/scoreboard/Team.java | 4 +- .../geyser/session/DownstreamSession.java | 6 +- .../geyser/session/GeyserSession.java | 58 +++++++++---------- .../session/cache/AdvancementsCache.java | 4 +- .../geyser/session/cache/BookEditCache.java | 2 +- .../geyser/session/cache/ChunkCache.java | 2 +- .../session/cache/EntityEffectCache.java | 2 +- .../geyser/session/cache/LodestoneCache.java | 8 +-- .../geyser/session/cache/RegistryCache.java | 4 +- .../geyser/session/cache/TagCache.java | 2 +- .../geyser/session/cache/TeleportCache.java | 2 +- .../geyser/session/cache/WorldCache.java | 2 +- .../geyser/skin/FakeHeadProvider.java | 4 +- .../geysermc/geyser/text/ChatTypeEntry.java | 4 +- .../geysermc/geyser/text/MinecraftLocale.java | 4 +- .../geysermc/geyser/text/TextDecoration.java | 2 +- .../translator/collision/BlockCollision.java | 4 +- .../entity/EntityMetadataTranslator.java | 4 +- .../inventory/AnvilInventoryTranslator.java | 2 +- .../inventory/BaseInventoryTranslator.java | 8 +-- .../inventory/BeaconInventoryTranslator.java | 4 +- .../CartographyInventoryTranslator.java | 2 +- .../inventory/CrafterInventoryTranslator.java | 8 +-- .../EnchantingInventoryTranslator.java | 4 +- .../Generic3X3InventoryTranslator.java | 2 +- .../inventory/InventoryTranslator.java | 10 ++-- .../inventory/LecternInventoryTranslator.java | 18 +++--- .../inventory/LoomInventoryTranslator.java | 8 +-- .../MerchantInventoryTranslator.java | 4 +- .../inventory/OldSmithingTableTranslator.java | 6 +- .../inventory/PlayerInventoryTranslator.java | 15 ++--- .../inventory/ShulkerInventoryTranslator.java | 2 +- .../StonecutterInventoryTranslator.java | 6 +- .../translator/item/CustomItemTranslator.java | 4 +- .../translator/item/ItemTranslator.java | 14 ++--- .../translator/level/BiomeTranslator.java | 12 ++-- .../entity/BannerBlockEntityTranslator.java | 2 +- .../entity/BeaconBlockEntityTranslator.java | 2 +- .../entity/BedBlockEntityTranslator.java | 2 +- .../level/block/entity/BlockEntity.java | 2 +- .../block/entity/BlockEntityTranslator.java | 2 +- .../BrushableBlockEntityTranslator.java | 2 +- .../entity/CampfireBlockEntityTranslator.java | 2 +- .../CommandBlockBlockEntityTranslator.java | 2 +- .../DecoratedPotBlockEntityTranslator.java | 2 +- .../DoubleChestBlockEntityTranslator.java | 2 +- .../EndGatewayBlockEntityTranslator.java | 6 +- .../HangingSignBlockEntityTranslator.java | 2 +- .../JigsawBlockBlockEntityTranslator.java | 2 +- .../level/block/entity/PistonBlockEntity.java | 2 +- .../ShulkerBoxBlockEntityTranslator.java | 2 +- .../entity/SignBlockEntityTranslator.java | 2 +- .../entity/SkullBlockEntityTranslator.java | 2 +- .../entity/SpawnerBlockEntityTranslator.java | 2 +- .../StructureBlockBlockEntityTranslator.java | 2 +- .../TrialSpawnerBlockEntityTranslator.java | 2 +- .../level/event/LevelEventTranslator.java | 2 +- .../level/event/PlaySoundEventTranslator.java | 2 +- .../event/SoundEventEventTranslator.java | 2 +- .../event/SoundLevelEventTranslator.java | 2 +- .../bedrock/BedrockAnimateTranslator.java | 6 +- .../BedrockBlockEntityDataTranslator.java | 4 +- .../BedrockBlockPickRequestTranslator.java | 2 +- .../bedrock/BedrockBookEditTranslator.java | 12 ++-- .../BedrockCommandBlockUpdateTranslator.java | 6 +- .../BedrockContainerCloseTranslator.java | 2 +- ...BedrockInventoryTransactionTranslator.java | 22 +++---- .../BedrockItemFrameDropItemTranslator.java | 6 +- .../BedrockLecternUpdateTranslator.java | 10 ++-- .../BedrockMobEquipmentTranslator.java | 6 +- .../BedrockMoveEntityAbsoluteTranslator.java | 2 +- .../BedrockNetworkStackLatencyTranslator.java | 2 +- .../bedrock/BedrockPlayerInputTranslator.java | 4 +- .../BedrockRequestAbilityTranslator.java | 4 +- .../bedrock/BedrockRespawnTranslator.java | 4 +- .../bedrock/BedrockShowCreditsTranslator.java | 4 +- ...BedrockStructureBlockUpdateTranslator.java | 4 +- ...tructureTemplateDataRequestTranslator.java | 4 +- ...ockToggleCrafterSlotRequestTranslator.java | 2 +- .../entity/BedrockEntityEventTranslator.java | 2 +- .../player/BedrockActionTranslator.java | 10 +--- .../player/BedrockInteractTranslator.java | 12 ++-- .../player/BedrockMovePlayerTranslator.java | 8 +-- .../player/BedrockRiderJumpTranslator.java | 4 +- .../BedrockSetDefaultGameTypeTranslator.java | 2 +- .../BedrockSetDifficultyTranslator.java | 2 +- .../BedrockSetPlayerGameTypeTranslator.java | 2 +- ...ckSetPlayerInventoryOptionsTranslator.java | 6 +- .../BedrockLevelSoundEventTranslator.java | 8 +-- .../java/JavaAwardStatsTranslator.java | 2 +- .../java/JavaBossEventTranslator.java | 2 +- .../java/JavaChangeDifficultyTranslator.java | 2 +- .../JavaClientboundRecipesTranslator.java | 2 +- ...JavaClientboundResourcePackPushPacket.java | 6 +- .../protocol/java/JavaCommandsTranslator.java | 10 ++-- .../java/JavaCustomPayloadTranslator.java | 8 +-- .../java/JavaCustomQueryTranslator.java | 4 +- .../java/JavaDisconnectTranslator.java | 2 +- .../java/JavaDisguisedChatTranslator.java | 2 +- .../java/JavaGameProfileTranslator.java | 4 +- .../java/JavaKeepAliveTranslator.java | 2 +- .../java/JavaLoginDisconnectTranslator.java | 2 +- .../protocol/java/JavaLoginTranslator.java | 6 +- .../protocol/java/JavaPingTranslator.java | 4 +- .../java/JavaPlayerChatTranslator.java | 2 +- .../java/JavaRegistryDataTranslator.java | 2 +- .../protocol/java/JavaRespawnTranslator.java | 4 +- .../JavaSelectAdvancementsTabTranslator.java | 2 +- .../java/JavaSystemChatTranslator.java | 2 +- .../JavaUpdateAdvancementsTranslator.java | 4 +- .../java/JavaUpdateRecipesTranslator.java | 24 ++++---- .../java/JavaUpdateTagsTranslator.java | 2 +- .../java/entity/JavaAnimateTranslator.java | 4 +- .../entity/JavaDamageEventTranslator.java | 2 +- .../entity/JavaEntityEventTranslator.java | 2 +- .../JavaMoveEntityPosRotTranslator.java | 2 +- .../entity/JavaMoveEntityPosTranslator.java | 2 +- .../entity/JavaMoveEntityRotTranslator.java | 2 +- .../entity/JavaMoveVehicleTranslator.java | 2 +- .../entity/JavaRemoveEntitiesTranslator.java | 2 +- .../entity/JavaRemoveMobEffectTranslator.java | 2 +- .../java/entity/JavaRotateHeadTranslator.java | 2 +- .../entity/JavaSetEntityDataTranslator.java | 4 +- .../entity/JavaSetEntityLinkTranslator.java | 2 +- .../entity/JavaSetEntityMotionTranslator.java | 2 +- .../entity/JavaSetEquipmentTranslator.java | 6 +- .../entity/JavaSetPassengersTranslator.java | 2 +- .../entity/JavaSoundEntityTranslator.java | 2 +- .../entity/JavaTakeItemEntityTranslator.java | 2 +- .../entity/JavaTeleportEntityTranslator.java | 2 +- .../JavaUpdateAttributesTranslator.java | 2 +- .../entity/JavaUpdateMobEffectTranslator.java | 2 +- .../player/JavaBlockChangedAckTranslator.java | 2 +- .../player/JavaPlayerAbilitiesTranslator.java | 2 +- .../JavaPlayerCombatKillTranslator.java | 2 +- .../JavaPlayerInfoRemoveTranslator.java | 2 +- .../JavaPlayerInfoUpdateTranslator.java | 6 +- .../player/JavaPlayerLookAtTranslator.java | 2 +- .../player/JavaPlayerPositionTranslator.java | 8 +-- .../player/JavaSetCarriedItemTranslator.java | 2 +- .../player/JavaSetExperienceTranslator.java | 2 +- .../player/JavaSetHealthTranslator.java | 2 +- .../entity/spawn/JavaAddEntityTranslator.java | 14 ++--- .../spawn/JavaAddExperienceOrbTranslator.java | 2 +- .../JavaContainerCloseTranslator.java | 2 +- .../JavaContainerSetContentTranslator.java | 2 +- .../JavaContainerSetDataTranslator.java | 2 +- .../JavaContainerSetSlotTranslator.java | 6 +- .../JavaHorseScreenOpenTranslator.java | 2 +- .../JavaMerchantOffersTranslator.java | 6 +- .../inventory/JavaOpenBookTranslator.java | 6 +- .../inventory/JavaOpenScreenTranslator.java | 6 +- .../level/JavaBlockDestructionTranslator.java | 2 +- .../level/JavaBlockEntityDataTranslator.java | 6 +- .../java/level/JavaBlockEventTranslator.java | 4 +- .../java/level/JavaBlockUpdateTranslator.java | 2 +- .../JavaChunkBatchFinishedTranslator.java | 4 +- .../java/level/JavaCooldownTranslator.java | 2 +- .../java/level/JavaExplodeTranslator.java | 2 +- .../level/JavaForgetLevelChunkTranslator.java | 2 +- .../java/level/JavaGameEventTranslator.java | 16 ++--- .../JavaLevelChunkWithLightTranslator.java | 29 ++++------ .../java/level/JavaLevelEventTranslator.java | 6 +- .../level/JavaLevelParticlesTranslator.java | 18 +++--- .../java/level/JavaMapItemDataTranslator.java | 6 +- .../level/JavaOpenSignEditorTranslator.java | 2 +- .../JavaSectionBlocksUpdateTranslator.java | 4 +- .../JavaSetChunkCacheCenterTranslator.java | 2 +- .../JavaSetChunkCacheRadiusTranslator.java | 2 +- ...JavaSetDefaultSpawnPositionTranslator.java | 2 +- .../java/level/JavaSetTimeTranslator.java | 2 +- .../java/level/JavaSoundTranslator.java | 2 +- .../java/level/JavaStopSoundTranslator.java | 2 +- .../JavaInitializeBorderTranslator.java | 2 +- .../border/JavaSetBorderCenterTranslator.java | 2 +- .../JavaSetBorderLerpSizeTranslator.java | 2 +- .../border/JavaSetBorderSizeTranslator.java | 2 +- .../JavaSetBorderWarningDelayTranslator.java | 2 +- ...avaSetBorderWarningDistanceTranslator.java | 2 +- .../java/scoreboard/JavaResetScorePacket.java | 4 +- .../JavaSetDisplayObjectiveTranslator.java | 2 +- .../JavaSetObjectiveTranslator.java | 6 +- .../JavaSetPlayerTeamTranslator.java | 8 +-- .../scoreboard/JavaSetScoreTranslator.java | 4 +- .../java/title/JavaClearTitlesTranslator.java | 2 +- .../title/JavaSetActionBarTextTranslator.java | 2 +- .../title/JavaSetSubtitleTextTranslator.java | 2 +- .../title/JavaSetTitleTextTranslator.java | 2 +- .../JavaSetTitlesAnimationTranslator.java | 2 +- .../BlockSoundInteractionTranslator.java | 2 +- .../translator/text/MessageTranslator.java | 4 +- .../geysermc/geyser/util/AttributeUtils.java | 6 +- .../geyser/util/BlockEntityUtils.java | 2 +- .../org/geysermc/geyser/util/BlockUtils.java | 4 +- .../geysermc/geyser/util/CooldownUtils.java | 2 +- .../geysermc/geyser/util/DimensionUtils.java | 8 +-- .../org/geysermc/geyser/util/EntityUtils.java | 8 +-- .../geysermc/geyser/util/InventoryUtils.java | 12 ++-- .../org/geysermc/geyser/util/ItemUtils.java | 6 +- .../geyser/util/PluginMessageUtils.java | 2 +- .../org/geysermc/geyser/util/SoundUtils.java | 2 +- .../geyser/util/StatisticFormatters.java | 2 +- .../geysermc/geyser/util/StatisticsUtils.java | 2 +- .../geyser/util/StructureBlockUtils.java | 24 ++++---- .../chat/MessageTranslatorTest.java | 2 +- .../loader/ResourcePackLoaderTest.java | 4 +- gradle/libs.versions.toml | 2 +- 389 files changed, 869 insertions(+), 956 deletions(-) diff --git a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/world/GeyserModWorldManager.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/world/GeyserModWorldManager.java index b9fbd6cdc..656305690 100644 --- a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/world/GeyserModWorldManager.java +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/world/GeyserModWorldManager.java @@ -25,11 +25,11 @@ package org.geysermc.geyser.platform.mod.world; -import com.github.steveice10.mc.protocol.data.game.Holder; -import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; -import com.github.steveice10.mc.protocol.data.game.item.component.BannerPatternLayer; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityInfo; +import org.geysermc.mcprotocollib.protocol.data.game.Holder; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.BannerPatternLayer; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityInfo; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import net.minecraft.SharedConstants; @@ -222,8 +222,8 @@ public class GeyserModWorldManager extends GeyserWorldManager { @NonNull @Override - public CompletableFuture getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addNbtData) { - CompletableFuture future = new CompletableFuture<>(); + public CompletableFuture getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addNbtData) { + CompletableFuture future = new CompletableFuture<>(); server.execute(() -> { ServerPlayer player = getPlayer(session); if (player == null) { @@ -240,8 +240,8 @@ public class GeyserModWorldManager extends GeyserWorldManager { // the banner might have a custom name, both of which a Java client knows and caches ItemStack itemStack = banner.getItem(); - com.github.steveice10.mc.protocol.data.game.item.component.DataComponents components = - new com.github.steveice10.mc.protocol.data.game.item.component.DataComponents(new HashMap<>()); + org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents components = + new org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents(new HashMap<>()); components.put(DataComponentType.DAMAGE, itemStack.getDamageValue()); diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java index ad31131bd..43ecf7154 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.platform.spigot; -import com.github.steveice10.mc.protocol.MinecraftProtocol; +import org.geysermc.mcprotocollib.protocol.MinecraftProtocol; import com.viaversion.viaversion.bukkit.handlers.BukkitChannelInitializer; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.*; diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/PaperAdventure.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/PaperAdventure.java index 9e0b14b11..fa7555ac6 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/PaperAdventure.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/PaperAdventure.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.platform.spigot; -import com.github.steveice10.mc.protocol.data.DefaultComponentSerializer; +import org.geysermc.mcprotocollib.protocol.data.DefaultComponentSerializer; import net.kyori.adventure.text.Component; import org.bukkit.command.CommandSender; import org.checkerframework.checker.nullness.qual.Nullable; diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserPistonListener.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserPistonListener.java index 01b0be9f2..61c0d5fe8 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserPistonListener.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserPistonListener.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.platform.spigot.world; -import com.github.steveice10.mc.protocol.data.game.level.block.value.PistonValueType; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.PistonValueType; import org.cloudburstmc.math.vector.Vector3i; import it.unimi.dsi.fastutil.objects.Object2IntArrayMap; import it.unimi.dsi.fastutil.objects.Object2IntMap; diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java index 07a9d489a..8a0e0b70d 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java @@ -25,9 +25,9 @@ package org.geysermc.geyser.platform.spigot.world.manager; -import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityInfo; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityInfo; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.World; diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index 8b54f5298..5c4313f09 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -29,7 +29,6 @@ import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; -import com.github.steveice10.packetlib.tcp.TcpSession; import io.netty.channel.epoll.Epoll; import io.netty.util.NettyRuntime; import io.netty.util.concurrent.DefaultThreadFactory; @@ -86,6 +85,7 @@ import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.util.*; +import org.geysermc.mcprotocollib.network.tcp.TcpSession; import java.io.File; import java.io.FileWriter; diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/StatisticsCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/StatisticsCommand.java index 1ff12dea3..5952ea00d 100644 --- a/core/src/main/java/org/geysermc/geyser/command/defaults/StatisticsCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/StatisticsCommand.java @@ -25,12 +25,12 @@ package org.geysermc.geyser.command.defaults; -import com.github.steveice10.mc.protocol.data.game.ClientCommand; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundClientCommandPacket; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.command.GeyserCommand; import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.ClientCommand; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundClientCommandPacket; public class StatisticsCommand extends GeyserCommand { diff --git a/core/src/main/java/org/geysermc/geyser/dump/BootstrapDumpInfo.java b/core/src/main/java/org/geysermc/geyser/dump/BootstrapDumpInfo.java index 6a56c536a..7851fadfd 100644 --- a/core/src/main/java/org/geysermc/geyser/dump/BootstrapDumpInfo.java +++ b/core/src/main/java/org/geysermc/geyser/dump/BootstrapDumpInfo.java @@ -27,8 +27,8 @@ package org.geysermc.geyser.dump; import lombok.AllArgsConstructor; import lombok.Getter; -import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.text.AsteriskSerializer; import java.util.List; 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 e54bbc1eb..6989dc10a 100644 --- a/core/src/main/java/org/geysermc/geyser/dump/DumpInfo.java +++ b/core/src/main/java/org/geysermc/geyser/dump/DumpInfo.java @@ -56,12 +56,7 @@ import java.net.InetSocketAddress; import java.net.Socket; import java.net.UnknownHostException; import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Properties; +import java.util.*; import java.util.stream.Collectors; @Getter diff --git a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinition.java b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinition.java index 8b430d559..f0e221bad 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinition.java +++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinition.java @@ -25,9 +25,9 @@ package org.geysermc.geyser.entity; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.MetadataType; -import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.MetadataType; +import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import lombok.Setter; import lombok.experimental.Accessors; diff --git a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java index f454bef88..328dd4bbf 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java +++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java @@ -25,10 +25,10 @@ package org.geysermc.geyser.entity; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.MetadataType; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.FloatEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.MetadataType; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.FloatEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.type.*; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/AbstractArrowEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/AbstractArrowEntity.java index 6828d1020..1cc746d7a 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/AbstractArrowEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/AbstractArrowEntity.java @@ -25,8 +25,8 @@ package org.geysermc.geyser.entity.type; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/AreaEffectCloudEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/AreaEffectCloudEntity.java index 84dfae468..4b8eea061 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/AreaEffectCloudEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/AreaEffectCloudEntity.java @@ -25,9 +25,6 @@ package org.geysermc.geyser.entity.type; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.FloatEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.level.particle.Particle; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.ParticleType; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; @@ -35,6 +32,9 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.FloatEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.level.particle.Particle; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/BoatEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/BoatEntity.java index e3420abeb..d9a64ccc6 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/BoatEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/BoatEntity.java @@ -25,22 +25,21 @@ package org.geysermc.geyser.entity.type; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; +import lombok.Getter; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.packet.AnimatePacket; import org.cloudburstmc.protocol.bedrock.packet.MoveEntityAbsolutePacket; -import lombok.Getter; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; -import java.util.concurrent.TimeUnit; public class BoatEntity extends Entity implements Tickable { diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/ChestBoatEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ChestBoatEntity.java index 675e9517d..479b4d80d 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/ChestBoatEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/ChestBoatEntity.java @@ -25,12 +25,12 @@ package org.geysermc.geyser.entity.type; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import org.cloudburstmc.math.vector.Vector3f; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/CommandBlockMinecartEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/CommandBlockMinecartEntity.java index 9c7a28f6e..2d0835286 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/CommandBlockMinecartEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/CommandBlockMinecartEntity.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.entity.type; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/DefaultBlockMinecartEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/DefaultBlockMinecartEntity.java index 63b5ff2ab..fd6f17eb8 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/DefaultBlockMinecartEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/DefaultBlockMinecartEntity.java @@ -25,8 +25,8 @@ package org.geysermc.geyser.entity.type; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.geysermc.geyser.entity.EntityDefinition; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/EnderCrystalEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/EnderCrystalEntity.java index 86436f82b..932864bf7 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/EnderCrystalEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/EnderCrystalEntity.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.entity.type; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java b/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java index 306c244b3..f1d6bfb98 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java @@ -25,13 +25,6 @@ package org.geysermc.geyser.entity.type; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; -import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType; import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; @@ -42,12 +35,7 @@ import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; -import org.cloudburstmc.protocol.bedrock.packet.AddEntityPacket; -import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket; -import org.cloudburstmc.protocol.bedrock.packet.MoveEntityAbsolutePacket; -import org.cloudburstmc.protocol.bedrock.packet.MoveEntityDeltaPacket; -import org.cloudburstmc.protocol.bedrock.packet.RemoveEntityPacket; -import org.cloudburstmc.protocol.bedrock.packet.SetEntityDataPacket; +import org.cloudburstmc.protocol.bedrock.packet.*; import org.geysermc.geyser.api.entity.type.GeyserEntity; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.GeyserDirtyMetadata; @@ -57,12 +45,15 @@ import org.geysermc.geyser.util.EntityUtils; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; import org.geysermc.geyser.util.MathUtils; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; +import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType; -import java.util.Collections; -import java.util.EnumSet; -import java.util.List; -import java.util.Optional; -import java.util.UUID; +import java.util.*; @Getter @Setter 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 e6d3a5783..4fcec7a63 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 @@ -25,12 +25,12 @@ package org.geysermc.geyser.entity.type; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/FireworkEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/FireworkEntity.java index 04317e6d6..f0739abb3 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/FireworkEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/FireworkEntity.java @@ -25,9 +25,6 @@ package org.geysermc.geyser.entity.type; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.packet.SetEntityMotionPacket; @@ -36,6 +33,9 @@ import org.geysermc.geyser.entity.type.player.PlayerEntity; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; import java.util.OptionalInt; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/FishingHookEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/FishingHookEntity.java index 0de11c382..f4c0cea36 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/FishingHookEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/FishingHookEntity.java @@ -25,11 +25,10 @@ package org.geysermc.geyser.entity.type; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; +import lombok.Getter; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.packet.PlaySoundPacket; -import lombok.Getter; import org.geysermc.erosion.util.BlockPositionIterator; import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.type.player.PlayerEntity; @@ -38,6 +37,7 @@ import org.geysermc.geyser.level.physics.BoundingBox; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.collision.BlockCollision; import org.geysermc.geyser.util.BlockUtils; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/FurnaceMinecartEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/FurnaceMinecartEntity.java index a7a117fff..ef584c4fd 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/FurnaceMinecartEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/FurnaceMinecartEntity.java @@ -25,8 +25,8 @@ package org.geysermc.geyser.entity.type; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.geysermc.geyser.entity.EntityDefinition; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/InteractionEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/InteractionEntity.java index 0917465d4..4e7a805b4 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/InteractionEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/InteractionEntity.java @@ -25,16 +25,16 @@ package org.geysermc.geyser.entity.type; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.FloatEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundSwingPacket; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.packet.AnimatePacket; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.FloatEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundSwingPacket; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/ItemEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ItemEntity.java index 226ad7df8..ead717b34 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/ItemEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/ItemEntity.java @@ -25,8 +25,6 @@ package org.geysermc.geyser.entity.type; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType; @@ -38,6 +36,8 @@ import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.ItemTranslator; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import java.util.UUID; import java.util.concurrent.CompletableFuture; 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 453125945..f38e727c0 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 @@ -25,12 +25,7 @@ package org.geysermc.geyser.entity.type; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.object.Direction; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; -import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType; +import lombok.Getter; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; @@ -39,12 +34,17 @@ import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket; import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket; -import lombok.Getter; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.ItemTranslator; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InventoryUtils; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; +import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/LeashKnotEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/LeashKnotEntity.java index 3f0d2ee68..af739297c 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/LeashKnotEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/LeashKnotEntity.java @@ -25,11 +25,11 @@ package org.geysermc.geyser.entity.type; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import org.cloudburstmc.math.vector.Vector3f; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java index b070bdfff..5823ba3b2 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java @@ -25,14 +25,6 @@ package org.geysermc.geyser.entity.type; -import com.github.steveice10.mc.protocol.data.game.entity.attribute.Attribute; -import com.github.steveice10.mc.protocol.data.game.entity.attribute.AttributeType; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.FloatEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import lombok.AccessLevel; @@ -57,6 +49,14 @@ import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.AttributeUtils; import org.geysermc.geyser.util.InteractionResult; +import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.Attribute; +import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.AttributeType; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.FloatEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.*; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/MinecartEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/MinecartEntity.java index ecf67052b..9096d8bd6 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/MinecartEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/MinecartEntity.java @@ -25,9 +25,6 @@ package org.geysermc.geyser.entity.type; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.geysermc.geyser.entity.EntityDefinition; @@ -35,6 +32,9 @@ import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/PaintingEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/PaintingEntity.java index 4e5fe9d59..f5145c11f 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/PaintingEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/PaintingEntity.java @@ -25,13 +25,13 @@ package org.geysermc.geyser.entity.type; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ObjectEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.object.Direction; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.packet.AddPaintingPacket; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.level.PaintingType; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ObjectEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction; import java.util.UUID; @@ -49,7 +49,7 @@ public class PaintingEntity extends Entity { // Wait until we get the metadata needed } - public void setPaintingType(ObjectEntityMetadata entityMetadata) { + public void setPaintingType(ObjectEntityMetadata entityMetadata) { PaintingType type = PaintingType.getByPaintingType(entityMetadata.getValue()); AddPaintingPacket addPaintingPacket = new AddPaintingPacket(); addPaintingPacket.setUniqueEntityId(geyserId); diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/TNTEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/TNTEntity.java index 98c2edd00..dca36cda0 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/TNTEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/TNTEntity.java @@ -25,13 +25,13 @@ package org.geysermc.geyser.entity.type; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.packet.SetEntityDataPacket; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/TextDisplayEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/TextDisplayEntity.java index 0b6160401..28f38f919 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/TextDisplayEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/TextDisplayEntity.java @@ -25,14 +25,14 @@ package org.geysermc.geyser.entity.type; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import net.kyori.adventure.text.Component; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.text.MessageTranslator; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import java.util.Optional; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/ThrowableEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ThrowableEntity.java index 47884e60a..25bbdbd3c 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/ThrowableEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/ThrowableEntity.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.entity.type; -import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.LevelEvent; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; @@ -34,6 +33,7 @@ import org.cloudburstmc.protocol.bedrock.packet.MoveEntityDeltaPacket; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/ThrowableItemEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ThrowableItemEntity.java index 3c080345e..55334010f 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/ThrowableItemEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/ThrowableItemEntity.java @@ -25,8 +25,8 @@ package org.geysermc.geyser.entity.type; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/ThrownPotionEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ThrownPotionEntity.java index 31428477a..bfe429f33 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/ThrownPotionEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/ThrownPotionEntity.java @@ -25,11 +25,6 @@ package org.geysermc.geyser.entity.type; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.mc.protocol.data.game.item.component.PotionContents; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; @@ -39,6 +34,11 @@ import org.geysermc.geyser.inventory.item.Potion; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.PotionContents; import java.util.EnumSet; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/TippedArrowEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/TippedArrowEntity.java index 856c4cc66..be4133028 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/TippedArrowEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/TippedArrowEntity.java @@ -25,12 +25,12 @@ package org.geysermc.geyser.entity.type; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.inventory.item.TippedArrowPotion; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/WitherSkullEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/WitherSkullEntity.java index 637ca4139..8427a8e10 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/WitherSkullEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/WitherSkullEntity.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.entity.type; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinitions; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/AbstractFishEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/AbstractFishEntity.java index 9cc3a006e..6ecfa4978 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/AbstractFishEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/AbstractFishEntity.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.entity.type.living; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; @@ -34,6 +33,7 @@ import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.EntityUtils; import org.geysermc.geyser.util.InteractionResult; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/AgeableEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/AgeableEntity.java index 6e2e7a407..5b1d682ce 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/AgeableEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/AgeableEntity.java @@ -25,12 +25,12 @@ package org.geysermc.geyser.entity.type.living; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/AllayEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/AllayEntity.java index 48d633e5d..01a42e527 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/AllayEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/AllayEntity.java @@ -25,8 +25,6 @@ package org.geysermc.geyser.entity.type.living; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; @@ -36,6 +34,8 @@ import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java index 9c56568c8..c64f2f218 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java @@ -25,10 +25,6 @@ package org.geysermc.geyser.entity.type.living; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import lombok.Getter; import net.kyori.adventure.text.Component; import org.cloudburstmc.math.vector.Vector3f; @@ -43,6 +39,10 @@ import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.MathUtils; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.Optional; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/BatEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/BatEntity.java index 644054e72..bdfc20c88 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/BatEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/BatEntity.java @@ -25,11 +25,11 @@ package org.geysermc.geyser.entity.type.living; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/DolphinEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/DolphinEntity.java index a43bb666f..6182a27f4 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/DolphinEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/DolphinEntity.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.entity.type.living; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.geysermc.geyser.entity.EntityDefinition; @@ -34,6 +33,7 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/IronGolemEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/IronGolemEntity.java index 7afa4b436..58a349cc9 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/IronGolemEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/IronGolemEntity.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.entity.type.living; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; @@ -35,6 +34,7 @@ import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/MobEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/MobEntity.java index 0ac81c957..95145ae60 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/MobEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/MobEntity.java @@ -25,8 +25,6 @@ package org.geysermc.geyser.entity.type.living; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import lombok.Getter; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; @@ -40,6 +38,8 @@ import org.geysermc.geyser.item.type.SpawnEggItem; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/SlimeEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/SlimeEntity.java index 1d2eb95bc..50095fe3f 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/SlimeEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/SlimeEntity.java @@ -25,11 +25,11 @@ package org.geysermc.geyser.entity.type.living; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/SnowGolemEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/SnowGolemEntity.java index 7f0699415..50aa7b90e 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/SnowGolemEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/SnowGolemEntity.java @@ -25,8 +25,6 @@ package org.geysermc.geyser.entity.type.living; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; @@ -36,6 +34,8 @@ import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/TadpoleEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/TadpoleEntity.java index 7094c431e..4fdaa1059 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/TadpoleEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/TadpoleEntity.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.entity.type.living; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.geysermc.geyser.entity.EntityDefinition; @@ -34,6 +33,7 @@ import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AnimalEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AnimalEntity.java index 7278709ce..bf23a5418 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AnimalEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AnimalEntity.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.entity.type.living.animal; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType; @@ -38,6 +37,7 @@ import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java index c4f95e546..37cd5f1e6 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java @@ -25,9 +25,6 @@ package org.geysermc.geyser.entity.type.living.animal; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; @@ -39,6 +36,9 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.util.EntityUtils; import org.geysermc.geyser.util.InteractionResult; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/BeeEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/BeeEntity.java index 7f1a88d7b..d6aa9615d 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/BeeEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/BeeEntity.java @@ -25,8 +25,6 @@ package org.geysermc.geyser.entity.type.living.animal; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType; @@ -36,6 +34,8 @@ import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.tags.ItemTag; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/CowEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/CowEntity.java index cdcf534a3..d542cb46f 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/CowEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/CowEntity.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.entity.type.living.animal; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; @@ -36,6 +35,7 @@ import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FoxEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FoxEntity.java index 200505f14..18e346b98 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FoxEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FoxEntity.java @@ -25,8 +25,6 @@ package org.geysermc.geyser.entity.type.living.animal; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; @@ -34,6 +32,8 @@ import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.tags.ItemTag; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FrogEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FrogEntity.java index 039ef5bf9..ed21a9609 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FrogEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FrogEntity.java @@ -25,9 +25,6 @@ package org.geysermc.geyser.entity.type.living.animal; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ObjectEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; @@ -36,6 +33,9 @@ import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ObjectEntityMetadata; import java.util.OptionalInt; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/GoatEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/GoatEntity.java index 9ed94f96f..7cbbd4433 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/GoatEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/GoatEntity.java @@ -25,9 +25,6 @@ package org.geysermc.geyser.entity.type.living.animal; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; @@ -38,6 +35,9 @@ import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/HoglinEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/HoglinEntity.java index 154c2f688..29d1839c7 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/HoglinEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/HoglinEntity.java @@ -25,13 +25,13 @@ package org.geysermc.geyser.entity.type.living.animal; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/MooshroomEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/MooshroomEntity.java index 8673eb18e..55c3c406f 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/MooshroomEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/MooshroomEntity.java @@ -25,8 +25,6 @@ package org.geysermc.geyser.entity.type.living.animal; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ObjectEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; @@ -37,6 +35,8 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ObjectEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/OcelotEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/OcelotEntity.java index c115ebcdc..8a3dd6c72 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/OcelotEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/OcelotEntity.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.entity.type.living.animal; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; @@ -36,6 +35,7 @@ import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PandaEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PandaEntity.java index d2ef36932..df72fdc63 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PandaEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PandaEntity.java @@ -25,9 +25,6 @@ package org.geysermc.geyser.entity.type.living.animal; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; @@ -42,6 +39,9 @@ import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PigEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PigEntity.java index 2bc02cd55..4dbf3064a 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PigEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PigEntity.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.entity.type.living.animal; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; @@ -37,6 +36,7 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.EntityUtils; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PufferFishEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PufferFishEntity.java index d0d119593..6f0063474 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PufferFishEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PufferFishEntity.java @@ -25,12 +25,12 @@ package org.geysermc.geyser.entity.type.living.animal; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.type.living.AbstractFishEntity; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/RabbitEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/RabbitEntity.java index 1efa87ec8..09db7257b 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/RabbitEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/RabbitEntity.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.entity.type.living.animal; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; @@ -33,6 +32,7 @@ import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SheepEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SheepEntity.java index 13059244a..e87186bf6 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SheepEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SheepEntity.java @@ -25,8 +25,6 @@ package org.geysermc.geyser.entity.type.living.animal; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; @@ -38,6 +36,8 @@ import org.geysermc.geyser.item.type.DyeItem; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SnifferEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SnifferEntity.java index 0e6fffbc0..35b2b4183 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SnifferEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SnifferEntity.java @@ -25,9 +25,6 @@ package org.geysermc.geyser.entity.type.living.animal; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.SnifferState; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ObjectEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.LevelEvent; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; @@ -40,6 +37,9 @@ import org.geysermc.geyser.entity.type.Tickable; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.tags.ItemTag; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.SnifferState; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ObjectEntityMetadata; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/StriderEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/StriderEntity.java index 39a55fa1e..dcdd40199 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/StriderEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/StriderEntity.java @@ -25,8 +25,6 @@ package org.geysermc.geyser.entity.type.living.animal; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; @@ -39,6 +37,8 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.EntityUtils; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/TropicalFishEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/TropicalFishEntity.java index b18e55a48..b6751bc3f 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/TropicalFishEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/TropicalFishEntity.java @@ -25,14 +25,14 @@ package org.geysermc.geyser.entity.type.living.animal; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; import com.google.common.collect.ImmutableList; +import it.unimi.dsi.fastutil.ints.IntList; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; -import it.unimi.dsi.fastutil.ints.IntList; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.type.living.AbstractFishEntity; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; import java.util.List; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/TurtleEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/TurtleEntity.java index 870ded193..1d0aec75f 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/TurtleEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/TurtleEntity.java @@ -25,13 +25,13 @@ package org.geysermc.geyser.entity.type.living.animal; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/AbstractHorseEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/AbstractHorseEntity.java index faa495487..76416c146 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/AbstractHorseEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/AbstractHorseEntity.java @@ -25,8 +25,6 @@ package org.geysermc.geyser.entity.type.living.animal.horse; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; @@ -44,6 +42,8 @@ import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.Set; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/CamelEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/CamelEntity.java index 8106b096d..00144617a 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/CamelEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/CamelEntity.java @@ -25,9 +25,6 @@ package org.geysermc.geyser.entity.type.living.animal.horse; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType; @@ -38,6 +35,9 @@ import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/HorseEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/HorseEntity.java index dfa6ef30a..b8a9a8f28 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/HorseEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/HorseEntity.java @@ -25,11 +25,11 @@ package org.geysermc.geyser.entity.type.living.animal.horse; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/LlamaEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/LlamaEntity.java index 29da2e0dc..346b6da9b 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/LlamaEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/LlamaEntity.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.entity.type.living.animal.horse; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; import lombok.Getter; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; @@ -34,6 +33,7 @@ import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.MathUtils; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/SkeletonHorseEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/SkeletonHorseEntity.java index 7080f9f75..d74913c31 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/SkeletonHorseEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/SkeletonHorseEntity.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.entity.type.living.animal.horse; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.geysermc.geyser.entity.EntityDefinition; @@ -33,6 +32,7 @@ import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/ZombieHorseEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/ZombieHorseEntity.java index 3275712fc..9e77daebc 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/ZombieHorseEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/ZombieHorseEntity.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.entity.type.living.animal.horse; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.geysermc.geyser.entity.EntityDefinition; @@ -33,6 +32,7 @@ import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/CatEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/CatEntity.java index 93cb92c7d..fc5978c2b 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/CatEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/CatEntity.java @@ -25,10 +25,6 @@ package org.geysermc.geyser.entity.type.living.animal.tameable; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; @@ -40,6 +36,10 @@ import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/ParrotEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/ParrotEntity.java index 4c4b6a222..18feec979 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/ParrotEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/ParrotEntity.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.entity.type.living.animal.tameable; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; @@ -36,6 +35,7 @@ import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.Set; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/TameableEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/TameableEntity.java index 5fc8c459d..4a1cd70e9 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/TameableEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/TameableEntity.java @@ -25,16 +25,16 @@ package org.geysermc.geyser.entity.type.living.animal.tameable; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; +import lombok.Getter; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; -import lombok.Getter; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.living.animal.AnimalEntity; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import java.util.Optional; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java index ff130aeff..29c3526fe 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java @@ -25,9 +25,6 @@ package org.geysermc.geyser.entity.type.living.animal.tameable; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; @@ -42,6 +39,9 @@ import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.Collections; import java.util.Locale; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/AbstractMerchantEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/AbstractMerchantEntity.java index c7b29130f..64e35e52e 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/AbstractMerchantEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/AbstractMerchantEntity.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.entity.type.living.merchant; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; @@ -37,6 +36,7 @@ import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/VillagerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/VillagerEntity.java index 9b0f50050..3c2160a2b 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/VillagerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/VillagerEntity.java @@ -25,8 +25,6 @@ package org.geysermc.geyser.entity.type.living.merchant; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.VillagerData; import lombok.Getter; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; @@ -38,6 +36,8 @@ import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.type.BlockMapping; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.VillagerData; import java.util.Optional; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/AbstractSkeletonEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/AbstractSkeletonEntity.java index 04b3bba1b..3fbdda245 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/AbstractSkeletonEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/AbstractSkeletonEntity.java @@ -25,11 +25,11 @@ package org.geysermc.geyser.entity.type.living.monster; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BasePiglinEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BasePiglinEntity.java index 5f2647b7a..09bd28cd0 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BasePiglinEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BasePiglinEntity.java @@ -25,11 +25,11 @@ package org.geysermc.geyser.entity.type.living.monster; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BlazeEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BlazeEntity.java index 43d78f468..5b26d7bd1 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BlazeEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BlazeEntity.java @@ -25,11 +25,11 @@ package org.geysermc.geyser.entity.type.living.monster; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/CreeperEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/CreeperEntity.java index f134c31b3..5f54d2942 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/CreeperEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/CreeperEntity.java @@ -25,9 +25,6 @@ package org.geysermc.geyser.entity.type.living.monster; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; @@ -38,6 +35,9 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/EnderDragonEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/EnderDragonEntity.java index 8c00d065a..0162d498e 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/EnderDragonEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/EnderDragonEntity.java @@ -25,23 +25,19 @@ package org.geysermc.geyser.entity.type.living.monster; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.FloatEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; import lombok.Data; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.ParticleType; import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; -import org.cloudburstmc.protocol.bedrock.packet.AddEntityPacket; -import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket; -import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket; -import org.cloudburstmc.protocol.bedrock.packet.PlaySoundPacket; -import org.cloudburstmc.protocol.bedrock.packet.SpawnParticleEffectPacket; +import org.cloudburstmc.protocol.bedrock.packet.*; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.type.Tickable; import org.geysermc.geyser.entity.type.living.MobEntity; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.DimensionUtils; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.FloatEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; import java.util.Optional; import java.util.Random; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/EndermanEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/EndermanEntity.java index 5b8e23f8b..586ba5cd9 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/EndermanEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/EndermanEntity.java @@ -25,8 +25,6 @@ package org.geysermc.geyser.entity.type.living.monster; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; @@ -35,6 +33,8 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEvent2Packet; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/GhastEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/GhastEntity.java index f7b9d17b8..984aab642 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/GhastEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/GhastEntity.java @@ -25,12 +25,12 @@ package org.geysermc.geyser.entity.type.living.monster; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.type.living.FlyingEntity; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/GuardianEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/GuardianEntity.java index 92e50d207..40793522e 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/GuardianEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/GuardianEntity.java @@ -25,12 +25,12 @@ package org.geysermc.geyser.entity.type.living.monster; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PhantomEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PhantomEntity.java index 915e34e79..cb4b7a8cf 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PhantomEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PhantomEntity.java @@ -25,12 +25,12 @@ package org.geysermc.geyser.entity.type.living.monster; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.type.living.FlyingEntity; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java index 696982a33..db2a3ecc3 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java @@ -25,8 +25,6 @@ package org.geysermc.geyser.entity.type.living.monster; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; @@ -38,6 +36,8 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ShulkerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ShulkerEntity.java index 27dd45f40..aecb4a915 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ShulkerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ShulkerEntity.java @@ -25,15 +25,15 @@ package org.geysermc.geyser.entity.type.living.monster; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.object.Direction; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.type.living.GolemEntity; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/SkeletonEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/SkeletonEntity.java index da11b2759..a6343e256 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/SkeletonEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/SkeletonEntity.java @@ -25,11 +25,11 @@ package org.geysermc.geyser.entity.type.living.monster; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/SpiderEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/SpiderEntity.java index 03e234911..4a4527cef 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/SpiderEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/SpiderEntity.java @@ -25,11 +25,11 @@ package org.geysermc.geyser.entity.type.living.monster; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/VexEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/VexEntity.java index 56a0975ae..840f5b3b4 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/VexEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/VexEntity.java @@ -25,11 +25,11 @@ package org.geysermc.geyser.entity.type.living.monster; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/WardenEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/WardenEntity.java index 7a0c5e040..2341b8c32 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/WardenEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/WardenEntity.java @@ -25,8 +25,6 @@ package org.geysermc.geyser.entity.type.living.monster; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; import org.cloudburstmc.math.GenericMath; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; @@ -36,6 +34,8 @@ import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.type.Tickable; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.MathUtils; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/WitherEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/WitherEntity.java index 3abb7f122..19c1a457b 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/WitherEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/WitherEntity.java @@ -25,13 +25,13 @@ package org.geysermc.geyser.entity.type.living.monster; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataType; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZoglinEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZoglinEntity.java index 6e40573ba..efbb7753c 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZoglinEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZoglinEntity.java @@ -25,12 +25,12 @@ package org.geysermc.geyser.entity.type.living.monster; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieEntity.java index af6a30a10..11354fbf8 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieEntity.java @@ -25,12 +25,12 @@ package org.geysermc.geyser.entity.type.living.monster; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieVillagerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieVillagerEntity.java index 32e45507a..6e03e4f98 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieVillagerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieVillagerEntity.java @@ -25,10 +25,6 @@ package org.geysermc.geyser.entity.type.living.monster; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.VillagerData; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; @@ -40,6 +36,10 @@ import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.VillagerData; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/SpellcasterIllagerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/SpellcasterIllagerEntity.java index f083437ae..8d4b3c44e 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/SpellcasterIllagerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/SpellcasterIllagerEntity.java @@ -25,13 +25,13 @@ package org.geysermc.geyser.entity.type.living.monster.raid; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/VindicatorEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/VindicatorEntity.java index ad99dda50..04a58addd 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/VindicatorEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/VindicatorEntity.java @@ -25,11 +25,11 @@ package org.geysermc.geyser.entity.type.living.monster.raid; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java index b957a0243..1ca387259 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java @@ -25,18 +25,6 @@ package org.geysermc.geyser.entity.type.player; -import com.github.steveice10.mc.protocol.codec.NbtComponentSerializer; -import com.github.steveice10.mc.protocol.data.game.chat.numbers.BlankFormat; -import com.github.steveice10.mc.protocol.data.game.chat.numbers.FixedFormat; -import com.github.steveice10.mc.protocol.data.game.chat.numbers.NumberFormat; -import com.github.steveice10.mc.protocol.data.game.chat.numbers.StyledFormat; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.FloatEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.scoreboard.ScoreboardPosition; -import com.github.steveice10.mc.protocol.data.game.scoreboard.TeamColor; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import lombok.Getter; @@ -47,18 +35,13 @@ import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.Ability; import org.cloudburstmc.protocol.bedrock.data.AbilityLayer; -import org.cloudburstmc.protocol.bedrock.data.AttributeData; import org.cloudburstmc.protocol.bedrock.data.GameType; import org.cloudburstmc.protocol.bedrock.data.PlayerPermission; import org.cloudburstmc.protocol.bedrock.data.command.CommandPermission; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.data.entity.EntityLinkData; -import org.cloudburstmc.protocol.bedrock.packet.AddPlayerPacket; -import org.cloudburstmc.protocol.bedrock.packet.MovePlayerPacket; -import org.cloudburstmc.protocol.bedrock.packet.SetEntityDataPacket; -import org.cloudburstmc.protocol.bedrock.packet.SetEntityLinkPacket; -import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket; +import org.cloudburstmc.protocol.bedrock.packet.*; import org.geysermc.geyser.api.entity.type.player.GeyserPlayerEntity; import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.attribute.GeyserAttributeType; @@ -73,6 +56,18 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.util.ChunkUtils; +import org.geysermc.mcprotocollib.protocol.codec.NbtComponentSerializer; +import org.geysermc.mcprotocollib.protocol.data.game.chat.numbers.BlankFormat; +import org.geysermc.mcprotocollib.protocol.data.game.chat.numbers.FixedFormat; +import org.geysermc.mcprotocollib.protocol.data.game.chat.numbers.NumberFormat; +import org.geysermc.mcprotocollib.protocol.data.game.chat.numbers.StyledFormat; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.FloatEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.ScoreboardPosition; +import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.TeamColor; import java.util.Collections; import java.util.List; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java index 89aa540d8..e10adb134 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java @@ -25,13 +25,6 @@ package org.geysermc.geyser.entity.type.player; -import com.github.steveice10.mc.protocol.data.game.entity.attribute.Attribute; -import com.github.steveice10.mc.protocol.data.game.entity.attribute.AttributeType; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.GlobalPos; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.FloatEntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import lombok.Getter; import org.checkerframework.checker.nullness.qual.Nullable; @@ -45,6 +38,13 @@ import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.AttributeUtils; import org.geysermc.geyser.util.DimensionUtils; +import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.Attribute; +import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.AttributeType; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.GlobalPos; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.FloatEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; import java.util.Collections; import java.util.List; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/SkullPlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/SkullPlayerEntity.java index 939e4721d..89f9c37d6 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/player/SkullPlayerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/SkullPlayerEntity.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.entity.type.player; +import lombok.Getter; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.GameType; @@ -33,7 +34,6 @@ import org.cloudburstmc.protocol.bedrock.data.command.CommandPermission; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.packet.AddPlayerPacket; -import lombok.Getter; import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.SkullCache; diff --git a/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java b/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java index 57147fc49..a62f9ec49 100644 --- a/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java +++ b/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java @@ -25,8 +25,8 @@ package org.geysermc.geyser.erosion; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.mc.protocol.data.game.level.block.value.PistonValueType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.PistonValueType; import io.netty.channel.Channel; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; diff --git a/core/src/main/java/org/geysermc/geyser/impl/camera/GeyserCameraData.java b/core/src/main/java/org/geysermc/geyser/impl/camera/GeyserCameraData.java index 28c881eba..2a93c89e3 100644 --- a/core/src/main/java/org/geysermc/geyser/impl/camera/GeyserCameraData.java +++ b/core/src/main/java/org/geysermc/geyser/impl/camera/GeyserCameraData.java @@ -38,19 +38,10 @@ import org.cloudburstmc.protocol.bedrock.data.camera.CameraSetInstruction; import org.cloudburstmc.protocol.bedrock.packet.CameraInstructionPacket; import org.cloudburstmc.protocol.bedrock.packet.CameraShakePacket; import org.cloudburstmc.protocol.bedrock.packet.PlayerFogPacket; -import org.geysermc.geyser.api.bedrock.camera.CameraEaseType; -import org.geysermc.geyser.api.bedrock.camera.CameraData; -import org.geysermc.geyser.api.bedrock.camera.CameraFade; -import org.geysermc.geyser.api.bedrock.camera.CameraPerspective; -import org.geysermc.geyser.api.bedrock.camera.CameraPosition; -import org.geysermc.geyser.api.bedrock.camera.CameraShake; +import org.geysermc.geyser.api.bedrock.camera.*; import org.geysermc.geyser.session.GeyserSession; -import java.util.Collections; -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; -import java.util.UUID; +import java.util.*; public class GeyserCameraData implements CameraData { diff --git a/core/src/main/java/org/geysermc/geyser/impl/camera/GeyserCameraFade.java b/core/src/main/java/org/geysermc/geyser/impl/camera/GeyserCameraFade.java index 648e70c81..f69504545 100644 --- a/core/src/main/java/org/geysermc/geyser/impl/camera/GeyserCameraFade.java +++ b/core/src/main/java/org/geysermc/geyser/impl/camera/GeyserCameraFade.java @@ -29,7 +29,7 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.common.value.qual.IntRange; import org.geysermc.geyser.api.bedrock.camera.CameraFade; -import java.awt.Color; +import java.awt.*; import java.util.Objects; public record GeyserCameraFade( diff --git a/core/src/main/java/org/geysermc/geyser/inventory/AnvilContainer.java b/core/src/main/java/org/geysermc/geyser/inventory/AnvilContainer.java index 1c5826cdb..e6332bc41 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/AnvilContainer.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/AnvilContainer.java @@ -25,8 +25,8 @@ package org.geysermc.geyser.inventory; -import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundRenameItemPacket; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundRenameItemPacket; import lombok.Getter; import lombok.Setter; import org.checkerframework.checker.nullness.qual.Nullable; diff --git a/core/src/main/java/org/geysermc/geyser/inventory/BeaconContainer.java b/core/src/main/java/org/geysermc/geyser/inventory/BeaconContainer.java index 7644ada73..1b59772fa 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/BeaconContainer.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/BeaconContainer.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.inventory; -import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; import lombok.Getter; import lombok.Setter; diff --git a/core/src/main/java/org/geysermc/geyser/inventory/CartographyContainer.java b/core/src/main/java/org/geysermc/geyser/inventory/CartographyContainer.java index 72f1088c3..ace3f93ad 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/CartographyContainer.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/CartographyContainer.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.inventory; -import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; public class CartographyContainer extends Container { public CartographyContainer(String title, int id, int size, ContainerType containerType, PlayerInventory playerInventory) { diff --git a/core/src/main/java/org/geysermc/geyser/inventory/Container.java b/core/src/main/java/org/geysermc/geyser/inventory/Container.java index 79fa67da1..209aeb24f 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/Container.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/Container.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.inventory; -import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; import lombok.Getter; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.session.GeyserSession; diff --git a/core/src/main/java/org/geysermc/geyser/inventory/CrafterContainer.java b/core/src/main/java/org/geysermc/geyser/inventory/CrafterContainer.java index bcacd3587..41452bed6 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/CrafterContainer.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/CrafterContainer.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.inventory; -import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; import lombok.Getter; import lombok.Setter; import org.geysermc.geyser.GeyserImpl; diff --git a/core/src/main/java/org/geysermc/geyser/inventory/EnchantingContainer.java b/core/src/main/java/org/geysermc/geyser/inventory/EnchantingContainer.java index ac55aae60..08397ab44 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/EnchantingContainer.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/EnchantingContainer.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.inventory; -import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; import org.cloudburstmc.protocol.bedrock.data.inventory.EnchantOptionData; import lombok.Getter; diff --git a/core/src/main/java/org/geysermc/geyser/inventory/Generic3X3Container.java b/core/src/main/java/org/geysermc/geyser/inventory/Generic3X3Container.java index 6518dce7c..65e47d877 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/Generic3X3Container.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/Generic3X3Container.java @@ -25,10 +25,10 @@ package org.geysermc.geyser.inventory; -import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; import lombok.Getter; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.inventory.Generic3X3InventoryTranslator; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; public class Generic3X3Container extends Container { /** diff --git a/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java b/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java index a1ecc6f58..f75c1fdd9 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java @@ -25,9 +25,6 @@ package org.geysermc.geyser.inventory; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import lombok.AccessLevel; import lombok.Data; @@ -42,6 +39,9 @@ import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.ItemTranslator; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; @Data public class GeyserItemStack { diff --git a/core/src/main/java/org/geysermc/geyser/inventory/Inventory.java b/core/src/main/java/org/geysermc/geyser/inventory/Inventory.java index b78bbe1b3..4e8257ff8 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/Inventory.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/Inventory.java @@ -25,20 +25,20 @@ package org.geysermc.geyser.inventory; -import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; import com.github.steveice10.opennbt.tag.builtin.ByteTag; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.Tag; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.cloudburstmc.math.vector.Vector3i; import lombok.Getter; import lombok.Setter; import lombok.ToString; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.ItemTranslator; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; import org.jetbrains.annotations.Range; import java.util.Arrays; diff --git a/core/src/main/java/org/geysermc/geyser/inventory/LecternContainer.java b/core/src/main/java/org/geysermc/geyser/inventory/LecternContainer.java index 7ac2fed99..389611c67 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/LecternContainer.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/LecternContainer.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.inventory; -import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; import lombok.Getter; import lombok.Setter; import org.checkerframework.checker.nullness.qual.NonNull; @@ -33,6 +32,7 @@ import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.java.inventory.JavaOpenBookTranslator; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; public class LecternContainer extends Container { @Getter @Setter diff --git a/core/src/main/java/org/geysermc/geyser/inventory/MerchantContainer.java b/core/src/main/java/org/geysermc/geyser/inventory/MerchantContainer.java index 105b5ca5b..0bfa6d1a7 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/MerchantContainer.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/MerchantContainer.java @@ -25,14 +25,14 @@ package org.geysermc.geyser.inventory; -import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; -import com.github.steveice10.mc.protocol.data.game.inventory.VillagerTrade; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.inventory.ClientboundMerchantOffersPacket; import lombok.Getter; import lombok.Setter; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.VillagerTrade; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.inventory.ClientboundMerchantOffersPacket; public class MerchantContainer extends Container { @Getter @Setter diff --git a/core/src/main/java/org/geysermc/geyser/inventory/PlayerInventory.java b/core/src/main/java/org/geysermc/geyser/inventory/PlayerInventory.java index bda09a4ed..9bef4b08e 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/PlayerInventory.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/PlayerInventory.java @@ -25,12 +25,12 @@ package org.geysermc.geyser.inventory; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import lombok.Getter; import lombok.Setter; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import org.jetbrains.annotations.Range; public class PlayerInventory extends Inventory { diff --git a/core/src/main/java/org/geysermc/geyser/inventory/StonecutterContainer.java b/core/src/main/java/org/geysermc/geyser/inventory/StonecutterContainer.java index f99a0c71e..269a4fb7d 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/StonecutterContainer.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/StonecutterContainer.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.inventory; -import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; import lombok.Getter; import lombok.Setter; import org.checkerframework.checker.nullness.qual.NonNull; diff --git a/core/src/main/java/org/geysermc/geyser/inventory/click/Click.java b/core/src/main/java/org/geysermc/geyser/inventory/click/Click.java index d7068920e..6897786c1 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/click/Click.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/click/Click.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.inventory.click; -import com.github.steveice10.mc.protocol.data.game.inventory.*; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.*; import lombok.AllArgsConstructor; @AllArgsConstructor diff --git a/core/src/main/java/org/geysermc/geyser/inventory/click/ClickPlan.java b/core/src/main/java/org/geysermc/geyser/inventory/click/ClickPlan.java index a118670af..53b02ef88 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/click/ClickPlan.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/click/ClickPlan.java @@ -25,11 +25,11 @@ package org.geysermc.geyser.inventory.click; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.inventory.ContainerActionType; -import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; -import com.github.steveice10.mc.protocol.data.game.inventory.MoveToHotbarAction; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClickPacket; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerActionType; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.MoveToHotbarAction; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClickPacket; import it.unimi.dsi.fastutil.ints.*; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.Inventory; diff --git a/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserRecipe.java b/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserRecipe.java index 641d5ad94..9d98e9fb3 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserRecipe.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserRecipe.java @@ -26,7 +26,7 @@ package org.geysermc.geyser.inventory.recipe; /** - * A more compact version of {@link com.github.steveice10.mc.protocol.data.game.recipe.Recipe}. + * A more compact version of {@link org.geysermc.mcprotocollib.protocol.data.game.recipe.Recipe}. */ public interface GeyserRecipe { /** diff --git a/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserShapedRecipe.java b/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserShapedRecipe.java index d420170f4..ac9fa3ab4 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserShapedRecipe.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserShapedRecipe.java @@ -25,10 +25,10 @@ package org.geysermc.geyser.inventory.recipe; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; -import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapedRecipeData; import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.recipe.Ingredient; +import org.geysermc.mcprotocollib.protocol.data.game.recipe.data.ShapedRecipeData; public record GeyserShapedRecipe(int width, int height, Ingredient[] ingredients, @Nullable ItemStack result) implements GeyserRecipe { diff --git a/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserShapelessRecipe.java b/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserShapelessRecipe.java index e6eabea2d..388831d4c 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserShapelessRecipe.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserShapelessRecipe.java @@ -25,9 +25,9 @@ package org.geysermc.geyser.inventory.recipe; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; -import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapelessRecipeData; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.recipe.Ingredient; +import org.geysermc.mcprotocollib.protocol.data.game.recipe.data.ShapelessRecipeData; import org.checkerframework.checker.nullness.qual.Nullable; public record GeyserShapelessRecipe(Ingredient[] ingredients, @Nullable ItemStack result) implements GeyserRecipe { diff --git a/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserStonecutterData.java b/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserStonecutterData.java index ce044e745..7bd21ecfa 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserStonecutterData.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserStonecutterData.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.inventory.recipe; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.checkerframework.checker.nullness.qual.Nullable; /** diff --git a/core/src/main/java/org/geysermc/geyser/inventory/recipe/TrimRecipe.java b/core/src/main/java/org/geysermc/geyser/inventory/recipe/TrimRecipe.java index 441f050a7..860ccfd89 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/recipe/TrimRecipe.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/recipe/TrimRecipe.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.inventory.recipe; -import com.github.steveice10.mc.protocol.data.game.RegistryEntry; +import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import net.kyori.adventure.text.Component; diff --git a/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java b/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java index 9bf001f42..d6324ba23 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java @@ -25,9 +25,9 @@ package org.geysermc.geyser.inventory.updater; -import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundRenameItemPacket; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundRenameItemPacket; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; diff --git a/core/src/main/java/org/geysermc/geyser/item/DyeableLeatherItem.java b/core/src/main/java/org/geysermc/geyser/item/DyeableLeatherItem.java index 214b9d78c..e884ecec5 100644 --- a/core/src/main/java/org/geysermc/geyser/item/DyeableLeatherItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/DyeableLeatherItem.java @@ -25,12 +25,12 @@ package org.geysermc.geyser.item; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.mc.protocol.data.game.item.component.DyedItemColor; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.IntTag; import org.geysermc.geyser.translator.item.BedrockItemBuilder; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DyedItemColor; public interface DyeableLeatherItem { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java index 773b850c0..fb9f35629 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java @@ -25,9 +25,6 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.ArmorTrim; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import org.checkerframework.checker.nullness.qual.NonNull; @@ -39,6 +36,9 @@ import org.geysermc.geyser.item.ArmorMaterial; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.ArmorTrim; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; public class ArmorItem extends Item { private final ArmorMaterial material; diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java index 16d5fd482..f3c832a31 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; import com.github.steveice10.opennbt.tag.builtin.StringTag; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; @@ -33,6 +32,7 @@ import org.geysermc.geyser.inventory.item.TippedArrowPotion; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; public class ArrowItem extends Item { public ArrowItem(String javaIdentifier, Builder builder) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/AxolotlBucketItem.java b/core/src/main/java/org/geysermc/geyser/item/type/AxolotlBucketItem.java index 99f649e87..8895d45a8 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/AxolotlBucketItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/AxolotlBucketItem.java @@ -25,11 +25,11 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.translator.item.BedrockItemBuilder; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; public class AxolotlBucketItem extends Item { public AxolotlBucketItem(String javaIdentifier, Builder builder) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java index fe378d4c6..29a98e598 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java @@ -25,9 +25,6 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.BannerPatternLayer; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.*; import it.unimi.dsi.fastutil.Pair; import org.checkerframework.checker.nullness.qual.NonNull; @@ -39,6 +36,9 @@ import org.geysermc.geyser.inventory.item.DyeColor; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.BannerPatternLayer; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; import java.util.ArrayList; import java.util.List; diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ChestItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ChestItem.java index 1f6ac6964..09718ba66 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ChestItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ChestItem.java @@ -25,10 +25,10 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; @Deprecated public class ChestItem extends BlockItem { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java b/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java index 10c574d5d..aa34f76ba 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java @@ -25,10 +25,6 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.mc.protocol.data.game.item.component.LodestoneTracker; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; @@ -36,6 +32,10 @@ import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.LodestoneTracker; public class CompassItem extends Item { public CompassItem(String javaIdentifier, Builder builder) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/CrossbowItem.java b/core/src/main/java/org/geysermc/geyser/item/type/CrossbowItem.java index 5b92ba303..9a10c701c 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/CrossbowItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/CrossbowItem.java @@ -25,9 +25,6 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.ByteTag; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; @@ -39,6 +36,9 @@ import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.geyser.translator.item.ItemTranslator; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; import java.util.List; diff --git a/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java b/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java index ea194522b..2631bf9be 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java @@ -25,13 +25,13 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtType; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; import java.util.ArrayList; import java.util.List; diff --git a/core/src/main/java/org/geysermc/geyser/item/type/DyeableArmorItem.java b/core/src/main/java/org/geysermc/geyser/item/type/DyeableArmorItem.java index 117e70b9a..e57470607 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/DyeableArmorItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/DyeableArmorItem.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.item.ArmorMaterial; @@ -33,6 +32,7 @@ import org.geysermc.geyser.item.DyeableLeatherItem; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; public class DyeableArmorItem extends ArmorItem implements DyeableLeatherItem { public DyeableArmorItem(String javaIdentifier, ArmorMaterial material, Builder builder) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/DyeableHorseArmorItem.java b/core/src/main/java/org/geysermc/geyser/item/type/DyeableHorseArmorItem.java index cb6dd869b..881598648 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/DyeableHorseArmorItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/DyeableHorseArmorItem.java @@ -25,13 +25,13 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.item.DyeableLeatherItem; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; public class DyeableHorseArmorItem extends Item implements DyeableLeatherItem { public DyeableHorseArmorItem(String javaIdentifier, Builder builder) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java b/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java index 095537a09..952967475 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java @@ -25,14 +25,14 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.mc.protocol.data.game.item.component.ItemEnchantments; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtType; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemEnchantments; import java.util.ArrayList; import java.util.List; diff --git a/core/src/main/java/org/geysermc/geyser/item/type/FilledMapItem.java b/core/src/main/java/org/geysermc/geyser/item/type/FilledMapItem.java index af0b84308..70a04b863 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/FilledMapItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/FilledMapItem.java @@ -25,11 +25,11 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; public class FilledMapItem extends MapItem { public FilledMapItem(String javaIdentifier, Builder builder) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java b/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java index afb848e2d..e5656b494 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java @@ -25,10 +25,9 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.mc.protocol.data.game.item.component.Fireworks; -import com.github.steveice10.opennbt.tag.builtin.*; +import com.github.steveice10.opennbt.tag.builtin.ByteTag; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.IntArrayTag; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; @@ -38,6 +37,9 @@ import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.geyser.util.MathUtils; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.Fireworks; import java.util.ArrayList; import java.util.List; diff --git a/core/src/main/java/org/geysermc/geyser/item/type/FireworkStarItem.java b/core/src/main/java/org/geysermc/geyser/item/type/FireworkStarItem.java index 505296418..ab6b7f300 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/FireworkStarItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/FireworkStarItem.java @@ -25,9 +25,6 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.mc.protocol.data.game.item.component.Fireworks; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import org.checkerframework.checker.nullness.qual.NonNull; @@ -35,6 +32,9 @@ import org.cloudburstmc.nbt.NbtMap; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.Fireworks; public class FireworkStarItem extends Item { public FireworkStarItem(String javaIdentifier, Builder builder) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/FishingRodItem.java b/core/src/main/java/org/geysermc/geyser/item/type/FishingRodItem.java index 743928482..32b1d5df5 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/FishingRodItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/FishingRodItem.java @@ -25,10 +25,10 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; public class FishingRodItem extends Item { public FishingRodItem(String javaIdentifier, Builder builder) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java b/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java index 35b7a76fc..0ff78676c 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java @@ -25,17 +25,17 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.Holder; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.mc.protocol.data.game.item.component.Instrument; import com.github.steveice10.opennbt.tag.builtin.StringTag; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; +import org.geysermc.mcprotocollib.protocol.data.game.Holder; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.Instrument; import java.util.List; diff --git a/core/src/main/java/org/geysermc/geyser/item/type/Item.java b/core/src/main/java/org/geysermc/geyser/item/type/Item.java index 2779768db..64e2dcbc6 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/Item.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/Item.java @@ -25,11 +25,6 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.Identifier; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.mc.protocol.data.game.item.component.ItemEnchantments; import com.github.steveice10.opennbt.tag.builtin.*; import net.kyori.adventure.text.Component; import org.checkerframework.checker.nullness.qual.NonNull; @@ -48,6 +43,11 @@ import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.geyser.translator.item.ItemTranslator; import org.geysermc.geyser.translator.text.MessageTranslator; +import org.geysermc.mcprotocollib.protocol.data.game.Identifier; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemEnchantments; import java.util.ArrayList; import java.util.List; diff --git a/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java b/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java index 72014e15e..f6492a169 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java @@ -25,13 +25,14 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.opennbt.tag.builtin.*; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.IntTag; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; public class MapItem extends Item { public MapItem(String javaIdentifier, Builder builder) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java b/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java index 82219d7d9..0cdbe70f1 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java @@ -26,13 +26,13 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.auth.data.GameProfile; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.translator.item.BedrockItemBuilder; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; public class PlayerHeadItem extends Item { public PlayerHeadItem(String javaIdentifier, Builder builder) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java b/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java index 63b9240c0..13d7ccd5e 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java @@ -25,10 +25,6 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.mc.protocol.data.game.item.component.PotionContents; import com.github.steveice10.opennbt.tag.builtin.StringTag; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; @@ -38,6 +34,10 @@ import org.geysermc.geyser.inventory.item.Potion; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.translator.item.CustomItemTranslator; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.PotionContents; public class PotionItem extends Item { public PotionItem(String javaIdentifier, Builder builder) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ShieldItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ShieldItem.java index f495222f3..001fa74b6 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ShieldItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ShieldItem.java @@ -25,11 +25,11 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.item.components.ToolTier; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; public class ShieldItem extends Item { public ShieldItem(String javaIdentifier, Builder builder) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java index 267946442..4108d0fa0 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java @@ -25,9 +25,6 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtMap; @@ -38,6 +35,9 @@ import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.geyser.translator.item.ItemTranslator; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; import java.util.ArrayList; import java.util.List; diff --git a/core/src/main/java/org/geysermc/geyser/item/type/TippedArrowItem.java b/core/src/main/java/org/geysermc/geyser/item/type/TippedArrowItem.java index 9074c2ec8..85291886e 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/TippedArrowItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/TippedArrowItem.java @@ -25,14 +25,14 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.mc.protocol.data.game.item.component.PotionContents; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.inventory.item.TippedArrowPotion; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.PotionContents; public class TippedArrowItem extends ArrowItem { public TippedArrowItem(String javaIdentifier, Builder builder) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/TropicalFishBucketItem.java b/core/src/main/java/org/geysermc/geyser/item/type/TropicalFishBucketItem.java index f70e6b295..8c00cb049 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/TropicalFishBucketItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/TropicalFishBucketItem.java @@ -25,8 +25,6 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import net.kyori.adventure.text.Component; @@ -39,6 +37,8 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.geyser.translator.text.MessageTranslator; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; import java.util.List; diff --git a/core/src/main/java/org/geysermc/geyser/item/type/WritableBookItem.java b/core/src/main/java/org/geysermc/geyser/item/type/WritableBookItem.java index d925d2b8a..097a5e65b 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/WritableBookItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/WritableBookItem.java @@ -25,10 +25,6 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.mc.protocol.data.game.item.component.Filterable; -import com.github.steveice10.mc.protocol.data.game.item.component.WritableBookContent; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; @@ -41,6 +37,10 @@ import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.geyser.translator.text.MessageTranslator; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.Filterable; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.WritableBookContent; import java.util.ArrayList; import java.util.List; diff --git a/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java b/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java index a6b5e73d4..a11c4f583 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java @@ -25,10 +25,6 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.mc.protocol.data.game.item.component.Filterable; -import com.github.steveice10.mc.protocol.data.game.item.component.WrittenBookContent; import net.kyori.adventure.text.Component; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtMap; @@ -37,6 +33,10 @@ import org.cloudburstmc.nbt.NbtType; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.geyser.translator.text.MessageTranslator; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.Filterable; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.WrittenBookContent; import java.util.ArrayList; import java.util.List; diff --git a/core/src/main/java/org/geysermc/geyser/level/BedrockMapIcon.java b/core/src/main/java/org/geysermc/geyser/level/BedrockMapIcon.java index 120e40f17..c55a74cd2 100644 --- a/core/src/main/java/org/geysermc/geyser/level/BedrockMapIcon.java +++ b/core/src/main/java/org/geysermc/geyser/level/BedrockMapIcon.java @@ -25,9 +25,9 @@ package org.geysermc.geyser.level; -import com.github.steveice10.mc.protocol.data.game.level.map.MapIconType; import lombok.Getter; import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.mcprotocollib.protocol.data.game.level.map.MapIconType; public enum BedrockMapIcon { ICON_WHITE_ARROW(MapIconType.WHITE_ARROW, 0), diff --git a/core/src/main/java/org/geysermc/geyser/level/GeyserAdvancement.java b/core/src/main/java/org/geysermc/geyser/level/GeyserAdvancement.java index f51e7b2ab..7d48b90af 100644 --- a/core/src/main/java/org/geysermc/geyser/level/GeyserAdvancement.java +++ b/core/src/main/java/org/geysermc/geyser/level/GeyserAdvancement.java @@ -25,12 +25,12 @@ package org.geysermc.geyser.level; -import com.github.steveice10.mc.protocol.data.game.advancement.Advancement; -import com.github.steveice10.mc.protocol.data.game.advancement.Advancement.DisplayData; -import com.github.steveice10.mc.protocol.data.game.advancement.Advancement.DisplayData.AdvancementType; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.session.cache.AdvancementsCache; import org.geysermc.geyser.text.ChatColor; +import org.geysermc.mcprotocollib.protocol.data.game.advancement.Advancement; +import org.geysermc.mcprotocollib.protocol.data.game.advancement.Advancement.DisplayData; +import org.geysermc.mcprotocollib.protocol.data.game.advancement.Advancement.DisplayData.AdvancementType; import java.util.List; diff --git a/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java b/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java index 9a9eac2df..08611a5e1 100644 --- a/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java +++ b/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java @@ -25,9 +25,6 @@ package org.geysermc.geyser.level; -import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityInfo; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; @@ -36,15 +33,14 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; -import org.geysermc.erosion.packet.backendbound.BackendboundBatchBlockEntityPacket; -import org.geysermc.erosion.packet.backendbound.BackendboundBatchBlockRequestPacket; -import org.geysermc.erosion.packet.backendbound.BackendboundBlockEntityPacket; -import org.geysermc.erosion.packet.backendbound.BackendboundBlockRequestPacket; -import org.geysermc.erosion.packet.backendbound.BackendboundPickBlockPacket; +import org.geysermc.erosion.packet.backendbound.*; import org.geysermc.erosion.util.BlockPositionIterator; import org.geysermc.erosion.util.LecternUtils; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.BlockEntityUtils; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityInfo; import java.util.List; import java.util.concurrent.CompletableFuture; diff --git a/core/src/main/java/org/geysermc/geyser/level/JavaDimension.java b/core/src/main/java/org/geysermc/geyser/level/JavaDimension.java index 4babc3af0..27b2430bd 100644 --- a/core/src/main/java/org/geysermc/geyser/level/JavaDimension.java +++ b/core/src/main/java/org/geysermc/geyser/level/JavaDimension.java @@ -25,10 +25,10 @@ package org.geysermc.geyser.level; -import com.github.steveice10.mc.protocol.data.game.RegistryEntry; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.IntTag; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry; import java.util.List; diff --git a/core/src/main/java/org/geysermc/geyser/level/PaintingType.java b/core/src/main/java/org/geysermc/geyser/level/PaintingType.java index 5c0cbf643..643fd735d 100644 --- a/core/src/main/java/org/geysermc/geyser/level/PaintingType.java +++ b/core/src/main/java/org/geysermc/geyser/level/PaintingType.java @@ -75,7 +75,7 @@ public enum PaintingType { return KEBAB; } - public static PaintingType getByPaintingType(com.github.steveice10.mc.protocol.data.game.entity.type.PaintingType paintingType) { + public static PaintingType getByPaintingType(org.geysermc.mcprotocollib.protocol.data.game.entity.type.PaintingType paintingType) { return getByName(paintingType.name()); } } diff --git a/core/src/main/java/org/geysermc/geyser/level/WorldManager.java b/core/src/main/java/org/geysermc/geyser/level/WorldManager.java index aa0b43b80..a1b16a1d5 100644 --- a/core/src/main/java/org/geysermc/geyser/level/WorldManager.java +++ b/core/src/main/java/org/geysermc/geyser/level/WorldManager.java @@ -25,15 +25,15 @@ package org.geysermc.geyser.level; -import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityInfo; -import com.github.steveice10.mc.protocol.data.game.setting.Difficulty; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3i; import org.geysermc.erosion.util.BlockPositionIterator; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityInfo; +import org.geysermc.mcprotocollib.protocol.data.game.setting.Difficulty; import java.util.List; import java.util.Locale; diff --git a/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockComponents.java b/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockComponents.java index dfcb548ee..979d3bc7d 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockComponents.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockComponents.java @@ -32,18 +32,9 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import lombok.Value; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; -import org.geysermc.geyser.api.block.custom.component.BoxComponent; -import org.geysermc.geyser.api.block.custom.component.CustomBlockComponents; -import org.geysermc.geyser.api.block.custom.component.GeometryComponent; -import org.geysermc.geyser.api.block.custom.component.MaterialInstance; -import org.geysermc.geyser.api.block.custom.component.PlacementConditions; -import org.geysermc.geyser.api.block.custom.component.TransformationComponent; +import org.geysermc.geyser.api.block.custom.component.*; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.Objects; +import java.util.*; @Value public class GeyserCustomBlockComponents implements CustomBlockComponents { diff --git a/core/src/main/java/org/geysermc/geyser/level/chunk/GeyserChunk.java b/core/src/main/java/org/geysermc/geyser/level/chunk/GeyserChunk.java index ca8c4db1d..c76c1994b 100644 --- a/core/src/main/java/org/geysermc/geyser/level/chunk/GeyserChunk.java +++ b/core/src/main/java/org/geysermc/geyser/level/chunk/GeyserChunk.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.level.chunk; -import com.github.steveice10.mc.protocol.data.game.chunk.DataPalette; +import org.geysermc.mcprotocollib.protocol.data.game.chunk.DataPalette; /** * Acts as a lightweight chunk class that doesn't store biomes, heightmaps or block entities. diff --git a/core/src/main/java/org/geysermc/geyser/level/physics/BoundingBox.java b/core/src/main/java/org/geysermc/geyser/level/physics/BoundingBox.java index 8343babd0..b1a93d8ee 100644 --- a/core/src/main/java/org/geysermc/geyser/level/physics/BoundingBox.java +++ b/core/src/main/java/org/geysermc/geyser/level/physics/BoundingBox.java @@ -25,10 +25,10 @@ package org.geysermc.geyser.level.physics; -import org.cloudburstmc.math.vector.Vector3d; import lombok.AllArgsConstructor; import lombok.Data; import lombok.SneakyThrows; +import org.cloudburstmc.math.vector.Vector3d; @Data @AllArgsConstructor diff --git a/core/src/main/java/org/geysermc/geyser/level/physics/CollisionManager.java b/core/src/main/java/org/geysermc/geyser/level/physics/CollisionManager.java index 2c3da3c41..ce89689eb 100644 --- a/core/src/main/java/org/geysermc/geyser/level/physics/CollisionManager.java +++ b/core/src/main/java/org/geysermc/geyser/level/physics/CollisionManager.java @@ -25,6 +25,8 @@ package org.geysermc.geyser.level.physics; +import lombok.Getter; +import lombok.Setter; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.GenericMath; import org.cloudburstmc.math.vector.Vector3d; @@ -32,8 +34,6 @@ import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.packet.MovePlayerPacket; -import lombok.Getter; -import lombok.Setter; import org.geysermc.erosion.util.BlockPositionIterator; import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.type.Entity; diff --git a/core/src/main/java/org/geysermc/geyser/level/physics/Direction.java b/core/src/main/java/org/geysermc/geyser/level/physics/Direction.java index 09ff89800..f14a46999 100644 --- a/core/src/main/java/org/geysermc/geyser/level/physics/Direction.java +++ b/core/src/main/java/org/geysermc/geyser/level/physics/Direction.java @@ -30,12 +30,12 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3i; public enum Direction { - DOWN(1, Vector3i.from(0, -1, 0), Axis.Y, com.github.steveice10.mc.protocol.data.game.entity.object.Direction.DOWN), - UP(0, Vector3i.UNIT_Y, Axis.Y, com.github.steveice10.mc.protocol.data.game.entity.object.Direction.UP), - NORTH(3, Vector3i.from(0, 0, -1), Axis.Z, com.github.steveice10.mc.protocol.data.game.entity.object.Direction.NORTH), - SOUTH(2, Vector3i.UNIT_Z, Axis.Z, com.github.steveice10.mc.protocol.data.game.entity.object.Direction.SOUTH), - WEST(5, Vector3i.from(-1, 0, 0), Axis.X, com.github.steveice10.mc.protocol.data.game.entity.object.Direction.WEST), - EAST(4, Vector3i.UNIT_X, Axis.X, com.github.steveice10.mc.protocol.data.game.entity.object.Direction.EAST); + DOWN(1, Vector3i.from(0, -1, 0), Axis.Y, org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction.DOWN), + UP(0, Vector3i.UNIT_Y, Axis.Y, org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction.UP), + NORTH(3, Vector3i.from(0, 0, -1), Axis.Z, org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction.NORTH), + SOUTH(2, Vector3i.UNIT_Z, Axis.Z, org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction.SOUTH), + WEST(5, Vector3i.from(-1, 0, 0), Axis.X, org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction.WEST), + EAST(4, Vector3i.UNIT_X, Axis.X, org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction.EAST); public static final Direction[] VALUES = values(); @@ -44,9 +44,9 @@ public enum Direction { private final Vector3i unitVector; @Getter private final Axis axis; - private final com.github.steveice10.mc.protocol.data.game.entity.object.Direction pistonValue; + private final org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction pistonValue; - Direction(int reversedId, Vector3i unitVector, Axis axis, com.github.steveice10.mc.protocol.data.game.entity.object.Direction pistonValue) { + Direction(int reversedId, Vector3i unitVector, Axis axis, org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction pistonValue) { this.reversedId = reversedId; this.unitVector = unitVector; this.axis = axis; @@ -65,7 +65,7 @@ public enum Direction { return axis == Axis.X || axis == Axis.Z; } - public static @NonNull Direction fromPistonValue(com.github.steveice10.mc.protocol.data.game.entity.object.Direction pistonValue) { + public static @NonNull Direction fromPistonValue(org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction pistonValue) { for (Direction direction : VALUES) { if (direction.pistonValue == pistonValue) { return direction; diff --git a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java index b5fc4440c..cf80e8c6e 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java @@ -25,8 +25,6 @@ package org.geysermc.geyser.network; -import com.github.steveice10.mc.protocol.codec.MinecraftCodec; -import com.github.steveice10.mc.protocol.codec.PacketCodec; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; import org.cloudburstmc.protocol.bedrock.codec.v622.Bedrock_v622; @@ -36,6 +34,8 @@ import org.cloudburstmc.protocol.bedrock.codec.v662.Bedrock_v662; import org.cloudburstmc.protocol.bedrock.codec.v671.Bedrock_v671; import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodec; +import org.geysermc.mcprotocollib.protocol.codec.PacketCodec; import java.util.ArrayList; import java.util.List; diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java b/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java index 121c70f90..19b0b423f 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java @@ -25,19 +25,19 @@ package org.geysermc.geyser.network.netty; -import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; -import com.github.steveice10.packetlib.BuiltinFlags; -import com.github.steveice10.packetlib.codec.PacketCodecHelper; -import com.github.steveice10.packetlib.packet.PacketProtocol; -import com.github.steveice10.packetlib.tcp.TcpPacketCodec; -import com.github.steveice10.packetlib.tcp.TcpPacketSizer; -import com.github.steveice10.packetlib.tcp.TcpSession; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBufAllocator; import io.netty.channel.*; import io.netty.channel.unix.PreferredDirectByteBufAllocator; import io.netty.handler.codec.haproxy.*; import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.mcprotocollib.network.BuiltinFlags; +import org.geysermc.mcprotocollib.network.codec.PacketCodecHelper; +import org.geysermc.mcprotocollib.network.packet.PacketProtocol; +import org.geysermc.mcprotocollib.network.tcp.TcpPacketCodec; +import org.geysermc.mcprotocollib.network.tcp.TcpPacketSizer; +import org.geysermc.mcprotocollib.network.tcp.TcpSession; +import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper; import java.net.Inet4Address; import java.net.InetSocketAddress; diff --git a/core/src/main/java/org/geysermc/geyser/pack/SkullResourcePackManager.java b/core/src/main/java/org/geysermc/geyser/pack/SkullResourcePackManager.java index f6c5140d8..f0faa4244 100644 --- a/core/src/main/java/org/geysermc/geyser/pack/SkullResourcePackManager.java +++ b/core/src/main/java/org/geysermc/geyser/pack/SkullResourcePackManager.java @@ -48,7 +48,9 @@ import java.nio.file.StandardOpenOption; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.List; -import java.util.*; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; import java.util.function.UnaryOperator; import java.util.stream.Stream; import java.util.zip.ZipEntry; diff --git a/core/src/main/java/org/geysermc/geyser/ping/GeyserLegacyPingPassthrough.java b/core/src/main/java/org/geysermc/geyser/ping/GeyserLegacyPingPassthrough.java index 6bbca11ca..320334ee5 100644 --- a/core/src/main/java/org/geysermc/geyser/ping/GeyserLegacyPingPassthrough.java +++ b/core/src/main/java/org/geysermc/geyser/ping/GeyserLegacyPingPassthrough.java @@ -27,11 +27,11 @@ package org.geysermc.geyser.ping; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.JsonMappingException; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.cloudburstmc.nbt.util.VarInts; import io.netty.handler.codec.haproxy.HAProxyCommand; import io.netty.handler.codec.haproxy.HAProxyProxiedProtocol; import io.netty.util.NetUtil; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.cloudburstmc.nbt.util.VarInts; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.network.GameProtocol; diff --git a/core/src/main/java/org/geysermc/geyser/ping/IGeyserPingPassthrough.java b/core/src/main/java/org/geysermc/geyser/ping/IGeyserPingPassthrough.java index 318035e32..69ac974cc 100644 --- a/core/src/main/java/org/geysermc/geyser/ping/IGeyserPingPassthrough.java +++ b/core/src/main/java/org/geysermc/geyser/ping/IGeyserPingPassthrough.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.ping; import org.checkerframework.checker.nullness.qual.Nullable; + import java.net.InetSocketAddress; /** diff --git a/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java b/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java index e37f8aa64..9a5b43816 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java +++ b/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java @@ -25,10 +25,10 @@ package org.geysermc.geyser.registry; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundDelimiterPacket; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundTabListPacket; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundChunkBatchStartPacket; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundLightUpdatePacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundDelimiterPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundTabListPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundChunkBatchStartPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundLightUpdatePacket; import io.netty.channel.EventLoop; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.registry.loader.RegistryLoaders; diff --git a/core/src/main/java/org/geysermc/geyser/registry/Registries.java b/core/src/main/java/org/geysermc/geyser/registry/Registries.java index 9b5ed8ae6..f19898016 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/Registries.java +++ b/core/src/main/java/org/geysermc/geyser/registry/Registries.java @@ -25,12 +25,12 @@ package org.geysermc.geyser.registry; -import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType; -import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; -import com.github.steveice10.mc.protocol.data.game.level.event.LevelEvent; -import com.github.steveice10.mc.protocol.data.game.level.particle.ParticleType; -import com.github.steveice10.mc.protocol.data.game.recipe.RecipeType; -import com.github.steveice10.packetlib.packet.Packet; +import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; +import org.geysermc.mcprotocollib.protocol.data.game.level.event.LevelEvent; +import org.geysermc.mcprotocollib.protocol.data.game.level.particle.ParticleType; +import org.geysermc.mcprotocollib.protocol.data.game.recipe.RecipeType; +import org.geysermc.mcprotocollib.network.packet.Packet; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2IntMap; diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/BlockEntityRegistryLoader.java b/core/src/main/java/org/geysermc/geyser/registry/loader/BlockEntityRegistryLoader.java index f47273827..a813ee458 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/loader/BlockEntityRegistryLoader.java +++ b/core/src/main/java/org/geysermc/geyser/registry/loader/BlockEntityRegistryLoader.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.registry.loader; -import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.geysermc.geyser.translator.level.block.entity.BlockEntity; diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/ParticleTypesRegistryLoader.java b/core/src/main/java/org/geysermc/geyser/registry/loader/ParticleTypesRegistryLoader.java index 677806b3f..a09d6d6d3 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/loader/ParticleTypesRegistryLoader.java +++ b/core/src/main/java/org/geysermc/geyser/registry/loader/ParticleTypesRegistryLoader.java @@ -26,7 +26,7 @@ package org.geysermc.geyser.registry.loader; import com.fasterxml.jackson.databind.JsonNode; -import com.github.steveice10.mc.protocol.data.game.level.particle.ParticleType; +import org.geysermc.mcprotocollib.protocol.data.game.level.particle.ParticleType; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.cloudburstmc.protocol.bedrock.data.LevelEvent; import org.cloudburstmc.protocol.bedrock.data.LevelEventType; diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/SoundEventsRegistryLoader.java b/core/src/main/java/org/geysermc/geyser/registry/loader/SoundEventsRegistryLoader.java index c0600b878..4e3fbe40a 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/loader/SoundEventsRegistryLoader.java +++ b/core/src/main/java/org/geysermc/geyser/registry/loader/SoundEventsRegistryLoader.java @@ -26,7 +26,7 @@ package org.geysermc.geyser.registry.loader; import com.fasterxml.jackson.databind.JsonNode; -import com.github.steveice10.mc.protocol.data.game.level.event.LevelEvent; +import org.geysermc.mcprotocollib.protocol.data.game.level.event.LevelEvent; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.cloudburstmc.protocol.bedrock.data.LevelEventType; import org.geysermc.geyser.GeyserImpl; @@ -58,20 +58,20 @@ public class SoundEventsRegistryLoader extends EffectRegistryLoader { - javaEffect = com.github.steveice10.mc.protocol.data.game.level.event.LevelEventType.valueOf(entry.getKey()); + javaEffect = org.geysermc.mcprotocollib.protocol.data.game.level.event.LevelEventType.valueOf(entry.getKey()); LevelEventType levelEventType = org.cloudburstmc.protocol.bedrock.data.LevelEvent.valueOf(node.get("name").asText()); int data = node.has("data") ? node.get("data").intValue() : 0; transformer = new SoundLevelEventTranslator(levelEventType, data); } case "soundEvent" -> { - javaEffect = com.github.steveice10.mc.protocol.data.game.level.event.LevelEventType.valueOf(entry.getKey()); + javaEffect = org.geysermc.mcprotocollib.protocol.data.game.level.event.LevelEventType.valueOf(entry.getKey()); org.cloudburstmc.protocol.bedrock.data.SoundEvent soundEvent = org.cloudburstmc.protocol.bedrock.data.SoundEvent.valueOf(node.get("name").asText()); String identifier = node.has("identifier") ? node.get("identifier").asText() : ""; int extraData = node.has("extraData") ? node.get("extraData").intValue() : -1; transformer = new SoundEventEventTranslator(soundEvent, identifier, extraData); } case "playSound" -> { - javaEffect = com.github.steveice10.mc.protocol.data.game.level.event.LevelEventType.valueOf(entry.getKey()); + javaEffect = org.geysermc.mcprotocollib.protocol.data.game.level.event.LevelEventType.valueOf(entry.getKey()); String name = node.get("name").asText(); float volume = node.has("volume") ? node.get("volume").floatValue() : 1.0f; boolean pitchSub = node.has("pitch_sub") && node.get("pitch_sub").booleanValue(); diff --git a/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java b/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java index e8901a550..d32d5bc09 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java +++ b/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java @@ -27,7 +27,7 @@ package org.geysermc.geyser.registry.mappings.versions; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; -import com.github.steveice10.mc.protocol.data.game.Identifier; +import org.geysermc.mcprotocollib.protocol.data.game.Identifier; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.checkerframework.checker.nullness.qual.Nullable; diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/PacketRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/PacketRegistryPopulator.java index d055f7b28..9be00732c 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/PacketRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/PacketRegistryPopulator.java @@ -25,13 +25,13 @@ package org.geysermc.geyser.registry.populator; -import com.github.steveice10.packetlib.packet.Packet; import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.util.FileUtils; +import org.geysermc.mcprotocollib.network.packet.Packet; public class PacketRegistryPopulator { 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 34e855212..928ab8df9 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 @@ -26,9 +26,9 @@ package org.geysermc.geyser.registry.populator; import com.fasterxml.jackson.databind.JsonNode; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; -import com.github.steveice10.mc.protocol.data.game.recipe.RecipeType; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.recipe.Ingredient; +import org.geysermc.mcprotocollib.protocol.data.game.recipe.RecipeType; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; 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 199481cbc..f3cfa3f0f 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 @@ -25,7 +25,7 @@ package org.geysermc.geyser.registry.type; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import lombok.Builder; diff --git a/core/src/main/java/org/geysermc/geyser/scoreboard/Objective.java b/core/src/main/java/org/geysermc/geyser/scoreboard/Objective.java index c00c69660..6c1389ef5 100644 --- a/core/src/main/java/org/geysermc/geyser/scoreboard/Objective.java +++ b/core/src/main/java/org/geysermc/geyser/scoreboard/Objective.java @@ -25,13 +25,13 @@ package org.geysermc.geyser.scoreboard; -import com.github.steveice10.mc.protocol.data.game.chat.numbers.NumberFormat; -import com.github.steveice10.mc.protocol.data.game.scoreboard.ScoreboardPosition; -import com.github.steveice10.mc.protocol.data.game.scoreboard.TeamColor; import lombok.Getter; import lombok.Setter; import net.kyori.adventure.text.Component; import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.mcprotocollib.protocol.data.game.chat.numbers.NumberFormat; +import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.ScoreboardPosition; +import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.TeamColor; import java.util.Map; import java.util.Objects; diff --git a/core/src/main/java/org/geysermc/geyser/scoreboard/Score.java b/core/src/main/java/org/geysermc/geyser/scoreboard/Score.java index ec17818c4..9a26b7f77 100644 --- a/core/src/main/java/org/geysermc/geyser/scoreboard/Score.java +++ b/core/src/main/java/org/geysermc/geyser/scoreboard/Score.java @@ -25,8 +25,8 @@ package org.geysermc.geyser.scoreboard; -import com.github.steveice10.mc.protocol.data.game.chat.numbers.FixedFormat; -import com.github.steveice10.mc.protocol.data.game.chat.numbers.NumberFormat; +import org.geysermc.mcprotocollib.protocol.data.game.chat.numbers.FixedFormat; +import org.geysermc.mcprotocollib.protocol.data.game.chat.numbers.NumberFormat; import net.kyori.adventure.text.Component; import org.cloudburstmc.protocol.bedrock.data.ScoreInfo; import lombok.Getter; diff --git a/core/src/main/java/org/geysermc/geyser/scoreboard/Scoreboard.java b/core/src/main/java/org/geysermc/geyser/scoreboard/Scoreboard.java index dfd74a79e..acce86f4d 100644 --- a/core/src/main/java/org/geysermc/geyser/scoreboard/Scoreboard.java +++ b/core/src/main/java/org/geysermc/geyser/scoreboard/Scoreboard.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.scoreboard; -import com.github.steveice10.mc.protocol.data.game.scoreboard.ScoreboardPosition; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import lombok.Getter; import org.checkerframework.checker.nullness.qual.Nullable; @@ -40,6 +39,7 @@ import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.player.PlayerEntity; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.GeyserLocale; +import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.ScoreboardPosition; import org.jetbrains.annotations.Contract; import java.util.*; @@ -48,10 +48,7 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.function.Function; import java.util.stream.Collectors; -import static org.geysermc.geyser.scoreboard.UpdateType.ADD; -import static org.geysermc.geyser.scoreboard.UpdateType.NOTHING; -import static org.geysermc.geyser.scoreboard.UpdateType.REMOVE; -import static org.geysermc.geyser.scoreboard.UpdateType.UPDATE; +import static org.geysermc.geyser.scoreboard.UpdateType.*; public final class Scoreboard { private static final boolean SHOW_SCOREBOARD_LOGS = Boolean.parseBoolean(System.getProperty("Geyser.ShowScoreboardLogs", "true")); diff --git a/core/src/main/java/org/geysermc/geyser/scoreboard/Team.java b/core/src/main/java/org/geysermc/geyser/scoreboard/Team.java index 9164fec1d..cdf2e247e 100644 --- a/core/src/main/java/org/geysermc/geyser/scoreboard/Team.java +++ b/core/src/main/java/org/geysermc/geyser/scoreboard/Team.java @@ -25,8 +25,8 @@ package org.geysermc.geyser.scoreboard; -import com.github.steveice10.mc.protocol.data.game.scoreboard.NameTagVisibility; -import com.github.steveice10.mc.protocol.data.game.scoreboard.TeamColor; +import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.NameTagVisibility; +import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.TeamColor; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import lombok.AccessLevel; import lombok.Getter; diff --git a/core/src/main/java/org/geysermc/geyser/session/DownstreamSession.java b/core/src/main/java/org/geysermc/geyser/session/DownstreamSession.java index 40b685783..8845cdbea 100644 --- a/core/src/main/java/org/geysermc/geyser/session/DownstreamSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/DownstreamSession.java @@ -25,12 +25,12 @@ package org.geysermc.geyser.session; -import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; -import com.github.steveice10.packetlib.packet.Packet; -import com.github.steveice10.packetlib.tcp.TcpSession; import lombok.Getter; import lombok.RequiredArgsConstructor; import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.mcprotocollib.network.packet.Packet; +import org.geysermc.mcprotocollib.network.tcp.TcpSession; +import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper; @Getter @RequiredArgsConstructor diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 9ae1f6f49..82717050f 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -28,35 +28,35 @@ package org.geysermc.geyser.session; import com.github.steveice10.mc.auth.data.GameProfile; import com.github.steveice10.mc.auth.exception.request.RequestException; import com.github.steveice10.mc.auth.service.MsaAuthenticationService; -import com.github.steveice10.mc.protocol.MinecraftConstants; -import com.github.steveice10.mc.protocol.MinecraftProtocol; -import com.github.steveice10.mc.protocol.data.ProtocolState; -import com.github.steveice10.mc.protocol.data.UnexpectedEncryptionException; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose; -import com.github.steveice10.mc.protocol.data.game.entity.object.Direction; -import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; -import com.github.steveice10.mc.protocol.data.game.entity.player.HandPreference; -import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction; -import com.github.steveice10.mc.protocol.data.game.setting.ChatVisibility; -import com.github.steveice10.mc.protocol.data.game.setting.SkinPart; -import com.github.steveice10.mc.protocol.data.game.statistic.CustomStatistic; -import com.github.steveice10.mc.protocol.data.game.statistic.Statistic; -import com.github.steveice10.mc.protocol.packet.common.serverbound.ServerboundClientInformationPacket; -import com.github.steveice10.mc.protocol.packet.handshake.serverbound.ClientIntentionPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatCommandSignedPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundPlayerAbilitiesPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundPlayerActionPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundUseItemPacket; -import com.github.steveice10.mc.protocol.packet.login.serverbound.ServerboundCustomQueryAnswerPacket; -import com.github.steveice10.packetlib.BuiltinFlags; -import com.github.steveice10.packetlib.Session; -import com.github.steveice10.packetlib.event.session.*; -import com.github.steveice10.packetlib.packet.Packet; -import com.github.steveice10.packetlib.tcp.TcpClientSession; -import com.github.steveice10.packetlib.tcp.TcpSession; +import org.geysermc.mcprotocollib.protocol.MinecraftConstants; +import org.geysermc.mcprotocollib.protocol.MinecraftProtocol; +import org.geysermc.mcprotocollib.protocol.data.ProtocolState; +import org.geysermc.mcprotocollib.protocol.data.UnexpectedEncryptionException; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose; +import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.HandPreference; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerAction; +import org.geysermc.mcprotocollib.protocol.data.game.setting.ChatVisibility; +import org.geysermc.mcprotocollib.protocol.data.game.setting.SkinPart; +import org.geysermc.mcprotocollib.protocol.data.game.statistic.CustomStatistic; +import org.geysermc.mcprotocollib.protocol.data.game.statistic.Statistic; +import org.geysermc.mcprotocollib.protocol.packet.common.serverbound.ServerboundClientInformationPacket; +import org.geysermc.mcprotocollib.protocol.packet.handshake.serverbound.ClientIntentionPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundChatCommandSignedPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundChatPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundPlayerAbilitiesPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundPlayerActionPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundUseItemPacket; +import org.geysermc.mcprotocollib.protocol.packet.login.serverbound.ServerboundCustomQueryAnswerPacket; +import org.geysermc.mcprotocollib.network.BuiltinFlags; +import org.geysermc.mcprotocollib.network.Session; +import org.geysermc.mcprotocollib.network.event.session.*; +import org.geysermc.mcprotocollib.network.packet.Packet; +import org.geysermc.mcprotocollib.network.tcp.TcpClientSession; +import org.geysermc.mcprotocollib.network.tcp.TcpSession; import io.netty.channel.Channel; import io.netty.channel.EventLoop; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/AdvancementsCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/AdvancementsCache.java index 3bc661c16..da3c83ed4 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/AdvancementsCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/AdvancementsCache.java @@ -25,8 +25,8 @@ package org.geysermc.geyser.session.cache; -import com.github.steveice10.mc.protocol.data.game.advancement.Advancement; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundSeenAdvancementsPacket; +import org.geysermc.mcprotocollib.protocol.data.game.advancement.Advancement; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundSeenAdvancementsPacket; import lombok.Getter; import lombok.Setter; import org.geysermc.cumulus.form.SimpleForm; diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/BookEditCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/BookEditCache.java index 6a9025bc0..90f22afd6 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/BookEditCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/BookEditCache.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.session.cache; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundEditBookPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundEditBookPacket; import lombok.Setter; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.Items; diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/ChunkCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/ChunkCache.java index d2c1415a3..e3a9cba89 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/ChunkCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/ChunkCache.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.session.cache; -import com.github.steveice10.mc.protocol.data.game.chunk.DataPalette; +import org.geysermc.mcprotocollib.protocol.data.game.chunk.DataPalette; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import lombok.Getter; diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/EntityEffectCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/EntityEffectCache.java index a7693e516..a9679f6ef 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/EntityEffectCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/EntityEffectCache.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.session.cache; -import com.github.steveice10.mc.protocol.data.game.entity.Effect; +import org.geysermc.mcprotocollib.protocol.data.game.entity.Effect; import lombok.Getter; import java.util.EnumSet; diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/LodestoneCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/LodestoneCache.java index eced0e50b..f9515dbb4 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/LodestoneCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/LodestoneCache.java @@ -25,10 +25,10 @@ package org.geysermc.geyser.session.cache; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.GlobalPos; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.mc.protocol.data.game.item.component.LodestoneTracker; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.GlobalPos; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.LodestoneTracker; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import org.checkerframework.checker.nullness.qual.Nullable; diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java index d6d5ae292..7ad2afec7 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java @@ -25,8 +25,6 @@ package org.geysermc.geyser.session.cache; -import com.github.steveice10.mc.protocol.data.game.RegistryEntry; -import com.github.steveice10.mc.protocol.packet.configuration.clientbound.ClientboundRegistryDataPacket; import it.unimi.dsi.fastutil.ints.Int2IntMap; import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; @@ -44,6 +42,8 @@ import org.geysermc.geyser.level.JavaDimension; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.TextDecoration; import org.geysermc.geyser.translator.level.BiomeTranslator; +import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry; +import org.geysermc.mcprotocollib.protocol.packet.configuration.clientbound.ClientboundRegistryDataPacket; import java.util.HashMap; import java.util.List; diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java index b2f43f180..38ac32214 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.session.cache; -import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundUpdateTagsPacket; +import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundUpdateTagsPacket; import it.unimi.dsi.fastutil.ints.IntList; import org.geysermc.geyser.GeyserLogger; import org.geysermc.geyser.inventory.GeyserItemStack; diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/TeleportCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/TeleportCache.java index 8d243d3fa..80139a988 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/TeleportCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/TeleportCache.java @@ -33,7 +33,7 @@ import lombok.RequiredArgsConstructor; * Represents a teleport ID and corresponding coordinates that need to be confirmed.
* * The vanilla Java client, after getting a - * {@link com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.player.ClientboundPlayerPositionPacket}, + * {@link org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.player.ClientboundPlayerPositionPacket}, * adjusts the player's positions and immediately sends a teleport back. However, we want to acknowledge that the * Bedrock player actually moves close to that point, so we store the teleport until we get a movement packet from * Bedrock that the teleport was successful. diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/WorldCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/WorldCache.java index 6be57670c..c84126608 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/WorldCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/WorldCache.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.session.cache; -import com.github.steveice10.mc.protocol.data.game.setting.Difficulty; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntMaps; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; @@ -37,6 +36,7 @@ import org.geysermc.geyser.scoreboard.Scoreboard; import org.geysermc.geyser.scoreboard.ScoreboardUpdater.ScoreboardSession; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.ChunkUtils; +import org.geysermc.mcprotocollib.protocol.data.game.setting.Difficulty; import java.util.Iterator; diff --git a/core/src/main/java/org/geysermc/geyser/skin/FakeHeadProvider.java b/core/src/main/java/org/geysermc/geyser/skin/FakeHeadProvider.java index 2d6345bfa..d2a45b614 100644 --- a/core/src/main/java/org/geysermc/geyser/skin/FakeHeadProvider.java +++ b/core/src/main/java/org/geysermc/geyser/skin/FakeHeadProvider.java @@ -30,8 +30,6 @@ import com.github.steveice10.mc.auth.data.GameProfile.Texture; import com.github.steveice10.mc.auth.data.GameProfile.TextureModel; import com.github.steveice10.mc.auth.data.GameProfile.TextureType; import com.github.steveice10.mc.auth.exception.property.PropertyException; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; @@ -45,6 +43,8 @@ import org.geysermc.geyser.entity.type.player.PlayerEntity; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.skin.SkinManager.GameProfileData; import org.geysermc.geyser.text.GeyserLocale; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; import java.awt.*; import java.awt.image.BufferedImage; diff --git a/core/src/main/java/org/geysermc/geyser/text/ChatTypeEntry.java b/core/src/main/java/org/geysermc/geyser/text/ChatTypeEntry.java index 500f44d0b..f139b0bba 100644 --- a/core/src/main/java/org/geysermc/geyser/text/ChatTypeEntry.java +++ b/core/src/main/java/org/geysermc/geyser/text/ChatTypeEntry.java @@ -25,11 +25,11 @@ package org.geysermc.geyser.text; -import com.github.steveice10.mc.protocol.data.game.chat.BuiltinChatType; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.packet.TextPacket; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import org.geysermc.mcprotocollib.protocol.data.game.chat.BuiltinChatType; public record ChatTypeEntry(TextPacket.@NonNull Type bedrockChatType, @Nullable TextDecoration textDecoration) { private static final ChatTypeEntry CHAT = new ChatTypeEntry(TextPacket.Type.CHAT, null); diff --git a/core/src/main/java/org/geysermc/geyser/text/MinecraftLocale.java b/core/src/main/java/org/geysermc/geyser/text/MinecraftLocale.java index 692a05110..94d8b254f 100644 --- a/core/src/main/java/org/geysermc/geyser/text/MinecraftLocale.java +++ b/core/src/main/java/org/geysermc/geyser/text/MinecraftLocale.java @@ -32,7 +32,9 @@ import org.geysermc.geyser.util.AssetUtils; import org.geysermc.geyser.util.FileUtils; import org.geysermc.geyser.util.WebUtils; -import java.io.*; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; diff --git a/core/src/main/java/org/geysermc/geyser/text/TextDecoration.java b/core/src/main/java/org/geysermc/geyser/text/TextDecoration.java index bad55a5ca..a85153d13 100644 --- a/core/src/main/java/org/geysermc/geyser/text/TextDecoration.java +++ b/core/src/main/java/org/geysermc/geyser/text/TextDecoration.java @@ -25,13 +25,13 @@ package org.geysermc.geyser.text; -import com.github.steveice10.mc.protocol.data.game.RegistryEntry; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.Style; +import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry; import java.util.EnumSet; import java.util.Locale; diff --git a/core/src/main/java/org/geysermc/geyser/translator/collision/BlockCollision.java b/core/src/main/java/org/geysermc/geyser/translator/collision/BlockCollision.java index e82b994c7..a2615deb1 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/collision/BlockCollision.java +++ b/core/src/main/java/org/geysermc/geyser/translator/collision/BlockCollision.java @@ -25,10 +25,10 @@ package org.geysermc.geyser.translator.collision; -import org.cloudburstmc.math.vector.Vector3d; -import org.cloudburstmc.math.vector.Vector3i; import lombok.EqualsAndHashCode; import lombok.Getter; +import org.cloudburstmc.math.vector.Vector3d; +import org.cloudburstmc.math.vector.Vector3i; import org.geysermc.geyser.level.physics.Axis; import org.geysermc.geyser.level.physics.BoundingBox; import org.geysermc.geyser.level.physics.CollisionManager; diff --git a/core/src/main/java/org/geysermc/geyser/translator/entity/EntityMetadataTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/entity/EntityMetadataTranslator.java index dd53e4c5b..194194501 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/entity/EntityMetadataTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/entity/EntityMetadataTranslator.java @@ -25,8 +25,8 @@ package org.geysermc.geyser.translator.entity; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.MetadataType; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.MetadataType; import org.geysermc.geyser.entity.type.Entity; import java.util.function.BiConsumer; diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/AnvilInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/AnvilInventoryTranslator.java index 31a0b7b11..2da51a0eb 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/AnvilInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/AnvilInventoryTranslator.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.translator.inventory; -import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequest; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData; @@ -39,6 +38,7 @@ import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.PlayerInventory; import org.geysermc.geyser.inventory.updater.AnvilInventoryUpdater; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; import java.util.Objects; diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/BaseInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/BaseInventoryTranslator.java index 0f8fa4ca7..f70bad9ea 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/BaseInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/BaseInventoryTranslator.java @@ -25,15 +25,11 @@ package org.geysermc.geyser.translator.inventory; -import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData; -import org.geysermc.geyser.inventory.BedrockContainerSlot; -import org.geysermc.geyser.inventory.Container; -import org.geysermc.geyser.inventory.Inventory; -import org.geysermc.geyser.inventory.PlayerInventory; -import org.geysermc.geyser.inventory.SlotType; +import org.geysermc.geyser.inventory.*; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; public abstract class BaseInventoryTranslator extends InventoryTranslator { public BaseInventoryTranslator(int size) { diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/BeaconInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/BeaconInventoryTranslator.java index 00323ce83..9aeeff007 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/BeaconInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/BeaconInventoryTranslator.java @@ -25,8 +25,6 @@ package org.geysermc.geyser.translator.inventory; -import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundSetBeaconPacket; import it.unimi.dsi.fastutil.ints.IntSets; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; @@ -47,6 +45,8 @@ import org.geysermc.geyser.inventory.holder.BlockInventoryHolder; import org.geysermc.geyser.inventory.updater.UIInventoryUpdater; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InventoryUtils; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundSetBeaconPacket; import java.util.OptionalInt; diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/CartographyInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/CartographyInventoryTranslator.java index 95f227ed7..a115bd953 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/CartographyInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/CartographyInventoryTranslator.java @@ -25,13 +25,13 @@ package org.geysermc.geyser.translator.inventory; -import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData; import org.geysermc.geyser.inventory.*; import org.geysermc.geyser.inventory.updater.UIInventoryUpdater; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; public class CartographyInventoryTranslator extends AbstractBlockInventoryTranslator { public CartographyInventoryTranslator() { diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/CrafterInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/CrafterInventoryTranslator.java index 97398a207..2a2f5beb5 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/CrafterInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/CrafterInventoryTranslator.java @@ -25,19 +25,15 @@ package org.geysermc.geyser.translator.inventory; -import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData; -import org.geysermc.geyser.inventory.BedrockContainerSlot; -import org.geysermc.geyser.inventory.CrafterContainer; -import org.geysermc.geyser.inventory.Inventory; -import org.geysermc.geyser.inventory.PlayerInventory; -import org.geysermc.geyser.inventory.SlotType; +import org.geysermc.geyser.inventory.*; import org.geysermc.geyser.inventory.updater.CrafterInventoryUpdater; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.BlockEntityUtils; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; /** * Translates the Crafter. Most important thing to know about this class is that diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/EnchantingInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/EnchantingInventoryTranslator.java index 0085a7550..8fee2a391 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/EnchantingInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/EnchantingInventoryTranslator.java @@ -25,8 +25,6 @@ package org.geysermc.geyser.translator.inventory; -import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket; import it.unimi.dsi.fastutil.ints.IntSets; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; import org.cloudburstmc.protocol.bedrock.data.inventory.EnchantOptionData; @@ -41,6 +39,8 @@ import org.geysermc.geyser.inventory.*; import org.geysermc.geyser.inventory.item.Enchantment; import org.geysermc.geyser.inventory.updater.UIInventoryUpdater; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket; import java.util.Arrays; import java.util.Locale; diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/Generic3X3InventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/Generic3X3InventoryTranslator.java index 369a80282..2a80161c0 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/Generic3X3InventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/Generic3X3InventoryTranslator.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.translator.inventory; -import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; import org.cloudburstmc.protocol.bedrock.packet.ContainerOpenPacket; import org.geysermc.geyser.inventory.BedrockContainerSlot; @@ -34,6 +33,7 @@ import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.PlayerInventory; import org.geysermc.geyser.inventory.updater.ContainerInventoryUpdater; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; /** * Droppers and dispensers diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java index 4a3e31b30..0914aeba8 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java @@ -25,11 +25,6 @@ package org.geysermc.geyser.translator.inventory; -import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; import it.unimi.dsi.fastutil.ints.*; import lombok.AllArgsConstructor; import org.checkerframework.checker.nullness.qual.Nullable; @@ -59,6 +54,11 @@ import org.geysermc.geyser.translator.inventory.furnace.FurnaceInventoryTranslat import org.geysermc.geyser.translator.inventory.furnace.SmokerInventoryTranslator; import org.geysermc.geyser.util.InventoryUtils; import org.geysermc.geyser.util.ItemUtils; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; +import org.geysermc.mcprotocollib.protocol.data.game.recipe.Ingredient; import java.util.*; diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java index 7dff2647c..f3bbc9b87 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java @@ -25,12 +25,6 @@ package org.geysermc.geyser.translator.inventory; -import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.item.component.WritableBookContent; -import com.github.steveice10.mc.protocol.data.game.item.component.WrittenBookContent; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClosePacket; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; @@ -38,16 +32,18 @@ import org.cloudburstmc.nbt.NbtType; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.erosion.util.LecternUtils; import org.geysermc.geyser.GeyserImpl; -import org.geysermc.geyser.inventory.Container; -import org.geysermc.geyser.inventory.GeyserItemStack; -import org.geysermc.geyser.inventory.Inventory; -import org.geysermc.geyser.inventory.LecternContainer; -import org.geysermc.geyser.inventory.PlayerInventory; +import org.geysermc.geyser.inventory.*; import org.geysermc.geyser.inventory.updater.ContainerInventoryUpdater; import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.BlockEntityUtils; import org.geysermc.geyser.util.InventoryUtils; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.WritableBookContent; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.WrittenBookContent; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClosePacket; import java.util.Collections; diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/LoomInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/LoomInventoryTranslator.java index 636a7982a..e8571c8fb 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/LoomInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/LoomInventoryTranslator.java @@ -25,10 +25,6 @@ package org.geysermc.geyser.translator.inventory; -import com.github.steveice10.mc.protocol.data.game.item.component.BannerPatternLayer; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import org.cloudburstmc.nbt.NbtMap; @@ -50,6 +46,10 @@ import org.geysermc.geyser.inventory.updater.UIInventoryUpdater; import org.geysermc.geyser.item.type.BannerItem; import org.geysermc.geyser.item.type.DyeItem; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.BannerPatternLayer; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket; import java.util.ArrayList; import java.util.HashMap; diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/MerchantInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/MerchantInventoryTranslator.java index c4f958ba1..7a7646503 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/MerchantInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/MerchantInventoryTranslator.java @@ -25,8 +25,6 @@ package org.geysermc.geyser.translator.inventory; -import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundSelectTradePacket; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityLinkData; @@ -44,6 +42,8 @@ import org.geysermc.geyser.inventory.updater.InventoryUpdater; import org.geysermc.geyser.inventory.updater.UIInventoryUpdater; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InventoryUtils; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundSelectTradePacket; import java.util.concurrent.TimeUnit; diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/OldSmithingTableTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/OldSmithingTableTranslator.java index 5f08f1b8a..201c900d6 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/OldSmithingTableTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/OldSmithingTableTranslator.java @@ -31,11 +31,7 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequest; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData; -import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.DropAction; -import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.ItemStackRequestAction; -import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.PlaceAction; -import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.SwapAction; -import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.TakeAction; +import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.*; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.response.ItemStackResponse; import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket; import org.geysermc.geyser.inventory.BedrockContainerSlot; diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java index 36d10aa54..142651eb4 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java @@ -25,10 +25,6 @@ package org.geysermc.geyser.translator.inventory; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; -import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundSetCreativeModeSlotPacket; import it.unimi.dsi.fastutil.ints.IntIterator; import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; @@ -37,12 +33,7 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequest; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData; -import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.CraftCreativeAction; -import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.DestroyAction; -import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.DropAction; -import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.ItemStackRequestAction; -import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.SwapAction; -import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.TransferItemStackRequestAction; +import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.*; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.response.ItemStackResponse; import org.cloudburstmc.protocol.bedrock.packet.ContainerClosePacket; import org.cloudburstmc.protocol.bedrock.packet.ContainerOpenPacket; @@ -55,6 +46,10 @@ import org.geysermc.geyser.skin.FakeHeadProvider; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.translator.item.ItemTranslator; import org.geysermc.geyser.util.InventoryUtils; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundSetCreativeModeSlotPacket; import java.util.Arrays; import java.util.Collections; diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/ShulkerInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/ShulkerInventoryTranslator.java index b8bb2bee4..543f519c9 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/ShulkerInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/ShulkerInventoryTranslator.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.translator.inventory; -import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; @@ -39,6 +38,7 @@ import org.geysermc.geyser.inventory.updater.ContainerInventoryUpdater; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; public class ShulkerInventoryTranslator extends AbstractBlockInventoryTranslator { public ShulkerInventoryTranslator() { diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/StonecutterInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/StonecutterInventoryTranslator.java index d3d15680a..54f2f447b 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/StonecutterInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/StonecutterInventoryTranslator.java @@ -25,9 +25,6 @@ package org.geysermc.geyser.translator.inventory; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequest; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData; @@ -39,6 +36,9 @@ import org.geysermc.geyser.inventory.*; import org.geysermc.geyser.inventory.recipe.GeyserStonecutterData; import org.geysermc.geyser.inventory.updater.UIInventoryUpdater; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket; public class StonecutterInventoryTranslator extends AbstractBlockInventoryTranslator { public StonecutterInventoryTranslator() { diff --git a/core/src/main/java/org/geysermc/geyser/translator/item/CustomItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/item/CustomItemTranslator.java index 8a541fb9b..91eee3895 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/item/CustomItemTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/item/CustomItemTranslator.java @@ -25,8 +25,8 @@ package org.geysermc.geyser.translator.item; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import it.unimi.dsi.fastutil.Pair; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; diff --git a/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java index a8e9e1c52..24362f800 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java @@ -29,13 +29,13 @@ import com.github.steveice10.mc.auth.data.GameProfile; import com.github.steveice10.mc.auth.data.GameProfile.Texture; import com.github.steveice10.mc.auth.data.GameProfile.TextureType; import com.github.steveice10.mc.auth.exception.property.PropertyException; -import com.github.steveice10.mc.protocol.data.game.Identifier; -import com.github.steveice10.mc.protocol.data.game.entity.attribute.ModifierOperation; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.item.component.AdventureModePredicate; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.mc.protocol.data.game.item.component.ItemAttributeModifiers; +import org.geysermc.mcprotocollib.protocol.data.game.Identifier; +import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.ModifierOperation; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.AdventureModePredicate; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemAttributeModifiers; import com.github.steveice10.opennbt.tag.builtin.*; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; 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 450c786f2..d70f53e2c 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 @@ -25,12 +25,12 @@ package org.geysermc.geyser.translator.level; -import com.github.steveice10.mc.protocol.data.game.RegistryEntry; -import com.github.steveice10.mc.protocol.data.game.chunk.BitStorage; -import com.github.steveice10.mc.protocol.data.game.chunk.DataPalette; -import com.github.steveice10.mc.protocol.data.game.chunk.palette.GlobalPalette; -import com.github.steveice10.mc.protocol.data.game.chunk.palette.Palette; -import com.github.steveice10.mc.protocol.data.game.chunk.palette.SingletonPalette; +import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry; +import org.geysermc.mcprotocollib.protocol.data.game.chunk.BitStorage; +import org.geysermc.mcprotocollib.protocol.data.game.chunk.DataPalette; +import org.geysermc.mcprotocollib.protocol.data.game.chunk.palette.GlobalPalette; +import org.geysermc.mcprotocollib.protocol.data.game.chunk.palette.Palette; +import org.geysermc.mcprotocollib.protocol.data.game.chunk.palette.SingletonPalette; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; import it.unimi.dsi.fastutil.ints.IntLists; diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BannerBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BannerBlockEntityTranslator.java index e0e0130c5..bc08dd93b 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BannerBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BannerBlockEntityTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.level.block.entity; -import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.Tag; diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BeaconBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BeaconBlockEntityTranslator.java index 12b050236..0db362949 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BeaconBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BeaconBlockEntityTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.level.block.entity; -import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.cloudburstmc.nbt.NbtMapBuilder; diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BedBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BedBlockEntityTranslator.java index 58d36af56..1c46edf0a 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BedBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BedBlockEntityTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.level.block.entity; -import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.level.block.BlockStateValues; diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BlockEntity.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BlockEntity.java index 3e320029b..e6ce287c1 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BlockEntity.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BlockEntity.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.level.block.entity; -import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BlockEntityTranslator.java index 053e2c8f3..5f6487a24 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BlockEntityTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.level.block.entity; -import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import org.cloudburstmc.nbt.NbtMap; diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BrushableBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BrushableBlockEntityTranslator.java index 9a2b9d8e1..d2777d372 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BrushableBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BrushableBlockEntityTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.level.block.entity; -import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.Tag; diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/CampfireBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/CampfireBlockEntityTranslator.java index 5a15ebbb7..390615b9e 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/CampfireBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/CampfireBlockEntityTranslator.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.translator.level.block.entity; -import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.Tag; @@ -34,6 +33,7 @@ import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.type.ItemMapping; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; @BlockEntity(type = BlockEntityType.CAMPFIRE) public class CampfireBlockEntityTranslator extends BlockEntityTranslator { diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/CommandBlockBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/CommandBlockBlockEntityTranslator.java index 36345394b..31a7dbc69 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/CommandBlockBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/CommandBlockBlockEntityTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.level.block.entity; -import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; import com.github.steveice10.opennbt.tag.builtin.*; import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.level.block.BlockStateValues; diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DecoratedPotBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DecoratedPotBlockEntityTranslator.java index 1774d9c76..3ab61c489 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DecoratedPotBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DecoratedPotBlockEntityTranslator.java @@ -25,13 +25,13 @@ package org.geysermc.geyser.translator.level.block.entity; -import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; import java.util.ArrayList; import java.util.List; diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DoubleChestBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DoubleChestBlockEntityTranslator.java index 567d3a5e1..141520ed9 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DoubleChestBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DoubleChestBlockEntityTranslator.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.translator.level.block.entity; -import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMapBuilder; @@ -33,6 +32,7 @@ import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.DoubleChestValue; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.BlockEntityUtils; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; /** * Chests have more block entity properties in Bedrock, which is solved by implementing the BedrockOnlyBlockEntity diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/EndGatewayBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/EndGatewayBlockEntityTranslator.java index da992d0ad..633992431 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/EndGatewayBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/EndGatewayBlockEntityTranslator.java @@ -25,16 +25,16 @@ package org.geysermc.geyser.translator.level.block.entity; -import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.LongTag; import com.github.steveice10.opennbt.tag.builtin.Tag; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; import org.cloudburstmc.nbt.NbtList; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; -import it.unimi.dsi.fastutil.ints.IntArrayList; -import it.unimi.dsi.fastutil.ints.IntList; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; import java.util.LinkedHashMap; diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/HangingSignBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/HangingSignBlockEntityTranslator.java index ea11dcf48..3c09c0499 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/HangingSignBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/HangingSignBlockEntityTranslator.java @@ -25,8 +25,8 @@ package org.geysermc.geyser.translator.level.block.entity; -import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; import org.geysermc.geyser.util.SignUtils; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; @BlockEntity(type = BlockEntityType.HANGING_SIGN) public class HangingSignBlockEntityTranslator extends SignBlockEntityTranslator { diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/JigsawBlockBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/JigsawBlockBlockEntityTranslator.java index c8dcbc008..34c051a34 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/JigsawBlockBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/JigsawBlockBlockEntityTranslator.java @@ -25,12 +25,12 @@ package org.geysermc.geyser.translator.level.block.entity; -import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; 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 org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; @BlockEntity(type = BlockEntityType.JIGSAW) public class JigsawBlockBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState { 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 634b7c6f1..78e71000a 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 @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.level.block.entity; -import com.github.steveice10.mc.protocol.data.game.level.block.value.PistonValueType; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.PistonValueType; import org.cloudburstmc.math.vector.Vector3d; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/ShulkerBoxBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/ShulkerBoxBlockEntityTranslator.java index bbe6a0725..529ed731e 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/ShulkerBoxBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/ShulkerBoxBlockEntityTranslator.java @@ -25,12 +25,12 @@ package org.geysermc.geyser.translator.level.block.entity; -import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.translator.inventory.ShulkerInventoryTranslator; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; @BlockEntity(type = BlockEntityType.SHULKER_BOX) public class ShulkerBoxBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState { diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SignBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SignBlockEntityTranslator.java index 238b136ff..38a4f59c5 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SignBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SignBlockEntityTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.level.block.entity; -import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.Tag; diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java index e9aceece5..61c922528 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.level.block.entity; -import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.IntArrayTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SpawnerBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SpawnerBlockEntityTranslator.java index f2b0f5a78..5611bf90c 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SpawnerBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SpawnerBlockEntityTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.level.block.entity; -import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.Tag; diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/StructureBlockBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/StructureBlockBlockEntityTranslator.java index a24d010b7..40b10de40 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/StructureBlockBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/StructureBlockBlockEntityTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.level.block.entity; -import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/TrialSpawnerBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/TrialSpawnerBlockEntityTranslator.java index a6a99d868..da013cf3c 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/TrialSpawnerBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/TrialSpawnerBlockEntityTranslator.java @@ -25,9 +25,9 @@ package org.geysermc.geyser.translator.level.block.entity; -import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.cloudburstmc.nbt.NbtMapBuilder; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; @BlockEntity(type = BlockEntityType.TRIAL_SPAWNER) public class TrialSpawnerBlockEntityTranslator extends BlockEntityTranslator { diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/event/LevelEventTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/event/LevelEventTranslator.java index 03c40c796..311ae0acf 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/event/LevelEventTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/event/LevelEventTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.level.event; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundLevelEventPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundLevelEventPacket; import org.geysermc.geyser.session.GeyserSession; /** diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/event/PlaySoundEventTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/event/PlaySoundEventTranslator.java index 22d5c953d..774060a4c 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/event/PlaySoundEventTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/event/PlaySoundEventTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.level.event; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundLevelEventPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundLevelEventPacket; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.packet.PlaySoundPacket; import org.geysermc.geyser.session.GeyserSession; diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/event/SoundEventEventTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/event/SoundEventEventTranslator.java index d1695303d..d7a58fe48 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/event/SoundEventEventTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/event/SoundEventEventTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.level.event; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundLevelEventPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundLevelEventPacket; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEventPacket; diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/event/SoundLevelEventTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/event/SoundLevelEventTranslator.java index 67d43e6a8..e5b20493b 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/event/SoundLevelEventTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/event/SoundLevelEventTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.level.event; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundLevelEventPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundLevelEventPacket; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.LevelEventType; import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockAnimateTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockAnimateTranslator.java index 33fbaed30..79e013246 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockAnimateTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockAnimateTranslator.java @@ -25,9 +25,9 @@ package org.geysermc.geyser.translator.protocol.bedrock; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.level.ServerboundPaddleBoatPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundSwingPacket; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.level.ServerboundPaddleBoatPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundSwingPacket; import org.cloudburstmc.protocol.bedrock.packet.AnimatePacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockEntityDataTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockEntityDataTranslator.java index 239bf9616..b5e923ee6 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockEntityDataTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockEntityDataTranslator.java @@ -25,8 +25,8 @@ package org.geysermc.geyser.translator.protocol.bedrock; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundSetJigsawBlockPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.level.ServerboundSignUpdatePacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundSetJigsawBlockPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.level.ServerboundSignUpdatePacket; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java index f4116ec0c..35c46ffd2 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.bedrock; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.packet.BlockPickRequestPacket; import org.geysermc.geyser.entity.EntityDefinitions; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBookEditTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBookEditTranslator.java index 10024c02f..456b6507f 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBookEditTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBookEditTranslator.java @@ -25,12 +25,12 @@ package org.geysermc.geyser.translator.protocol.bedrock; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.mc.protocol.data.game.item.component.Filterable; -import com.github.steveice10.mc.protocol.data.game.item.component.WritableBookContent; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundEditBookPacket; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.Filterable; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.WritableBookContent; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundEditBookPacket; import org.cloudburstmc.protocol.bedrock.packet.BookEditPacket; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.type.WrittenBookItem; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockCommandBlockUpdateTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockCommandBlockUpdateTranslator.java index b9561518e..401ece6ca 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockCommandBlockUpdateTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockCommandBlockUpdateTranslator.java @@ -25,13 +25,13 @@ package org.geysermc.geyser.translator.protocol.bedrock; -import com.github.steveice10.mc.protocol.data.game.level.block.CommandBlockMode; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundSetCommandBlockPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundSetCommandMinecartPacket; import org.cloudburstmc.protocol.bedrock.packet.CommandBlockUpdatePacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.CommandBlockMode; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundSetCommandBlockPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundSetCommandMinecartPacket; @Translator(packet = CommandBlockUpdatePacket.class) public class BedrockCommandBlockUpdateTranslator extends PacketTranslator { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockContainerCloseTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockContainerCloseTranslator.java index e2552802f..d675a07e9 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockContainerCloseTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockContainerCloseTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.bedrock; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClosePacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClosePacket; import org.cloudburstmc.protocol.bedrock.packet.ContainerClosePacket; import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.MerchantContainer; 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 8d005e515..c4a00e41f 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 @@ -25,14 +25,6 @@ package org.geysermc.geyser.translator.protocol.bedrock; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.entity.object.Direction; -import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; -import com.github.steveice10.mc.protocol.data.game.entity.player.InteractAction; -import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClickPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.*; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; import org.cloudburstmc.math.vector.Vector3d; @@ -73,11 +65,15 @@ import org.geysermc.geyser.translator.inventory.InventoryTranslator; import org.geysermc.geyser.translator.item.ItemTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; -import org.geysermc.geyser.util.BlockUtils; -import org.geysermc.geyser.util.CooldownUtils; -import org.geysermc.geyser.util.EntityUtils; -import org.geysermc.geyser.util.InteractionResult; -import org.geysermc.geyser.util.InventoryUtils; +import org.geysermc.geyser.util.*; +import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.InteractAction; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerAction; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClickPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.*; import java.util.List; import java.util.concurrent.TimeUnit; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockItemFrameDropItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockItemFrameDropItemTranslator.java index 4a5145ead..dff4631b0 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockItemFrameDropItemTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockItemFrameDropItemTranslator.java @@ -25,15 +25,15 @@ package org.geysermc.geyser.translator.protocol.bedrock; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; -import com.github.steveice10.mc.protocol.data.game.entity.player.InteractAction; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundInteractPacket; import org.cloudburstmc.protocol.bedrock.packet.ItemFrameDropItemPacket; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.ItemFrameEntity; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.InteractAction; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundInteractPacket; /** * Pre-1.16.210: used for both survival and creative item frame item removal diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockLecternUpdateTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockLecternUpdateTranslator.java index 6bac96206..e6d3d4dce 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockLecternUpdateTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockLecternUpdateTranslator.java @@ -25,11 +25,11 @@ package org.geysermc.geyser.translator.protocol.bedrock; -import com.github.steveice10.mc.protocol.data.game.entity.object.Direction; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClosePacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundUseItemOnPacket; +import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClosePacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundUseItemOnPacket; import org.cloudburstmc.protocol.bedrock.packet.LecternUpdatePacket; import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.LecternContainer; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockMobEquipmentTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockMobEquipmentTranslator.java index f5086e29a..030c6580f 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockMobEquipmentTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockMobEquipmentTranslator.java @@ -25,9 +25,9 @@ package org.geysermc.geyser.translator.protocol.bedrock; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundSetCarriedItemPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundUseItemPacket; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundSetCarriedItemPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundUseItemPacket; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId; import org.cloudburstmc.protocol.bedrock.packet.MobEquipmentPacket; import org.geysermc.geyser.inventory.GeyserItemStack; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockMoveEntityAbsoluteTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockMoveEntityAbsoluteTranslator.java index 8a8749e34..f8f31d67f 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockMoveEntityAbsoluteTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockMoveEntityAbsoluteTranslator.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.translator.protocol.bedrock; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.level.ServerboundMoveVehiclePacket; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.packet.MoveEntityAbsolutePacket; import org.geysermc.geyser.entity.EntityDefinitions; @@ -34,6 +33,7 @@ import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.level.ServerboundMoveVehiclePacket; /** * Sent by the client when moving a horse or boat. diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockNetworkStackLatencyTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockNetworkStackLatencyTranslator.java index 412a97e3a..6ca0f3500 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockNetworkStackLatencyTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockNetworkStackLatencyTranslator.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.translator.protocol.bedrock; -import com.github.steveice10.mc.protocol.packet.common.serverbound.ServerboundKeepAlivePacket; import org.cloudburstmc.protocol.bedrock.data.AttributeData; import org.cloudburstmc.protocol.bedrock.packet.NetworkStackLatencyPacket; import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket; @@ -33,6 +32,7 @@ import org.geysermc.geyser.entity.attribute.GeyserAttributeType; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; +import org.geysermc.mcprotocollib.protocol.packet.common.serverbound.ServerboundKeepAlivePacket; import java.util.Collections; import java.util.concurrent.TimeUnit; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockPlayerInputTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockPlayerInputTranslator.java index 1737364ff..beb724ffb 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockPlayerInputTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockPlayerInputTranslator.java @@ -25,8 +25,8 @@ package org.geysermc.geyser.translator.protocol.bedrock; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.level.ServerboundMoveVehiclePacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.level.ServerboundPlayerInputPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.level.ServerboundMoveVehiclePacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.level.ServerboundPlayerInputPacket; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.packet.PlayerInputPacket; import org.geysermc.geyser.entity.EntityDefinitions; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockRequestAbilityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockRequestAbilityTranslator.java index be2b1f28a..d0c29c6a9 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockRequestAbilityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockRequestAbilityTranslator.java @@ -25,8 +25,8 @@ package org.geysermc.geyser.translator.protocol.bedrock; -import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundPlayerAbilitiesPacket; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundPlayerAbilitiesPacket; import org.cloudburstmc.protocol.bedrock.data.Ability; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.packet.RequestAbilityPacket; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockRespawnTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockRespawnTranslator.java index 7c4798f80..878f00443 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockRespawnTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockRespawnTranslator.java @@ -25,8 +25,8 @@ package org.geysermc.geyser.translator.protocol.bedrock; -import com.github.steveice10.mc.protocol.data.game.ClientCommand; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundClientCommandPacket; +import org.geysermc.mcprotocollib.protocol.data.game.ClientCommand; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundClientCommandPacket; import org.cloudburstmc.protocol.bedrock.packet.RespawnPacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockShowCreditsTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockShowCreditsTranslator.java index 3314975ef..06f680ca6 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockShowCreditsTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockShowCreditsTranslator.java @@ -25,8 +25,8 @@ package org.geysermc.geyser.translator.protocol.bedrock; -import com.github.steveice10.mc.protocol.data.game.ClientCommand; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundClientCommandPacket; +import org.geysermc.mcprotocollib.protocol.data.game.ClientCommand; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundClientCommandPacket; import org.cloudburstmc.protocol.bedrock.packet.ShowCreditsPacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockStructureBlockUpdateTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockStructureBlockUpdateTranslator.java index 84b7ffdd2..1434a6d99 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockStructureBlockUpdateTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockStructureBlockUpdateTranslator.java @@ -25,8 +25,6 @@ package org.geysermc.geyser.translator.protocol.bedrock; -import com.github.steveice10.mc.protocol.data.game.inventory.UpdateStructureBlockAction; -import com.github.steveice10.mc.protocol.data.game.inventory.UpdateStructureBlockMode; import org.cloudburstmc.protocol.bedrock.data.structure.StructureBlockType; import org.cloudburstmc.protocol.bedrock.data.structure.StructureEditorData; import org.cloudburstmc.protocol.bedrock.packet.StructureBlockUpdatePacket; @@ -34,6 +32,8 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.util.StructureBlockUtils; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.UpdateStructureBlockAction; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.UpdateStructureBlockMode; @Translator(packet = StructureBlockUpdatePacket.class) public class BedrockStructureBlockUpdateTranslator extends PacketTranslator { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockStructureTemplateDataRequestTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockStructureTemplateDataRequestTranslator.java index 947946f36..026d257ab 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockStructureTemplateDataRequestTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockStructureTemplateDataRequestTranslator.java @@ -25,8 +25,6 @@ package org.geysermc.geyser.translator.protocol.bedrock; -import com.github.steveice10.mc.protocol.data.game.inventory.UpdateStructureBlockAction; -import com.github.steveice10.mc.protocol.data.game.inventory.UpdateStructureBlockMode; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.structure.StructureSettings; import org.cloudburstmc.protocol.bedrock.data.structure.StructureTemplateRequestOperation; @@ -35,6 +33,8 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.util.StructureBlockUtils; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.UpdateStructureBlockAction; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.UpdateStructureBlockMode; /** * Packet used in Bedrock to load structure size into the structure block GUI. It is sent every time the GUI is opened. diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockToggleCrafterSlotRequestTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockToggleCrafterSlotRequestTranslator.java index 5c494cd88..980e8ac00 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockToggleCrafterSlotRequestTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockToggleCrafterSlotRequestTranslator.java @@ -25,12 +25,12 @@ package org.geysermc.geyser.translator.protocol.bedrock; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerSlotStateChangedPacket; import org.cloudburstmc.protocol.bedrock.packet.ToggleCrafterSlotRequestPacket; import org.geysermc.geyser.inventory.CrafterContainer; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerSlotStateChangedPacket; @Translator(packet = ToggleCrafterSlotRequestPacket.class) public class BedrockToggleCrafterSlotRequestTranslator extends PacketTranslator { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/BedrockEntityEventTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/BedrockEntityEventTranslator.java index 17a80aa39..6b7510d8b 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/BedrockEntityEventTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/BedrockEntityEventTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.bedrock.entity; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundSelectTradePacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundSelectTradePacket; import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket; import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.MerchantContainer; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java index 2fd9ce405..887ea3c09 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java @@ -25,13 +25,6 @@ package org.geysermc.geyser.translator.protocol.bedrock.entity.player; -import com.github.steveice10.mc.protocol.data.game.entity.object.Direction; -import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; -import com.github.steveice10.mc.protocol.data.game.entity.player.InteractAction; -import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction; -import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerState; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.*; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.LevelEvent; @@ -57,6 +50,9 @@ import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.util.BlockUtils; import org.geysermc.geyser.util.CooldownUtils; +import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.*; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.*; @Translator(packet = PlayerActionPacket.class) public class BedrockActionTranslator extends PacketTranslator { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockInteractTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockInteractTranslator.java index a45690ab1..20c1b055d 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockInteractTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockInteractTranslator.java @@ -25,12 +25,12 @@ package org.geysermc.geyser.translator.protocol.bedrock.entity.player; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; -import com.github.steveice10.mc.protocol.data.game.entity.player.InteractAction; -import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerState; -import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundInteractPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundPlayerCommandPacket; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.InteractAction; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerState; +import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundInteractPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundPlayerCommandPacket; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityLinkData; import org.cloudburstmc.protocol.bedrock.packet.InteractPacket; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockMovePlayerTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockMovePlayerTranslator.java index d81c0abab..cae12170d 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockMovePlayerTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockMovePlayerTranslator.java @@ -25,10 +25,10 @@ package org.geysermc.geyser.translator.protocol.bedrock.entity.player; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosRotPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerRotPacket; -import com.github.steveice10.packetlib.packet.Packet; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosRotPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerRotPacket; +import org.geysermc.mcprotocollib.network.packet.Packet; import org.cloudburstmc.math.vector.Vector3d; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.packet.MovePlayerPacket; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockRiderJumpTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockRiderJumpTranslator.java index f7ac81219..76b95103e 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockRiderJumpTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockRiderJumpTranslator.java @@ -25,8 +25,8 @@ package org.geysermc.geyser.translator.protocol.bedrock.entity.player; -import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerState; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundPlayerCommandPacket; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerState; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundPlayerCommandPacket; import org.cloudburstmc.protocol.bedrock.packet.RiderJumpPacket; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.living.animal.horse.AbstractHorseEntity; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetDefaultGameTypeTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetDefaultGameTypeTranslator.java index df28f7ca7..aa815fab7 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetDefaultGameTypeTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetDefaultGameTypeTranslator.java @@ -25,13 +25,13 @@ package org.geysermc.geyser.translator.protocol.bedrock.entity.player; -import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; import org.cloudburstmc.protocol.bedrock.packet.SetDefaultGameTypePacket; import org.cloudburstmc.protocol.bedrock.packet.SetPlayerGameTypePacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.util.EntityUtils; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; @Translator(packet = SetDefaultGameTypePacket.class) public class BedrockSetDefaultGameTypeTranslator extends PacketTranslator { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetDifficultyTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetDifficultyTranslator.java index b996a96b1..176f00b8f 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetDifficultyTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetDifficultyTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.bedrock.entity.player; -import com.github.steveice10.mc.protocol.data.game.setting.Difficulty; +import org.geysermc.mcprotocollib.protocol.data.game.setting.Difficulty; import org.cloudburstmc.protocol.bedrock.packet.SetDifficultyPacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetPlayerGameTypeTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetPlayerGameTypeTranslator.java index 2d8d420f8..f00156268 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetPlayerGameTypeTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetPlayerGameTypeTranslator.java @@ -25,12 +25,12 @@ package org.geysermc.geyser.translator.protocol.bedrock.entity.player; -import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; import org.cloudburstmc.protocol.bedrock.packet.SetPlayerGameTypePacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.util.EntityUtils; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; /** * In vanilla Bedrock, if you have operator status, this sets the player's gamemode without confirmation from the server. diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetPlayerInventoryOptionsTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetPlayerInventoryOptionsTranslator.java index 0f07d84da..7e23c2e4c 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetPlayerInventoryOptionsTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetPlayerInventoryOptionsTranslator.java @@ -25,9 +25,9 @@ package org.geysermc.geyser.translator.protocol.bedrock.entity.player; -import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; -import com.github.steveice10.mc.protocol.data.game.inventory.CraftingBookStateType; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundRecipeBookChangeSettingsPacket; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.CraftingBookStateType; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundRecipeBookChangeSettingsPacket; import org.cloudburstmc.protocol.bedrock.data.inventory.InventoryTabLeft; import org.cloudburstmc.protocol.bedrock.data.inventory.InventoryTabRight; import org.cloudburstmc.protocol.bedrock.packet.SetPlayerInventoryOptionsPacket; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/world/BedrockLevelSoundEventTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/world/BedrockLevelSoundEventTranslator.java index ec8a18edb..822d8f6ba 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/world/BedrockLevelSoundEventTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/world/BedrockLevelSoundEventTranslator.java @@ -25,10 +25,10 @@ package org.geysermc.geyser.translator.protocol.bedrock.world; -import com.github.steveice10.mc.protocol.data.game.entity.object.Direction; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundSwingPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundUseItemOnPacket; +import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundSwingPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundUseItemOnPacket; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaAwardStatsTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaAwardStatsTranslator.java index 4f4c2e549..4f0f1f587 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaAwardStatsTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaAwardStatsTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundAwardStatsPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundAwardStatsPacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaBossEventTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaBossEventTranslator.java index 30d6aa017..c1e0b9a3a 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaBossEventTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaBossEventTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundBossEventPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundBossEventPacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.BossBar; import org.geysermc.geyser.translator.protocol.PacketTranslator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaChangeDifficultyTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaChangeDifficultyTranslator.java index 970c49e23..996dc9d84 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaChangeDifficultyTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaChangeDifficultyTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundChangeDifficultyPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundChangeDifficultyPacket; import org.cloudburstmc.protocol.bedrock.packet.SetDifficultyPacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaClientboundRecipesTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaClientboundRecipesTranslator.java index 3fe5abff8..9eb69183d 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaClientboundRecipesTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaClientboundRecipesTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundRecipePacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundRecipePacket; import org.cloudburstmc.protocol.bedrock.packet.UnlockedRecipesPacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaClientboundResourcePackPushPacket.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaClientboundResourcePackPushPacket.java index b84c7a55b..9e7306ab1 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaClientboundResourcePackPushPacket.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaClientboundResourcePackPushPacket.java @@ -25,9 +25,9 @@ package org.geysermc.geyser.translator.protocol.java; -import com.github.steveice10.mc.protocol.data.game.ResourcePackStatus; -import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundResourcePackPushPacket; -import com.github.steveice10.mc.protocol.packet.common.serverbound.ServerboundResourcePackPacket; +import org.geysermc.mcprotocollib.protocol.data.game.ResourcePackStatus; +import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundResourcePackPushPacket; +import org.geysermc.mcprotocollib.protocol.packet.common.serverbound.ServerboundResourcePackPacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCommandsTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCommandsTranslator.java index 9d3351217..706997402 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCommandsTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCommandsTranslator.java @@ -25,11 +25,11 @@ package org.geysermc.geyser.translator.protocol.java; -import com.github.steveice10.mc.protocol.data.game.command.CommandNode; -import com.github.steveice10.mc.protocol.data.game.command.CommandParser; -import com.github.steveice10.mc.protocol.data.game.command.properties.ResourceProperties; -import com.github.steveice10.mc.protocol.data.game.entity.attribute.AttributeType; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundCommandsPacket; +import org.geysermc.mcprotocollib.protocol.data.game.command.CommandNode; +import org.geysermc.mcprotocollib.protocol.data.game.command.CommandParser; +import org.geysermc.mcprotocollib.protocol.data.game.command.properties.ResourceProperties; +import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.AttributeType; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundCommandsPacket; import it.unimi.dsi.fastutil.Hash; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCustomPayloadTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCustomPayloadTranslator.java index 2a7202b0c..f8a21f904 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCustomPayloadTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCustomPayloadTranslator.java @@ -25,13 +25,11 @@ package org.geysermc.geyser.translator.protocol.java; -import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundCustomPayloadPacket; -import com.github.steveice10.mc.protocol.packet.common.serverbound.ServerboundCustomPayloadPacket; import com.google.common.base.Charsets; -import org.cloudburstmc.protocol.bedrock.packet.TransferPacket; -import org.cloudburstmc.protocol.bedrock.packet.UnknownPacket; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; +import org.cloudburstmc.protocol.bedrock.packet.TransferPacket; +import org.cloudburstmc.protocol.bedrock.packet.UnknownPacket; import org.geysermc.cumulus.Forms; import org.geysermc.cumulus.form.Form; import org.geysermc.cumulus.form.util.FormType; @@ -45,6 +43,8 @@ import org.geysermc.geyser.GeyserLogger; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; +import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundCustomPayloadPacket; +import org.geysermc.mcprotocollib.protocol.packet.common.serverbound.ServerboundCustomPayloadPacket; import java.nio.charset.StandardCharsets; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCustomQueryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCustomQueryTranslator.java index 6096af12d..1e448c48e 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCustomQueryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCustomQueryTranslator.java @@ -25,8 +25,8 @@ package org.geysermc.geyser.translator.protocol.java; -import com.github.steveice10.mc.protocol.packet.login.clientbound.ClientboundCustomQueryPacket; -import com.github.steveice10.mc.protocol.packet.login.serverbound.ServerboundCustomQueryAnswerPacket; +import org.geysermc.mcprotocollib.protocol.packet.login.clientbound.ClientboundCustomQueryPacket; +import org.geysermc.mcprotocollib.protocol.packet.login.serverbound.ServerboundCustomQueryAnswerPacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaDisconnectTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaDisconnectTranslator.java index 8bf5ae4ba..2eb08fb92 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaDisconnectTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaDisconnectTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java; -import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundDisconnectPacket; +import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundDisconnectPacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaDisguisedChatTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaDisguisedChatTranslator.java index 2ad45fe52..67bdb6f9a 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaDisguisedChatTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaDisguisedChatTranslator.java @@ -25,11 +25,11 @@ package org.geysermc.geyser.translator.protocol.java; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundDisguisedChatPacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.translator.text.MessageTranslator; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundDisguisedChatPacket; @Translator(packet = ClientboundDisguisedChatPacket.class) public class JavaDisguisedChatTranslator extends PacketTranslator { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaGameProfileTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaGameProfileTranslator.java index 12f96360b..96bab0bfa 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaGameProfileTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaGameProfileTranslator.java @@ -26,8 +26,6 @@ package org.geysermc.geyser.translator.protocol.java; import com.github.steveice10.mc.auth.data.GameProfile; -import com.github.steveice10.mc.protocol.packet.common.serverbound.ServerboundCustomPayloadPacket; -import com.github.steveice10.mc.protocol.packet.login.clientbound.ClientboundGameProfilePacket; import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.entity.type.player.PlayerEntity; import org.geysermc.geyser.session.GeyserSession; @@ -35,6 +33,8 @@ import org.geysermc.geyser.skin.SkinManager; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.util.PluginMessageUtils; +import org.geysermc.mcprotocollib.protocol.packet.common.serverbound.ServerboundCustomPayloadPacket; +import org.geysermc.mcprotocollib.protocol.packet.login.clientbound.ClientboundGameProfilePacket; /** * ClientboundGameProfilePacket triggers protocol change LOGIN -> CONFIGURATION diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaKeepAliveTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaKeepAliveTranslator.java index da8358da2..399c23080 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaKeepAliveTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaKeepAliveTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java; -import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundKeepAlivePacket; +import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundKeepAlivePacket; import org.cloudburstmc.protocol.bedrock.packet.NetworkStackLatencyPacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginDisconnectTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginDisconnectTranslator.java index c0be2c624..e92ae1bbd 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginDisconnectTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginDisconnectTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java; -import com.github.steveice10.mc.protocol.packet.login.clientbound.ClientboundLoginDisconnectPacket; +import org.geysermc.mcprotocollib.protocol.packet.login.clientbound.ClientboundLoginDisconnectPacket; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.TranslatableComponent; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java index ebf99fb65..fe4401dca 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java @@ -25,9 +25,9 @@ package org.geysermc.geyser.translator.protocol.java; -import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerSpawnInfo; -import com.github.steveice10.mc.protocol.packet.common.serverbound.ServerboundCustomPayloadPacket; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundLoginPacket; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerSpawnInfo; +import org.geysermc.mcprotocollib.protocol.packet.common.serverbound.ServerboundCustomPayloadPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundLoginPacket; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.GameRuleData; import org.cloudburstmc.protocol.bedrock.data.LevelEvent; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaPingTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaPingTranslator.java index c966f3abb..fa7175003 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaPingTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaPingTranslator.java @@ -25,8 +25,8 @@ package org.geysermc.geyser.translator.protocol.java; -import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundPingPacket; -import com.github.steveice10.mc.protocol.packet.common.serverbound.ServerboundPongPacket; +import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundPingPacket; +import org.geysermc.mcprotocollib.protocol.packet.common.serverbound.ServerboundPongPacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaPlayerChatTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaPlayerChatTranslator.java index e06182b8d..f8d392dd5 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaPlayerChatTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaPlayerChatTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundPlayerChatPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundPlayerChatPacket; import net.kyori.adventure.text.Component; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaRegistryDataTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaRegistryDataTranslator.java index ddb9c76b7..6af94001e 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaRegistryDataTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaRegistryDataTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java; -import com.github.steveice10.mc.protocol.packet.configuration.clientbound.ClientboundRegistryDataPacket; +import org.geysermc.mcprotocollib.protocol.packet.configuration.clientbound.ClientboundRegistryDataPacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaRespawnTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaRespawnTranslator.java index bfb590247..fe0868253 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaRespawnTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaRespawnTranslator.java @@ -25,8 +25,6 @@ package org.geysermc.geyser.translator.protocol.java; -import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerSpawnInfo; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundRespawnPacket; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.LevelEvent; import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket; @@ -40,6 +38,8 @@ import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.util.ChunkUtils; import org.geysermc.geyser.util.DimensionUtils; import org.geysermc.geyser.util.EntityUtils; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerSpawnInfo; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundRespawnPacket; @Translator(packet = ClientboundRespawnPacket.class) public class JavaRespawnTranslator extends PacketTranslator { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaSelectAdvancementsTabTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaSelectAdvancementsTabTranslator.java index e33863244..04c018472 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaSelectAdvancementsTabTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaSelectAdvancementsTabTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundSelectAdvancementsTabPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundSelectAdvancementsTabPacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.AdvancementsCache; import org.geysermc.geyser.translator.protocol.PacketTranslator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaSystemChatTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaSystemChatTranslator.java index e400773c8..0a0f2832c 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaSystemChatTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaSystemChatTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundSystemChatPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundSystemChatPacket; import net.kyori.adventure.text.TranslatableComponent; import org.cloudburstmc.protocol.bedrock.packet.TextPacket; import org.geysermc.geyser.session.GeyserSession; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateAdvancementsTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateAdvancementsTranslator.java index a7efdbefa..8bf520da0 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateAdvancementsTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateAdvancementsTranslator.java @@ -25,8 +25,8 @@ package org.geysermc.geyser.translator.protocol.java; -import com.github.steveice10.mc.protocol.data.game.advancement.Advancement; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundUpdateAdvancementsPacket; +import org.geysermc.mcprotocollib.protocol.data.game.advancement.Advancement; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundUpdateAdvancementsPacket; import org.cloudburstmc.protocol.bedrock.packet.ToastRequestPacket; import org.geysermc.geyser.level.GeyserAdvancement; import org.geysermc.geyser.session.GeyserSession; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java index 20b223248..0db62f21d 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java @@ -25,15 +25,6 @@ package org.geysermc.geyser.translator.protocol.java; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; -import com.github.steveice10.mc.protocol.data.game.recipe.Recipe; -import com.github.steveice10.mc.protocol.data.game.recipe.RecipeType; -import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapedRecipeData; -import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapelessRecipeData; -import com.github.steveice10.mc.protocol.data.game.recipe.data.SmithingTransformRecipeData; -import com.github.steveice10.mc.protocol.data.game.recipe.data.StoneCuttingRecipeData; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundUpdateRecipesPacket; import it.unimi.dsi.fastutil.ints.*; import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; @@ -48,11 +39,7 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.descriptor.ItemTagDescri import org.cloudburstmc.protocol.bedrock.packet.CraftingDataPacket; import org.cloudburstmc.protocol.bedrock.packet.TrimDataPacket; import org.geysermc.geyser.GeyserImpl; -import org.geysermc.geyser.inventory.recipe.GeyserRecipe; -import org.geysermc.geyser.inventory.recipe.GeyserShapedRecipe; -import org.geysermc.geyser.inventory.recipe.GeyserShapelessRecipe; -import org.geysermc.geyser.inventory.recipe.GeyserStonecutterData; -import org.geysermc.geyser.inventory.recipe.TrimRecipe; +import org.geysermc.geyser.inventory.recipe.*; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; @@ -60,6 +47,15 @@ import org.geysermc.geyser.translator.item.ItemTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.util.InventoryUtils; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.recipe.Ingredient; +import org.geysermc.mcprotocollib.protocol.data.game.recipe.Recipe; +import org.geysermc.mcprotocollib.protocol.data.game.recipe.RecipeType; +import org.geysermc.mcprotocollib.protocol.data.game.recipe.data.ShapedRecipeData; +import org.geysermc.mcprotocollib.protocol.data.game.recipe.data.ShapelessRecipeData; +import org.geysermc.mcprotocollib.protocol.data.game.recipe.data.SmithingTransformRecipeData; +import org.geysermc.mcprotocollib.protocol.data.game.recipe.data.StoneCuttingRecipeData; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundUpdateRecipesPacket; import java.util.*; import java.util.stream.Collectors; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateTagsTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateTagsTranslator.java index ae59cf0f8..4df73b4c2 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateTagsTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateTagsTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java; -import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundUpdateTagsPacket; +import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundUpdateTagsPacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaAnimateTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaAnimateTranslator.java index 1aa147314..8bd4bad10 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaAnimateTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaAnimateTranslator.java @@ -25,8 +25,6 @@ package org.geysermc.geyser.translator.protocol.java.entity; -import com.github.steveice10.mc.protocol.data.game.entity.player.Animation; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundAnimatePacket; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.packet.AnimateEntityPacket; import org.cloudburstmc.protocol.bedrock.packet.AnimatePacket; @@ -36,6 +34,8 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.util.DimensionUtils; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Animation; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundAnimatePacket; import java.util.Optional; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaDamageEventTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaDamageEventTranslator.java index 19a6e25c0..9d491f92c 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaDamageEventTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaDamageEventTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.entity; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundDamageEventPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundDamageEventPacket; import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType; import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket; import org.geysermc.geyser.entity.type.Entity; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaEntityEventTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaEntityEventTranslator.java index 4b1483bbf..fbabd4afa 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaEntityEventTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaEntityEventTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.entity; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundEntityEventPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundEntityEventPacket; import org.cloudburstmc.protocol.bedrock.data.ParticleType; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaMoveEntityPosRotTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaMoveEntityPosRotTranslator.java index 2ad1503a8..31d46f096 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaMoveEntityPosRotTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaMoveEntityPosRotTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.entity; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundMoveEntityPosRotPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundMoveEntityPosRotPacket; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaMoveEntityPosTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaMoveEntityPosTranslator.java index cbb3cecc2..638828a2b 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaMoveEntityPosTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaMoveEntityPosTranslator.java @@ -25,11 +25,11 @@ package org.geysermc.geyser.translator.protocol.java.entity; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundMoveEntityPosPacket; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundMoveEntityPosPacket; @Translator(packet = ClientboundMoveEntityPosPacket.class) public class JavaMoveEntityPosTranslator extends PacketTranslator { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaMoveEntityRotTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaMoveEntityRotTranslator.java index 75d4c6189..b48b801f3 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaMoveEntityRotTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaMoveEntityRotTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.entity; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundMoveEntityRotPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundMoveEntityRotPacket; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaMoveVehicleTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaMoveVehicleTranslator.java index bdb159633..111b72c4f 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaMoveVehicleTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaMoveVehicleTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.entity; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundMoveVehiclePacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundMoveVehiclePacket; import org.cloudburstmc.math.vector.Vector3f; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.session.GeyserSession; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaRemoveEntitiesTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaRemoveEntitiesTranslator.java index 776cfb4d7..0148b1e05 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaRemoveEntitiesTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaRemoveEntitiesTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.entity; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundRemoveEntitiesPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundRemoveEntitiesPacket; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaRemoveMobEffectTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaRemoveMobEffectTranslator.java index 52b771caa..dafa5aec1 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaRemoveMobEffectTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaRemoveMobEffectTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.entity; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundRemoveMobEffectPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundRemoveMobEffectPacket; import org.cloudburstmc.protocol.bedrock.packet.MobEffectPacket; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.session.GeyserSession; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaRotateHeadTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaRotateHeadTranslator.java index 65e529792..dc03a76e9 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaRotateHeadTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaRotateHeadTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.entity; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundRotateHeadPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundRotateHeadPacket; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEntityDataTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEntityDataTranslator.java index 54c14f7f0..2dc780c66 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEntityDataTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEntityDataTranslator.java @@ -25,13 +25,13 @@ package org.geysermc.geyser.translator.protocol.java.entity; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundSetEntityDataPacket; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundSetEntityDataPacket; @Translator(packet = ClientboundSetEntityDataPacket.class) public class JavaSetEntityDataTranslator extends PacketTranslator { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEntityLinkTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEntityLinkTranslator.java index 720f03779..d595e928f 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEntityLinkTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEntityLinkTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.entity; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundSetEntityLinkPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundSetEntityLinkPacket; import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEntityMotionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEntityMotionTranslator.java index 62e1d200e..6bbc59e8b 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEntityMotionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEntityMotionTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.entity; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundSetEntityMotionPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundSetEntityMotionPacket; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.packet.SetEntityMotionPacket; import org.geysermc.geyser.entity.type.Entity; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEquipmentTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEquipmentTranslator.java index 7c93725e0..cc71cca0a 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEquipmentTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEquipmentTranslator.java @@ -25,9 +25,9 @@ package org.geysermc.geyser.translator.protocol.java.entity; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.Equipment; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundSetEquipmentPacket; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Equipment; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundSetEquipmentPacket; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.LivingEntity; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetPassengersTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetPassengersTranslator.java index 14d6127ad..9895a248c 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetPassengersTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetPassengersTranslator.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.translator.protocol.java.entity; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundSetPassengersPacket; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityLinkData; import org.cloudburstmc.protocol.bedrock.packet.SetEntityLinkPacket; @@ -35,6 +34,7 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.util.EntityUtils; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundSetPassengersPacket; import java.util.ArrayList; import java.util.List; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSoundEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSoundEntityTranslator.java index 68f310db4..d6e70b3f3 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSoundEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSoundEntityTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.entity; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundSoundEntityPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundSoundEntityPacket; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaTakeItemEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaTakeItemEntityTranslator.java index cc2b4b030..7722459d4 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaTakeItemEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaTakeItemEntityTranslator.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.translator.protocol.java.entity; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundTakeItemEntityPacket; import org.cloudburstmc.protocol.bedrock.data.LevelEvent; import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket; import org.cloudburstmc.protocol.bedrock.packet.TakeItemEntityPacket; @@ -34,6 +33,7 @@ import org.geysermc.geyser.entity.type.ExpOrbEntity; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundTakeItemEntityPacket; /** * This packet is called whenever a player picks up an item. diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaTeleportEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaTeleportEntityTranslator.java index 9925bf432..8b3a06d7c 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaTeleportEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaTeleportEntityTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.entity; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundTeleportEntityPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundTeleportEntityPacket; import org.cloudburstmc.math.vector.Vector3f; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.session.GeyserSession; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaUpdateAttributesTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaUpdateAttributesTranslator.java index a42f2d5dd..31c9c7df3 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaUpdateAttributesTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaUpdateAttributesTranslator.java @@ -25,12 +25,12 @@ package org.geysermc.geyser.translator.protocol.java.entity; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundUpdateAttributesPacket; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.LivingEntity; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundUpdateAttributesPacket; @Translator(packet = ClientboundUpdateAttributesPacket.class) public class JavaUpdateAttributesTranslator extends PacketTranslator { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaUpdateMobEffectTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaUpdateMobEffectTranslator.java index e56a272ab..7638df8be 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaUpdateMobEffectTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaUpdateMobEffectTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.entity; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundUpdateMobEffectPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundUpdateMobEffectPacket; import org.cloudburstmc.protocol.bedrock.packet.MobEffectPacket; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.session.GeyserSession; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaBlockChangedAckTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaBlockChangedAckTranslator.java index 523d0fdc4..c48c040a2 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaBlockChangedAckTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaBlockChangedAckTranslator.java @@ -25,10 +25,10 @@ package org.geysermc.geyser.translator.protocol.java.entity.player; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.player.ClientboundBlockChangedAckPacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.player.ClientboundBlockChangedAckPacket; @Translator(packet = ClientboundBlockChangedAckPacket.class) public class JavaBlockChangedAckTranslator extends PacketTranslator { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerAbilitiesTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerAbilitiesTranslator.java index 783f4e824..6f41603a4 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerAbilitiesTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerAbilitiesTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.entity.player; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.player.ClientboundPlayerAbilitiesPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.player.ClientboundPlayerAbilitiesPacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerCombatKillTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerCombatKillTranslator.java index 4b0cafed3..6f719b762 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerCombatKillTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerCombatKillTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.entity.player; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.player.ClientboundPlayerCombatKillPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.player.ClientboundPlayerCombatKillPacket; import org.cloudburstmc.protocol.bedrock.packet.DeathInfoPacket; import net.kyori.adventure.text.Component; import org.geysermc.geyser.session.GeyserSession; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerInfoRemoveTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerInfoRemoveTranslator.java index f5c4b1398..60a245111 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerInfoRemoveTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerInfoRemoveTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.entity.player; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundPlayerInfoRemovePacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundPlayerInfoRemovePacket; import org.cloudburstmc.protocol.bedrock.packet.PlayerListPacket; import org.geysermc.geyser.entity.type.player.PlayerEntity; import org.geysermc.geyser.session.GeyserSession; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerInfoUpdateTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerInfoUpdateTranslator.java index 3debb7f5f..f5ea4c08d 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerInfoUpdateTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerInfoUpdateTranslator.java @@ -26,9 +26,6 @@ package org.geysermc.geyser.translator.protocol.java.entity.player; import com.github.steveice10.mc.auth.data.GameProfile; -import com.github.steveice10.mc.protocol.data.game.PlayerListEntry; -import com.github.steveice10.mc.protocol.data.game.PlayerListEntryAction; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundPlayerInfoUpdatePacket; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.packet.PlayerListPacket; @@ -38,6 +35,9 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.skin.SkinManager; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; +import org.geysermc.mcprotocollib.protocol.data.game.PlayerListEntry; +import org.geysermc.mcprotocollib.protocol.data.game.PlayerListEntryAction; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundPlayerInfoUpdatePacket; import java.util.ArrayList; import java.util.List; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerLookAtTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerLookAtTranslator.java index 7814a6719..b1413542b 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerLookAtTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerLookAtTranslator.java @@ -25,12 +25,12 @@ package org.geysermc.geyser.translator.protocol.java.entity.player; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.player.ClientboundPlayerLookAtPacket; import org.cloudburstmc.math.vector.Vector3f; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.util.MathUtils; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.player.ClientboundPlayerLookAtPacket; @Translator(packet = ClientboundPlayerLookAtPacket.class) public class JavaPlayerLookAtTranslator extends PacketTranslator { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerPositionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerPositionTranslator.java index f2c566a23..413833acf 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerPositionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerPositionTranslator.java @@ -25,10 +25,10 @@ package org.geysermc.geyser.translator.protocol.java.entity.player; -import com.github.steveice10.mc.protocol.data.game.entity.player.PositionElement; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.player.ClientboundPlayerPositionPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.level.ServerboundAcceptTeleportationPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosRotPacket; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PositionElement; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.player.ClientboundPlayerPositionPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.level.ServerboundAcceptTeleportationPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosRotPacket; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.packet.ChunkRadiusUpdatedPacket; import org.cloudburstmc.protocol.bedrock.packet.MovePlayerPacket; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaSetCarriedItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaSetCarriedItemTranslator.java index 97a9e0aae..e590b5658 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaSetCarriedItemTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaSetCarriedItemTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.entity.player; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.player.ClientboundSetCarriedItemPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.player.ClientboundSetCarriedItemPacket; import org.cloudburstmc.protocol.bedrock.packet.PlayerHotbarPacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaSetExperienceTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaSetExperienceTranslator.java index 80dd08eaa..3e3550415 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaSetExperienceTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaSetExperienceTranslator.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.translator.protocol.java.entity.player; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.player.ClientboundSetExperiencePacket; import org.cloudburstmc.protocol.bedrock.data.AttributeData; import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket; import org.geysermc.geyser.entity.attribute.GeyserAttributeType; @@ -33,6 +32,7 @@ import org.geysermc.geyser.entity.type.player.SessionPlayerEntity; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.player.ClientboundSetExperiencePacket; import java.util.Arrays; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaSetHealthTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaSetHealthTranslator.java index decf910ca..1f8992e54 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaSetHealthTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaSetHealthTranslator.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.translator.protocol.java.entity.player; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.player.ClientboundSetHealthPacket; import org.cloudburstmc.protocol.bedrock.data.AttributeData; import org.cloudburstmc.protocol.bedrock.packet.RespawnPacket; import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket; @@ -34,6 +33,7 @@ import org.geysermc.geyser.entity.type.player.SessionPlayerEntity; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.player.ClientboundSetHealthPacket; import java.util.List; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/spawn/JavaAddEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/spawn/JavaAddEntityTranslator.java index e058594c3..572d233d0 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/spawn/JavaAddEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/spawn/JavaAddEntityTranslator.java @@ -25,13 +25,13 @@ package org.geysermc.geyser.translator.protocol.java.entity.spawn; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose; -import com.github.steveice10.mc.protocol.data.game.entity.object.Direction; -import com.github.steveice10.mc.protocol.data.game.entity.object.FallingBlockData; -import com.github.steveice10.mc.protocol.data.game.entity.object.ProjectileData; -import com.github.steveice10.mc.protocol.data.game.entity.object.WardenData; -import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.spawn.ClientboundAddEntityPacket; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose; +import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction; +import org.geysermc.mcprotocollib.protocol.data.game.entity.object.FallingBlockData; +import org.geysermc.mcprotocollib.protocol.data.game.entity.object.ProjectileData; +import org.geysermc.mcprotocollib.protocol.data.game.entity.object.WardenData; +import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.spawn.ClientboundAddEntityPacket; import org.cloudburstmc.math.vector.Vector3f; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.entity.EntityDefinition; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/spawn/JavaAddExperienceOrbTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/spawn/JavaAddExperienceOrbTranslator.java index 2d5e8fb08..8f37eb4d4 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/spawn/JavaAddExperienceOrbTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/spawn/JavaAddExperienceOrbTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.entity.spawn; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.spawn.ClientboundAddExperienceOrbPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.spawn.ClientboundAddExperienceOrbPacket; import org.cloudburstmc.math.vector.Vector3f; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.ExpOrbEntity; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerCloseTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerCloseTranslator.java index 9f687f046..c5786d9aa 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerCloseTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerCloseTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.inventory; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.inventory.ClientboundContainerClosePacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.inventory.ClientboundContainerClosePacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerSetContentTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerSetContentTranslator.java index 2f8204871..44bd7171f 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerSetContentTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerSetContentTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.inventory; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.inventory.ClientboundContainerSetContentPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.inventory.ClientboundContainerSetContentPacket; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserLogger; import org.geysermc.geyser.inventory.GeyserItemStack; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerSetDataTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerSetDataTranslator.java index 923b10a26..0b8d8c5ab 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerSetDataTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerSetDataTranslator.java @@ -25,13 +25,13 @@ package org.geysermc.geyser.translator.protocol.java.inventory; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.inventory.ClientboundContainerSetDataPacket; import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.inventory.InventoryTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.util.InventoryUtils; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.inventory.ClientboundContainerSetDataPacket; @Translator(packet = ClientboundContainerSetDataPacket.class) public class JavaContainerSetDataTranslator extends PacketTranslator { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerSetSlotTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerSetSlotTranslator.java index 594c99291..4372b5ea5 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerSetSlotTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerSetSlotTranslator.java @@ -25,9 +25,9 @@ package org.geysermc.geyser.translator.protocol.java.inventory; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.inventory.ClientboundContainerSetSlotPacket; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.recipe.Ingredient; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.inventory.ClientboundContainerSetSlotPacket; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.ShapedRecipeData; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaHorseScreenOpenTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaHorseScreenOpenTranslator.java index d2abcb5e3..23b79ba67 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaHorseScreenOpenTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaHorseScreenOpenTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.inventory; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.inventory.ClientboundHorseScreenOpenPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.inventory.ClientboundHorseScreenOpenPacket; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; 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 68d2bcab3..970061436 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 @@ -25,9 +25,9 @@ package org.geysermc.geyser.translator.protocol.java.inventory; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.inventory.VillagerTrade; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.inventory.ClientboundMerchantOffersPacket; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.VillagerTrade; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.inventory.ClientboundMerchantOffersPacket; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaOpenBookTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaOpenBookTranslator.java index 24b964b7c..539cce06d 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaOpenBookTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaOpenBookTranslator.java @@ -25,9 +25,6 @@ package org.geysermc.geyser.translator.protocol.java.inventory; -import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.inventory.ClientboundOpenBookPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClosePacket; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.LecternContainer; @@ -38,6 +35,9 @@ import org.geysermc.geyser.translator.inventory.InventoryTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.util.InventoryUtils; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.inventory.ClientboundOpenBookPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClosePacket; import java.util.Objects; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaOpenScreenTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaOpenScreenTranslator.java index 1d0b4bf63..31894339c 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaOpenScreenTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaOpenScreenTranslator.java @@ -25,9 +25,9 @@ package org.geysermc.geyser.translator.protocol.java.inventory; -import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.inventory.ClientboundOpenScreenPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClosePacket; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.inventory.ClientboundOpenScreenPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClosePacket; import net.kyori.adventure.text.Component; import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.network.GameProtocol; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockDestructionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockDestructionTranslator.java index 2fdba716b..1b23066cc 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockDestructionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockDestructionTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.level; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundBlockDestructionPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundBlockDestructionPacket; import org.cloudburstmc.protocol.bedrock.data.LevelEvent; import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket; import org.geysermc.geyser.registry.BlockRegistries; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEntityDataTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEntityDataTranslator.java index 325bae593..ca746f79b 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEntityDataTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEntityDataTranslator.java @@ -25,9 +25,6 @@ package org.geysermc.geyser.translator.protocol.java.level; -import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; -import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundBlockEntityDataPacket; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import org.cloudburstmc.math.vector.Vector3i; @@ -46,6 +43,9 @@ import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.util.BlockEntityUtils; import org.geysermc.geyser.util.StructureBlockUtils; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundBlockEntityDataPacket; @Translator(packet = ClientboundBlockEntityDataPacket.class) public class JavaBlockEntityDataTranslator extends PacketTranslator { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEventTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEventTranslator.java index 28fd2401b..8f6c69a29 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEventTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEventTranslator.java @@ -25,8 +25,8 @@ package org.geysermc.geyser.translator.protocol.java.level; -import com.github.steveice10.mc.protocol.data.game.level.block.value.*; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundBlockEventPacket; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.*; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundBlockEventPacket; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockUpdateTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockUpdateTranslator.java index 4ccc2b4d4..ac8bd8eb0 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockUpdateTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockUpdateTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.level; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundBlockUpdatePacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundBlockUpdatePacket; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEventPacket; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaChunkBatchFinishedTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaChunkBatchFinishedTranslator.java index 115222c6c..c93ebd530 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaChunkBatchFinishedTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaChunkBatchFinishedTranslator.java @@ -25,8 +25,8 @@ package org.geysermc.geyser.translator.protocol.java.level; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundChunkBatchFinishedPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.level.ServerboundChunkBatchReceivedPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundChunkBatchFinishedPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.level.ServerboundChunkBatchReceivedPacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaCooldownTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaCooldownTranslator.java index 4249be6fc..8e07a7d89 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaCooldownTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaCooldownTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.level; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundCooldownPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundCooldownPacket; import org.cloudburstmc.protocol.bedrock.packet.PlayerStartItemCooldownPacket; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.Item; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaExplodeTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaExplodeTranslator.java index c5dba39ae..7b6d4e264 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaExplodeTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaExplodeTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.level; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundExplodePacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundExplodePacket; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaForgetLevelChunkTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaForgetLevelChunkTranslator.java index 4cc0af6e7..b0abe0f59 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaForgetLevelChunkTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaForgetLevelChunkTranslator.java @@ -25,12 +25,12 @@ package org.geysermc.geyser.translator.protocol.java.level; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundForgetLevelChunkPacket; import org.cloudburstmc.math.vector.Vector3i; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.util.ChunkUtils; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundForgetLevelChunkPacket; import java.util.ArrayList; import java.util.Iterator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaGameEventTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaGameEventTranslator.java index f2d60fe34..3aa343cf5 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaGameEventTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaGameEventTranslator.java @@ -25,14 +25,14 @@ package org.geysermc.geyser.translator.protocol.java.level; -import com.github.steveice10.mc.protocol.data.game.ClientCommand; -import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; -import com.github.steveice10.mc.protocol.data.game.level.notify.EnterCreditsValue; -import com.github.steveice10.mc.protocol.data.game.level.notify.RainStrengthValue; -import com.github.steveice10.mc.protocol.data.game.level.notify.RespawnScreenValue; -import com.github.steveice10.mc.protocol.data.game.level.notify.ThunderStrengthValue; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundGameEventPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundClientCommandPacket; +import org.geysermc.mcprotocollib.protocol.data.game.ClientCommand; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; +import org.geysermc.mcprotocollib.protocol.data.game.level.notify.EnterCreditsValue; +import org.geysermc.mcprotocollib.protocol.data.game.level.notify.RainStrengthValue; +import org.geysermc.mcprotocollib.protocol.data.game.level.notify.RespawnScreenValue; +import org.geysermc.mcprotocollib.protocol.data.game.level.notify.ThunderStrengthValue; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundGameEventPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundClientCommandPacket; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.GameRuleData; import org.cloudburstmc.protocol.bedrock.data.LevelEvent; 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 1e6534130..4fd581d84 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 @@ -25,26 +25,12 @@ package org.geysermc.geyser.translator.protocol.java.level; -import com.github.steveice10.mc.protocol.data.game.chunk.BitStorage; -import com.github.steveice10.mc.protocol.data.game.chunk.ChunkSection; -import com.github.steveice10.mc.protocol.data.game.chunk.DataPalette; -import com.github.steveice10.mc.protocol.data.game.chunk.palette.GlobalPalette; -import com.github.steveice10.mc.protocol.data.game.chunk.palette.Palette; -import com.github.steveice10.mc.protocol.data.game.chunk.palette.SingletonPalette; -import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityInfo; -import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundLevelChunkWithLightPacket; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufOutputStream; import io.netty.buffer.Unpooled; -import it.unimi.dsi.fastutil.ints.IntArrayList; -import it.unimi.dsi.fastutil.ints.IntImmutableList; -import it.unimi.dsi.fastutil.ints.IntList; -import it.unimi.dsi.fastutil.ints.IntLists; -import it.unimi.dsi.fastutil.ints.IntOpenHashSet; -import it.unimi.dsi.fastutil.ints.IntSet; +import it.unimi.dsi.fastutil.ints.*; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NBTOutputStream; @@ -73,15 +59,22 @@ import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.util.BlockEntityUtils; import org.geysermc.geyser.util.ChunkUtils; import org.geysermc.geyser.util.DimensionUtils; +import org.geysermc.mcprotocollib.protocol.data.game.chunk.BitStorage; +import org.geysermc.mcprotocollib.protocol.data.game.chunk.ChunkSection; +import org.geysermc.mcprotocollib.protocol.data.game.chunk.DataPalette; +import org.geysermc.mcprotocollib.protocol.data.game.chunk.palette.GlobalPalette; +import org.geysermc.mcprotocollib.protocol.data.game.chunk.palette.Palette; +import org.geysermc.mcprotocollib.protocol.data.game.chunk.palette.SingletonPalette; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityInfo; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundLevelChunkWithLightPacket; import java.io.IOException; import java.util.BitSet; import java.util.List; import java.util.Map; -import static org.geysermc.geyser.util.ChunkUtils.EMPTY_BLOCK_STORAGE; -import static org.geysermc.geyser.util.ChunkUtils.EMPTY_CHUNK_SECTION_SIZE; -import static org.geysermc.geyser.util.ChunkUtils.indexYZXtoXZY; +import static org.geysermc.geyser.util.ChunkUtils.*; @Translator(packet = ClientboundLevelChunkWithLightPacket.class) public class JavaLevelChunkWithLightTranslator extends PacketTranslator { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelEventTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelEventTranslator.java index 843f3d514..cb8a8e60f 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelEventTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelEventTranslator.java @@ -25,9 +25,9 @@ package org.geysermc.geyser.translator.protocol.java.level; -import com.github.steveice10.mc.protocol.data.game.entity.object.Direction; -import com.github.steveice10.mc.protocol.data.game.level.event.*; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundLevelEventPacket; +import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction; +import org.geysermc.mcprotocollib.protocol.data.game.level.event.*; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundLevelEventPacket; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelParticlesTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelParticlesTranslator.java index 7d9b81d29..bedddbc6e 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelParticlesTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelParticlesTranslator.java @@ -25,15 +25,15 @@ package org.geysermc.geyser.translator.protocol.java.level; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.level.particle.BlockParticleData; -import com.github.steveice10.mc.protocol.data.game.level.particle.DustParticleData; -import com.github.steveice10.mc.protocol.data.game.level.particle.ItemParticleData; -import com.github.steveice10.mc.protocol.data.game.level.particle.Particle; -import com.github.steveice10.mc.protocol.data.game.level.particle.VibrationParticleData; -import com.github.steveice10.mc.protocol.data.game.level.particle.positionsource.BlockPositionSource; -import com.github.steveice10.mc.protocol.data.game.level.particle.positionsource.EntityPositionSource; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundLevelParticlesPacket; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.level.particle.BlockParticleData; +import org.geysermc.mcprotocollib.protocol.data.game.level.particle.DustParticleData; +import org.geysermc.mcprotocollib.protocol.data.game.level.particle.ItemParticleData; +import org.geysermc.mcprotocollib.protocol.data.game.level.particle.Particle; +import org.geysermc.mcprotocollib.protocol.data.game.level.particle.VibrationParticleData; +import org.geysermc.mcprotocollib.protocol.data.game.level.particle.positionsource.BlockPositionSource; +import org.geysermc.mcprotocollib.protocol.data.game.level.particle.positionsource.EntityPositionSource; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundLevelParticlesPacket; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.math.vector.Vector3f; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaMapItemDataTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaMapItemDataTranslator.java index 01b0f324f..1591b4952 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaMapItemDataTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaMapItemDataTranslator.java @@ -25,9 +25,9 @@ package org.geysermc.geyser.translator.protocol.java.level; -import com.github.steveice10.mc.protocol.data.game.level.map.MapData; -import com.github.steveice10.mc.protocol.data.game.level.map.MapIcon; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundMapItemDataPacket; +import org.geysermc.mcprotocollib.protocol.data.game.level.map.MapData; +import org.geysermc.mcprotocollib.protocol.data.game.level.map.MapIcon; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundMapItemDataPacket; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.MapDecoration; import org.cloudburstmc.protocol.bedrock.data.MapTrackedObject; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaOpenSignEditorTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaOpenSignEditorTranslator.java index d044ac034..99a32c0c1 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaOpenSignEditorTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaOpenSignEditorTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.level; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundOpenSignEditorPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundOpenSignEditorPacket; import org.cloudburstmc.protocol.bedrock.packet.OpenSignPacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSectionBlocksUpdateTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSectionBlocksUpdateTranslator.java index abc9a6c21..a52bb33b0 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSectionBlocksUpdateTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSectionBlocksUpdateTranslator.java @@ -25,8 +25,8 @@ package org.geysermc.geyser.translator.protocol.java.level; -import com.github.steveice10.mc.protocol.data.game.level.block.BlockChangeEntry; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundSectionBlocksUpdatePacket; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockChangeEntry; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundSectionBlocksUpdatePacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSetChunkCacheCenterTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSetChunkCacheCenterTranslator.java index baec29d47..e75b6c022 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSetChunkCacheCenterTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSetChunkCacheCenterTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.level; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundSetChunkCacheCenterPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundSetChunkCacheCenterPacket; import org.cloudburstmc.math.vector.Vector3i; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSetChunkCacheRadiusTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSetChunkCacheRadiusTranslator.java index 3a0a77cc0..59402325c 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSetChunkCacheRadiusTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSetChunkCacheRadiusTranslator.java @@ -25,10 +25,10 @@ package org.geysermc.geyser.translator.protocol.java.level; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundSetChunkCacheRadiusPacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundSetChunkCacheRadiusPacket; @Translator(packet = ClientboundSetChunkCacheRadiusPacket.class) public class JavaSetChunkCacheRadiusTranslator extends PacketTranslator { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSetDefaultSpawnPositionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSetDefaultSpawnPositionTranslator.java index 9662fdd81..da751419e 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSetDefaultSpawnPositionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSetDefaultSpawnPositionTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.level; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundSetDefaultSpawnPositionPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundSetDefaultSpawnPositionPacket; import org.cloudburstmc.protocol.bedrock.packet.SetSpawnPositionPacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSetTimeTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSetTimeTranslator.java index b86b4247c..1e398ad9b 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSetTimeTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSetTimeTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.level; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundSetTimePacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundSetTimePacket; import org.cloudburstmc.protocol.bedrock.packet.SetTimePacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSoundTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSoundTranslator.java index ceb2d989d..ad07d8537 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSoundTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSoundTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.level; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundSoundPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundSoundPacket; import org.cloudburstmc.math.vector.Vector3f; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaStopSoundTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaStopSoundTranslator.java index 7320b7637..99e076ad2 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaStopSoundTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaStopSoundTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.level; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundStopSoundPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundStopSoundPacket; import org.cloudburstmc.protocol.bedrock.packet.StopSoundPacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/border/JavaInitializeBorderTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/border/JavaInitializeBorderTranslator.java index 857997170..9f1f5b434 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/border/JavaInitializeBorderTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/border/JavaInitializeBorderTranslator.java @@ -25,12 +25,12 @@ package org.geysermc.geyser.translator.protocol.java.level.border; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.border.ClientboundInitializeBorderPacket; import org.cloudburstmc.math.vector.Vector2d; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.WorldBorder; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.border.ClientboundInitializeBorderPacket; @Translator(packet = ClientboundInitializeBorderPacket.class) public class JavaInitializeBorderTranslator extends PacketTranslator { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/border/JavaSetBorderCenterTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/border/JavaSetBorderCenterTranslator.java index ebcef08a7..28f7a6faa 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/border/JavaSetBorderCenterTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/border/JavaSetBorderCenterTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.level.border; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.border.ClientboundSetBorderCenterPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.border.ClientboundSetBorderCenterPacket; import org.cloudburstmc.math.vector.Vector2d; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.WorldBorder; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/border/JavaSetBorderLerpSizeTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/border/JavaSetBorderLerpSizeTranslator.java index a41c90f04..b676523c9 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/border/JavaSetBorderLerpSizeTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/border/JavaSetBorderLerpSizeTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.level.border; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.border.ClientboundSetBorderLerpSizePacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.border.ClientboundSetBorderLerpSizePacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.WorldBorder; import org.geysermc.geyser.translator.protocol.PacketTranslator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/border/JavaSetBorderSizeTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/border/JavaSetBorderSizeTranslator.java index 51cd17278..deec4b7a2 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/border/JavaSetBorderSizeTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/border/JavaSetBorderSizeTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.level.border; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.border.ClientboundSetBorderSizePacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.border.ClientboundSetBorderSizePacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.WorldBorder; import org.geysermc.geyser.translator.protocol.PacketTranslator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/border/JavaSetBorderWarningDelayTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/border/JavaSetBorderWarningDelayTranslator.java index 912ca9a09..e92ab34ad 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/border/JavaSetBorderWarningDelayTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/border/JavaSetBorderWarningDelayTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.level.border; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.border.ClientboundSetBorderWarningDelayPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.border.ClientboundSetBorderWarningDelayPacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.WorldBorder; import org.geysermc.geyser.translator.protocol.PacketTranslator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/border/JavaSetBorderWarningDistanceTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/border/JavaSetBorderWarningDistanceTranslator.java index 14badb565..4d862163e 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/border/JavaSetBorderWarningDistanceTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/border/JavaSetBorderWarningDistanceTranslator.java @@ -25,11 +25,11 @@ package org.geysermc.geyser.translator.protocol.java.level.border; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.border.ClientboundSetBorderWarningDistancePacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.WorldBorder; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.border.ClientboundSetBorderWarningDistancePacket; @Translator(packet = ClientboundSetBorderWarningDistancePacket.class) public class JavaSetBorderWarningDistanceTranslator extends PacketTranslator { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaResetScorePacket.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaResetScorePacket.java index 01b4fddea..e8d307c90 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaResetScorePacket.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaResetScorePacket.java @@ -25,8 +25,6 @@ package org.geysermc.geyser.translator.protocol.java.scoreboard; -import com.github.steveice10.mc.protocol.data.game.scoreboard.ScoreboardPosition; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.scoreboard.ClientboundResetScorePacket; import org.geysermc.geyser.scoreboard.Objective; import org.geysermc.geyser.scoreboard.Scoreboard; import org.geysermc.geyser.scoreboard.ScoreboardUpdater; @@ -34,6 +32,8 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.WorldCache; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; +import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.ScoreboardPosition; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.scoreboard.ClientboundResetScorePacket; @Translator(packet = ClientboundResetScorePacket.class) public class JavaResetScorePacket extends PacketTranslator { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaSetDisplayObjectiveTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaSetDisplayObjectiveTranslator.java index 74f063e44..4ce971cdf 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaSetDisplayObjectiveTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaSetDisplayObjectiveTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.scoreboard; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetDisplayObjectivePacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetDisplayObjectivePacket; import org.geysermc.geyser.scoreboard.Scoreboard; import org.geysermc.geyser.scoreboard.ScoreboardUpdater; import org.geysermc.geyser.session.GeyserSession; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaSetObjectiveTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaSetObjectiveTranslator.java index 75f7d38f2..85d93c0b5 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaSetObjectiveTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaSetObjectiveTranslator.java @@ -25,9 +25,9 @@ package org.geysermc.geyser.translator.protocol.java.scoreboard; -import com.github.steveice10.mc.protocol.data.game.scoreboard.ObjectiveAction; -import com.github.steveice10.mc.protocol.data.game.scoreboard.ScoreboardPosition; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetObjectivePacket; +import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.ObjectiveAction; +import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.ScoreboardPosition; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetObjectivePacket; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserLogger; import org.geysermc.geyser.entity.type.player.PlayerEntity; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaSetPlayerTeamTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaSetPlayerTeamTranslator.java index f942b6f09..999edcc8c 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaSetPlayerTeamTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaSetPlayerTeamTranslator.java @@ -25,10 +25,10 @@ package org.geysermc.geyser.translator.protocol.java.scoreboard; -import com.github.steveice10.mc.protocol.data.game.scoreboard.NameTagVisibility; -import com.github.steveice10.mc.protocol.data.game.scoreboard.TeamAction; -import com.github.steveice10.mc.protocol.data.game.scoreboard.TeamColor; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetPlayerTeamPacket; +import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.NameTagVisibility; +import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.TeamAction; +import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.TeamColor; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetPlayerTeamPacket; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserLogger; import org.geysermc.geyser.scoreboard.Scoreboard; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaSetScoreTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaSetScoreTranslator.java index 6bffee3d3..d1645b496 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaSetScoreTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/scoreboard/JavaSetScoreTranslator.java @@ -25,8 +25,8 @@ package org.geysermc.geyser.translator.protocol.java.scoreboard; -import com.github.steveice10.mc.protocol.data.game.scoreboard.ScoreboardPosition; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetScorePacket; +import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.ScoreboardPosition; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetScorePacket; import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserLogger; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/title/JavaClearTitlesTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/title/JavaClearTitlesTranslator.java index 968845e92..8601ec7e9 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/title/JavaClearTitlesTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/title/JavaClearTitlesTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.title; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.title.ClientboundClearTitlesPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.title.ClientboundClearTitlesPacket; import org.cloudburstmc.protocol.bedrock.packet.SetTitlePacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/title/JavaSetActionBarTextTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/title/JavaSetActionBarTextTranslator.java index c2dfc85ff..5e3ba834b 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/title/JavaSetActionBarTextTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/title/JavaSetActionBarTextTranslator.java @@ -25,12 +25,12 @@ package org.geysermc.geyser.translator.protocol.java.title; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.title.ClientboundSetActionBarTextPacket; import org.cloudburstmc.protocol.bedrock.packet.SetTitlePacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.translator.text.MessageTranslator; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.title.ClientboundSetActionBarTextPacket; @Translator(packet = ClientboundSetActionBarTextPacket.class) public class JavaSetActionBarTextTranslator extends PacketTranslator { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/title/JavaSetSubtitleTextTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/title/JavaSetSubtitleTextTranslator.java index ba0407dcb..44d0a1e63 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/title/JavaSetSubtitleTextTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/title/JavaSetSubtitleTextTranslator.java @@ -25,12 +25,12 @@ package org.geysermc.geyser.translator.protocol.java.title; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.title.ClientboundSetSubtitleTextPacket; import org.cloudburstmc.protocol.bedrock.packet.SetTitlePacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.translator.text.MessageTranslator; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.title.ClientboundSetSubtitleTextPacket; @Translator(packet = ClientboundSetSubtitleTextPacket.class) public class JavaSetSubtitleTextTranslator extends PacketTranslator { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/title/JavaSetTitleTextTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/title/JavaSetTitleTextTranslator.java index 1aa789ad4..d0ac15a73 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/title/JavaSetTitleTextTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/title/JavaSetTitleTextTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.title; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.title.ClientboundSetTitleTextPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.title.ClientboundSetTitleTextPacket; import org.cloudburstmc.protocol.bedrock.packet.SetTitlePacket; import net.kyori.adventure.text.Component; import org.geysermc.geyser.session.GeyserSession; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/title/JavaSetTitlesAnimationTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/title/JavaSetTitlesAnimationTranslator.java index 4299a0596..4bc5ba0c5 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/title/JavaSetTitlesAnimationTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/title/JavaSetTitlesAnimationTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.title; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.title.ClientboundSetTitlesAnimationPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.title.ClientboundSetTitlesAnimationPacket; import org.cloudburstmc.protocol.bedrock.packet.SetTitlePacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; diff --git a/core/src/main/java/org/geysermc/geyser/translator/sound/BlockSoundInteractionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/sound/BlockSoundInteractionTranslator.java index ef6be0e9d..ead619b68 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/sound/BlockSoundInteractionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/sound/BlockSoundInteractionTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.sound; -import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; diff --git a/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java index 604e34945..612b9c38b 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java @@ -25,8 +25,8 @@ package org.geysermc.geyser.translator.text; -import com.github.steveice10.mc.protocol.data.DefaultComponentSerializer; -import com.github.steveice10.mc.protocol.data.game.scoreboard.TeamColor; +import org.geysermc.mcprotocollib.protocol.data.DefaultComponentSerializer; +import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.TeamColor; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.ScoreComponent; import net.kyori.adventure.text.TranslatableComponent; diff --git a/core/src/main/java/org/geysermc/geyser/util/AttributeUtils.java b/core/src/main/java/org/geysermc/geyser/util/AttributeUtils.java index d79d606b4..af2faab94 100644 --- a/core/src/main/java/org/geysermc/geyser/util/AttributeUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/AttributeUtils.java @@ -25,9 +25,9 @@ package org.geysermc.geyser.util; -import com.github.steveice10.mc.protocol.data.game.entity.attribute.Attribute; -import com.github.steveice10.mc.protocol.data.game.entity.attribute.AttributeModifier; -import com.github.steveice10.mc.protocol.data.game.entity.attribute.ModifierOperation; +import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.Attribute; +import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.AttributeModifier; +import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.ModifierOperation; public class AttributeUtils { /** diff --git a/core/src/main/java/org/geysermc/geyser/util/BlockEntityUtils.java b/core/src/main/java/org/geysermc/geyser/util/BlockEntityUtils.java index 31a2ddee9..ec7f45c8d 100644 --- a/core/src/main/java/org/geysermc/geyser/util/BlockEntityUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/BlockEntityUtils.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.util; -import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; @@ -35,6 +34,7 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.level.block.entity.BedrockOnlyBlockEntity; import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator; import org.geysermc.geyser.translator.level.block.entity.FlowerPotBlockEntityTranslator; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; import java.util.List; import java.util.Locale; diff --git a/core/src/main/java/org/geysermc/geyser/util/BlockUtils.java b/core/src/main/java/org/geysermc/geyser/util/BlockUtils.java index 8392f9fcd..0fc7a39e7 100644 --- a/core/src/main/java/org/geysermc/geyser/util/BlockUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/BlockUtils.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.util; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3i; import org.geysermc.geyser.inventory.GeyserItemStack; @@ -38,6 +37,7 @@ import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.tags.BlockTag; import org.geysermc.geyser.translator.collision.BlockCollision; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; public final class BlockUtils { @@ -181,7 +181,7 @@ public final class BlockUtils { /** * Given a position, return the position if a block were located on the specified block face. * @param blockPos the block position - * @param face the face of the block - see {@link com.github.steveice10.mc.protocol.data.game.entity.object.Direction} + * @param face the face of the block - see {@link org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction} * @return the block position with the block face accounted for */ public static Vector3i getBlockPosition(Vector3i blockPos, int face) { diff --git a/core/src/main/java/org/geysermc/geyser/util/CooldownUtils.java b/core/src/main/java/org/geysermc/geyser/util/CooldownUtils.java index 60838686f..c020e96b2 100644 --- a/core/src/main/java/org/geysermc/geyser/util/CooldownUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/CooldownUtils.java @@ -25,8 +25,8 @@ package org.geysermc.geyser.util; -import org.cloudburstmc.protocol.bedrock.packet.SetTitlePacket; import lombok.Getter; +import org.cloudburstmc.protocol.bedrock.packet.SetTitlePacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.PreferencesCache; import org.geysermc.geyser.text.ChatColor; diff --git a/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java b/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java index 469accd40..54e1cc34a 100644 --- a/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java @@ -25,18 +25,14 @@ package org.geysermc.geyser.util; -import com.github.steveice10.mc.protocol.data.game.entity.Effect; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.PlayerActionType; -import org.cloudburstmc.protocol.bedrock.packet.ChangeDimensionPacket; -import org.cloudburstmc.protocol.bedrock.packet.ChunkRadiusUpdatedPacket; -import org.cloudburstmc.protocol.bedrock.packet.MobEffectPacket; -import org.cloudburstmc.protocol.bedrock.packet.PlayerActionPacket; -import org.cloudburstmc.protocol.bedrock.packet.StopSoundPacket; +import org.cloudburstmc.protocol.bedrock.packet.*; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.level.BedrockDimension; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.Effect; import java.util.Set; diff --git a/core/src/main/java/org/geysermc/geyser/util/EntityUtils.java b/core/src/main/java/org/geysermc/geyser/util/EntityUtils.java index f040fd0ba..d11c1f9e4 100644 --- a/core/src/main/java/org/geysermc/geyser/util/EntityUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/EntityUtils.java @@ -25,10 +25,6 @@ package org.geysermc.geyser.util; -import com.github.steveice10.mc.protocol.data.game.entity.Effect; -import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; -import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.GameType; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; @@ -41,6 +37,10 @@ import org.geysermc.geyser.entity.type.living.animal.AnimalEntity; import org.geysermc.geyser.entity.type.living.animal.horse.CamelEntity; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.Items; +import org.geysermc.mcprotocollib.protocol.data.game.entity.Effect; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; +import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType; import java.util.Locale; diff --git a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java index 2b619714e..63644d5fc 100644 --- a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java @@ -25,12 +25,6 @@ package org.geysermc.geyser.util; -import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; -import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundPickItemPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundSetCreativeModeSlotPacket; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; @@ -58,6 +52,12 @@ import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.translator.inventory.InventoryTranslator; import org.geysermc.geyser.translator.inventory.LecternInventoryTranslator; import org.geysermc.geyser.translator.inventory.chest.DoubleChestInventoryTranslator; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; +import org.geysermc.mcprotocollib.protocol.data.game.recipe.Ingredient; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundPickItemPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundSetCreativeModeSlotPacket; import org.jetbrains.annotations.Contract; import java.util.Arrays; diff --git a/core/src/main/java/org/geysermc/geyser/util/ItemUtils.java b/core/src/main/java/org/geysermc/geyser/util/ItemUtils.java index b1591e911..1b47c3a00 100644 --- a/core/src/main/java/org/geysermc/geyser/util/ItemUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/ItemUtils.java @@ -25,14 +25,14 @@ package org.geysermc.geyser.util; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; -import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; -import com.github.steveice10.mc.protocol.data.game.item.component.ItemEnchantments; import net.kyori.adventure.text.Component; import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.FishingRodItem; import org.geysermc.geyser.item.type.Item; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemEnchantments; public class ItemUtils { diff --git a/core/src/main/java/org/geysermc/geyser/util/PluginMessageUtils.java b/core/src/main/java/org/geysermc/geyser/util/PluginMessageUtils.java index f6b91388f..09543baca 100644 --- a/core/src/main/java/org/geysermc/geyser/util/PluginMessageUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/PluginMessageUtils.java @@ -25,10 +25,10 @@ package org.geysermc.geyser.util; -import com.github.steveice10.mc.protocol.packet.common.serverbound.ServerboundCustomPayloadPacket; import com.google.common.base.Charsets; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.packet.common.serverbound.ServerboundCustomPayloadPacket; import java.nio.ByteBuffer; diff --git a/core/src/main/java/org/geysermc/geyser/util/SoundUtils.java b/core/src/main/java/org/geysermc/geyser/util/SoundUtils.java index 4c5f6b68f..85f8fc704 100644 --- a/core/src/main/java/org/geysermc/geyser/util/SoundUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/SoundUtils.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.util; -import com.github.steveice10.mc.protocol.data.game.level.sound.Sound; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.LevelEvent; @@ -39,6 +38,7 @@ import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.type.SoundMapping; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.level.sound.Sound; import java.util.Locale; diff --git a/core/src/main/java/org/geysermc/geyser/util/StatisticFormatters.java b/core/src/main/java/org/geysermc/geyser/util/StatisticFormatters.java index d46a759fe..589bac043 100644 --- a/core/src/main/java/org/geysermc/geyser/util/StatisticFormatters.java +++ b/core/src/main/java/org/geysermc/geyser/util/StatisticFormatters.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.util; -import com.github.steveice10.mc.protocol.data.game.statistic.StatisticFormat; +import org.geysermc.mcprotocollib.protocol.data.game.statistic.StatisticFormat; import java.text.DecimalFormat; import java.text.NumberFormat; diff --git a/core/src/main/java/org/geysermc/geyser/util/StatisticsUtils.java b/core/src/main/java/org/geysermc/geyser/util/StatisticsUtils.java index aa174497b..96328bcdd 100644 --- a/core/src/main/java/org/geysermc/geyser/util/StatisticsUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/StatisticsUtils.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.util; -import com.github.steveice10.mc.protocol.data.game.statistic.*; import it.unimi.dsi.fastutil.objects.Object2IntMap; import org.geysermc.cumulus.form.SimpleForm; import org.geysermc.cumulus.util.FormImage; @@ -35,6 +34,7 @@ import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.text.MinecraftLocale; +import org.geysermc.mcprotocollib.protocol.data.game.statistic.*; import java.util.ArrayList; import java.util.List; diff --git a/core/src/main/java/org/geysermc/geyser/util/StructureBlockUtils.java b/core/src/main/java/org/geysermc/geyser/util/StructureBlockUtils.java index 9b3cfb53f..c1ccf9d5b 100644 --- a/core/src/main/java/org/geysermc/geyser/util/StructureBlockUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/StructureBlockUtils.java @@ -25,9 +25,6 @@ package org.geysermc.geyser.util; -import com.github.steveice10.mc.protocol.data.game.inventory.UpdateStructureBlockAction; -import com.github.steveice10.mc.protocol.data.game.inventory.UpdateStructureBlockMode; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundSetStructureBlockPacket; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtList; import org.cloudburstmc.nbt.NbtMap; @@ -39,6 +36,9 @@ import org.cloudburstmc.protocol.bedrock.data.structure.StructureSettings; import org.cloudburstmc.protocol.bedrock.data.structure.StructureTemplateResponseType; import org.cloudburstmc.protocol.bedrock.packet.StructureTemplateDataResponsePacket; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.UpdateStructureBlockAction; +import org.geysermc.mcprotocollib.protocol.data.game.inventory.UpdateStructureBlockMode; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundSetStructureBlockPacket; public class StructureBlockUtils { @@ -124,17 +124,17 @@ public class StructureBlockUtils { public static void sendJavaStructurePacket(GeyserSession session, Vector3i blockPosition, Vector3i size, UpdateStructureBlockMode mode, UpdateStructureBlockAction action, StructureSettings settings, boolean boundingBoxVisible, String structureName) { - com.github.steveice10.mc.protocol.data.game.level.block.StructureMirror mirror = switch (settings.getMirror()) { - case X -> com.github.steveice10.mc.protocol.data.game.level.block.StructureMirror.FRONT_BACK; - case Z -> com.github.steveice10.mc.protocol.data.game.level.block.StructureMirror.LEFT_RIGHT; - default -> com.github.steveice10.mc.protocol.data.game.level.block.StructureMirror.NONE; + org.geysermc.mcprotocollib.protocol.data.game.level.block.StructureMirror mirror = switch (settings.getMirror()) { + case X -> org.geysermc.mcprotocollib.protocol.data.game.level.block.StructureMirror.FRONT_BACK; + case Z -> org.geysermc.mcprotocollib.protocol.data.game.level.block.StructureMirror.LEFT_RIGHT; + default -> org.geysermc.mcprotocollib.protocol.data.game.level.block.StructureMirror.NONE; }; - com.github.steveice10.mc.protocol.data.game.level.block.StructureRotation rotation = switch (settings.getRotation()) { - case ROTATE_90 -> com.github.steveice10.mc.protocol.data.game.level.block.StructureRotation.CLOCKWISE_90; - case ROTATE_180 -> com.github.steveice10.mc.protocol.data.game.level.block.StructureRotation.CLOCKWISE_180; - case ROTATE_270 -> com.github.steveice10.mc.protocol.data.game.level.block.StructureRotation.COUNTERCLOCKWISE_90; - default -> com.github.steveice10.mc.protocol.data.game.level.block.StructureRotation.NONE; + org.geysermc.mcprotocollib.protocol.data.game.level.block.StructureRotation rotation = switch (settings.getRotation()) { + case ROTATE_90 -> org.geysermc.mcprotocollib.protocol.data.game.level.block.StructureRotation.CLOCKWISE_90; + case ROTATE_180 -> org.geysermc.mcprotocollib.protocol.data.game.level.block.StructureRotation.CLOCKWISE_180; + case ROTATE_270 -> org.geysermc.mcprotocollib.protocol.data.game.level.block.StructureRotation.COUNTERCLOCKWISE_90; + default -> org.geysermc.mcprotocollib.protocol.data.game.level.block.StructureRotation.NONE; }; Vector3i offset = settings.getOffset(); diff --git a/core/src/test/java/org/geysermc/geyser/network/translators/chat/MessageTranslatorTest.java b/core/src/test/java/org/geysermc/geyser/network/translators/chat/MessageTranslatorTest.java index 5e5c3af7a..85d7ffa9a 100644 --- a/core/src/test/java/org/geysermc/geyser/network/translators/chat/MessageTranslatorTest.java +++ b/core/src/test/java/org/geysermc/geyser/network/translators/chat/MessageTranslatorTest.java @@ -25,8 +25,8 @@ package org.geysermc.geyser.network.translators.chat; -import com.github.steveice10.mc.protocol.data.DefaultComponentSerializer; import org.geysermc.geyser.translator.text.MessageTranslator; +import org.geysermc.mcprotocollib.protocol.data.DefaultComponentSerializer; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; diff --git a/core/src/test/java/org/geysermc/geyser/registry/loader/ResourcePackLoaderTest.java b/core/src/test/java/org/geysermc/geyser/registry/loader/ResourcePackLoaderTest.java index b66fd0811..ce2fd2a6f 100644 --- a/core/src/test/java/org/geysermc/geyser/registry/loader/ResourcePackLoaderTest.java +++ b/core/src/test/java/org/geysermc/geyser/registry/loader/ResourcePackLoaderTest.java @@ -34,9 +34,7 @@ import java.nio.file.Path; import java.nio.file.PathMatcher; import java.util.Objects; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.*; public class ResourcePackLoaderTest { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2b6df11a6..3cb136683 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ protocol-connection = "3.0.0.Beta1-20240411.165033-128" raknet = "1.0.0.CR3-20240416.144209-1" blockstateupdater="1.20.80-20240411.142413-1" mcauthlib = "d9d773e" -mcprotocollib = "3c81cc80" # Revert from jitpack after release +mcprotocollib = "1ca8808" # Revert from jitpack after release adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" From 9d540fe672e6f0887a58695ef870e3c2e8fe8eff Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Wed, 24 Apr 2024 16:41:02 -0400 Subject: [PATCH 289/344] Shulker box NPE fix --- .../main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java index 4108d0fa0..2f2f45c5b 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java @@ -59,7 +59,7 @@ public class ShulkerBoxItem extends BlockItem { List itemsList = new ArrayList<>(); for (int slot = 0; slot < contents.size(); slot++) { ItemStack item = contents.get(slot); - if (item.getId() == Items.AIR_ID) { + if (item == null || item.getId() == Items.AIR_ID) { continue; } ItemMapping boxMapping = session.getItemMappings().getMapping(item.getId()); From 652f6af7849d05ecbe6d3028eff77646b68d6301 Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Wed, 24 Apr 2024 18:13:07 -0700 Subject: [PATCH 290/344] Fix custom skulls 1.20.5 Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .../entity/SkullBlockEntityTranslator.java | 32 +++++++++---------- .../level/JavaBlockEntityDataTranslator.java | 2 +- .../JavaLevelChunkWithLightTranslator.java | 3 +- 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java index 61c922528..38a056bd0 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java @@ -66,8 +66,8 @@ public class SkullBlockEntityTranslator extends BlockEntityTranslator implements } } - private static UUID getUUID(CompoundTag owner) { - if (owner.get("Id") instanceof IntArrayTag uuidTag && uuidTag.length() == 4) { + private static UUID getUUID(CompoundTag profile) { + if (profile.get("id") instanceof IntArrayTag uuidTag && uuidTag.length() == 4) { int[] uuidAsArray = uuidTag.getValue(); // thank u viaversion return new UUID((long) uuidAsArray[0] << 32 | ((long) uuidAsArray[1] & 0xFFFFFFFFL), @@ -75,46 +75,44 @@ public class SkullBlockEntityTranslator extends BlockEntityTranslator implements } // Convert username to an offline UUID String username = null; - if (owner.get("Name") instanceof StringTag nameTag) { + if (profile.get("name") instanceof StringTag nameTag) { username = nameTag.getValue().toLowerCase(Locale.ROOT); } return UUID.nameUUIDFromBytes(("OfflinePlayer:" + username).getBytes(StandardCharsets.UTF_8)); } - private static CompletableFuture getTextures(CompoundTag owner, UUID uuid) { - CompoundTag properties = owner.get("Properties"); + private static CompletableFuture getTextures(CompoundTag profile, UUID uuid) { + ListTag properties = profile.get("properties"); if (properties == null) { if (uuid != null && uuid.version() == 4) { String uuidString = uuid.toString().replace("-", ""); return SkinProvider.requestTexturesFromUUID(uuidString); - } else if (owner.get("Name") instanceof StringTag nameTag) { + } else if (profile.get("name") instanceof StringTag nameTag) { // Fall back to username if UUID was missing or was an offline mode UUID return SkinProvider.requestTexturesFromUsername(nameTag.getValue()); } return CompletableFuture.completedFuture(null); } - ListTag textures = properties.get("textures"); - LinkedHashMap tag1 = (LinkedHashMap) textures.get(0).getValue(); - StringTag texture = (StringTag) tag1.get("Value"); + LinkedHashMap tag1 = (LinkedHashMap) properties.get(0).getValue(); + StringTag texture = (StringTag) tag1.get("value"); return CompletableFuture.completedFuture(texture.getValue()); } public static @Nullable BlockDefinition translateSkull(GeyserSession session, CompoundTag tag, Vector3i blockPosition, int blockState) { - // TODO: The tag layout follows new format (profille, etc...) - CompoundTag owner = tag.get("SkullOwner"); - if (owner == null) { + CompoundTag profile = tag.get("profile"); + if (profile == null) { session.getSkullCache().removeSkull(blockPosition); return null; } - UUID uuid = getUUID(owner); + UUID uuid = getUUID(profile); - CompletableFuture texturesFuture = getTextures(owner, uuid); + CompletableFuture texturesFuture = getTextures(profile, uuid); if (texturesFuture.isDone()) { try { String texture = texturesFuture.get(); if (texture == null) { - session.getGeyser().getLogger().debug("Custom skull with invalid SkullOwner tag: " + blockPosition + " " + tag); + session.getGeyser().getLogger().debug("Custom skull with invalid profile tag: " + blockPosition + " " + tag); return null; } SkullCache.Skull skull = session.getSkullCache().putSkull(blockPosition, uuid, texture, blockState); @@ -128,10 +126,10 @@ public class SkullBlockEntityTranslator extends BlockEntityTranslator implements return null; } - // SkullOwner contained a username, so we have to wait for it to be retrieved + // profile contained a username, so we have to wait for it to be retrieved texturesFuture.whenComplete((texturesProperty, throwable) -> { if (texturesProperty == null) { - session.getGeyser().getLogger().debug("Custom skull with invalid SkullOwner tag: " + blockPosition + " " + tag); + session.getGeyser().getLogger().debug("Custom skull with invalid profile tag: " + blockPosition + " " + tag); return; } if (session.getEventLoop().inEventLoop()) { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEntityDataTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEntityDataTranslator.java index ca746f79b..82b51dfdd 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEntityDataTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEntityDataTranslator.java @@ -71,7 +71,7 @@ public class JavaBlockEntityDataTranslator extends PacketTranslator> 4) - (bedrockDimension.minY() >> 4); From 99e6a2981da27a9ec8f09c04cfc8e73a296e4263 Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Thu, 25 Apr 2024 01:33:18 -0700 Subject: [PATCH 291/344] Entity properties Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .../geyser/entity/EntityDefinition.java | 19 +- .../geyser/entity/EntityDefinitions.java | 15 +- .../properties/GeyserEntityProperties.java | 165 ++++++++++++++++++ .../GeyserEntityPropertyManager.java | 98 +++++++++++ .../properties/type/BooleanProperty.java | 44 +++++ .../entity/properties/type/EnumProperty.java | 61 +++++++ .../entity/properties/type/FloatProperty.java | 50 ++++++ .../entity/properties/type/IntProperty.java | 50 ++++++ .../entity/properties/type/PropertyType.java | 32 ++++ .../geysermc/geyser/entity/type/Entity.java | 22 +++ .../type/living/animal/ArmadilloEntity.java | 18 +- .../entity/type/living/animal/BeeEntity.java | 3 +- .../geysermc/geyser/registry/Registries.java | 5 + .../geyser/session/GeyserSession.java | 12 ++ 14 files changed, 587 insertions(+), 7 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/entity/properties/GeyserEntityProperties.java create mode 100644 core/src/main/java/org/geysermc/geyser/entity/properties/GeyserEntityPropertyManager.java create mode 100644 core/src/main/java/org/geysermc/geyser/entity/properties/type/BooleanProperty.java create mode 100644 core/src/main/java/org/geysermc/geyser/entity/properties/type/EnumProperty.java create mode 100644 core/src/main/java/org/geysermc/geyser/entity/properties/type/FloatProperty.java create mode 100644 core/src/main/java/org/geysermc/geyser/entity/properties/type/IntProperty.java create mode 100644 core/src/main/java/org/geysermc/geyser/entity/properties/type/PropertyType.java diff --git a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinition.java b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinition.java index f0e221bad..31aa7cc73 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinition.java +++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinition.java @@ -33,6 +33,7 @@ import lombok.Setter; import lombok.experimental.Accessors; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.entity.factory.EntityFactory; +import org.geysermc.geyser.entity.properties.GeyserEntityProperties; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.translator.entity.EntityMetadataTranslator; @@ -49,10 +50,10 @@ import java.util.function.BiConsumer; * @param the entity type this definition represents */ public record EntityDefinition(EntityFactory factory, EntityType entityType, String identifier, - float width, float height, float offset, List> translators) { + float width, float height, float offset, GeyserEntityProperties registeredProperties, List> translators) { public static Builder inherited(EntityFactory factory, EntityDefinition parent) { - return new Builder<>(factory, parent.entityType, parent.identifier, parent.width, parent.height, parent.offset, new ObjectArrayList<>(parent.translators)); + return new Builder<>(factory, parent.entityType, parent.identifier, parent.width, parent.height, parent.offset, parent.registeredProperties, new ObjectArrayList<>(parent.translators)); } public static Builder builder(EntityFactory factory) { @@ -87,6 +88,7 @@ public record EntityDefinition(EntityFactory factory, Entit private float width; private float height; private float offset = 0.00001f; + private GeyserEntityProperties registeredProperties; private final List> translators; private Builder(EntityFactory factory) { @@ -94,13 +96,14 @@ public record EntityDefinition(EntityFactory factory, Entit translators = new ObjectArrayList<>(); } - public Builder(EntityFactory factory, EntityType type, String identifier, float width, float height, float offset, List> translators) { + public Builder(EntityFactory factory, EntityType type, String identifier, float width, float height, float offset, GeyserEntityProperties registeredProperties, List> translators) { this.factory = factory; this.type = type; this.identifier = identifier; this.width = width; this.height = height; this.offset = offset; + this.registeredProperties = registeredProperties; this.translators = translators; } @@ -127,6 +130,11 @@ public record EntityDefinition(EntityFactory factory, Entit return this; } + public Builder properties(GeyserEntityProperties registeredProperties) { + this.registeredProperties = registeredProperties; + return this; + } + public >> Builder addTranslator(MetadataType type, BiConsumer translateFunction) { translators.add(new EntityMetadataTranslator<>(type, translateFunction)); return this; @@ -149,10 +157,13 @@ public record EntityDefinition(EntityFactory factory, Entit if (identifier == null && type != null) { identifier = "minecraft:" + type.name().toLowerCase(Locale.ROOT); } - EntityDefinition definition = new EntityDefinition<>(factory, type, identifier, width, height, offset, translators); + EntityDefinition definition = new EntityDefinition<>(factory, type, identifier, width, height, offset, registeredProperties, translators); if (register && definition.entityType() != null) { Registries.ENTITY_DEFINITIONS.get().putIfAbsent(definition.entityType(), definition); Registries.JAVA_ENTITY_IDENTIFIERS.get().putIfAbsent("minecraft:" + type.name().toLowerCase(Locale.ROOT), definition); + if (definition.registeredProperties() != null) { + Registries.BEDROCK_ENTITY_PROPERTIES.get().add(definition.registeredProperties().toNbtMap(identifier)); + } } return definition; } diff --git a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java index 328dd4bbf..317892676 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java +++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java @@ -31,6 +31,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.FloatE import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; +import org.geysermc.geyser.entity.properties.GeyserEntityProperties; import org.geysermc.geyser.entity.type.*; import org.geysermc.geyser.entity.type.living.*; import org.geysermc.geyser.entity.type.living.animal.*; @@ -774,7 +775,16 @@ public final class EntityDefinitions { ARMADILLO = EntityDefinition.inherited(ArmadilloEntity::new, ageableEntityBase) .type(EntityType.ARMADILLO) .height(0.65f).width(0.7f) - .addTranslator(null) + .properties(new GeyserEntityProperties.Builder() + .addEnum( + "minecraft:armadillo_state", + "unrolled", + "rolled_up", + "rolled_up_peeking", + "rolled_up_relaxing", + "rolled_up_unrolling") + .build()) + .addTranslator(MetadataType.ARMADILLO_STATE, ArmadilloEntity::setArmadilloState) .build(); AXOLOTL = EntityDefinition.inherited(AxolotlEntity::new, ageableEntityBase) .type(EntityType.AXOLOTL) @@ -786,6 +796,9 @@ public final class EntityDefinitions { BEE = EntityDefinition.inherited(BeeEntity::new, ageableEntityBase) .type(EntityType.BEE) .heightAndWidth(0.6f) + .properties(new GeyserEntityProperties.Builder() + .addBoolean("minecraft:has_nectar") + .build()) .addTranslator(MetadataType.BYTE, BeeEntity::setBeeFlags) .addTranslator(MetadataType.INT, BeeEntity::setAngerTime) .build(); diff --git a/core/src/main/java/org/geysermc/geyser/entity/properties/GeyserEntityProperties.java b/core/src/main/java/org/geysermc/geyser/entity/properties/GeyserEntityProperties.java new file mode 100644 index 000000000..1729b0583 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/entity/properties/GeyserEntityProperties.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2019-2024 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.entity.properties; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtMapBuilder; +import org.cloudburstmc.nbt.NbtType; +import org.geysermc.geyser.entity.properties.type.BooleanProperty; +import org.geysermc.geyser.entity.properties.type.EnumProperty; +import org.geysermc.geyser.entity.properties.type.FloatProperty; +import org.geysermc.geyser.entity.properties.type.IntProperty; +import org.geysermc.geyser.entity.properties.type.PropertyType; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +@EqualsAndHashCode +@ToString +public class GeyserEntityProperties { + private final ObjectArrayList properties; + private final Object2IntMap propertyIndices; + + private GeyserEntityProperties(ObjectArrayList properties, + Object2IntMap propertyIndices) { + this.properties = properties; + this.propertyIndices = propertyIndices; + } + + public NbtMap toNbtMap(String entityType) { + NbtMapBuilder mapBuilder = NbtMap.builder(); + List nbtProperties = new ArrayList<>(); + + for (PropertyType property : properties) { + nbtProperties.add(property.nbtMap()); + } + mapBuilder.putList("properties", NbtType.COMPOUND, nbtProperties); + + return mapBuilder.putString("type", entityType).build(); + } + + public @NonNull List getProperties() { + return properties; + } + + public int getPropertyIndex(String name) { + return propertyIndices.getOrDefault(name, -1); + } + + public static class Builder { + private final ObjectArrayList properties = new ObjectArrayList<>(); + private final Object2IntMap propertyIndices = new Object2IntOpenHashMap<>(); + + public Builder addInt(@NonNull String name, int min, int max) { + if (propertyIndices.containsKey(name)) { + throw new IllegalArgumentException( + "Property with name " + name + " already exists on builder!"); + } + PropertyType property = new IntProperty(name, min, max); + this.properties.add(property); + propertyIndices.put(name, properties.size() - 1); + return this; + } + + public Builder addInt(@NonNull String name) { + if (propertyIndices.containsKey(name)) { + throw new IllegalArgumentException( + "Property with name " + name + " already exists on builder!"); + } + PropertyType property = new IntProperty(name, Integer.MIN_VALUE, Integer.MAX_VALUE); + this.properties.add(property); + propertyIndices.put(name, properties.size() - 1); + return this; + } + + public Builder addFloat(@NonNull String name, float min, float max) { + if (propertyIndices.containsKey(name)) { + throw new IllegalArgumentException( + "Property with name " + name + " already exists on builder!"); + } + PropertyType property = new FloatProperty(name, min, max); + this.properties.add(property); + propertyIndices.put(name, properties.size() - 1); + return this; + } + + public Builder addFloat(@NonNull String name) { + if (propertyIndices.containsKey(name)) { + throw new IllegalArgumentException( + "Property with name " + name + " already exists on builder!"); + } + PropertyType property = new FloatProperty(name, Float.MIN_NORMAL, Float.MAX_VALUE); + this.properties.add(property); + propertyIndices.put(name, properties.size() - 1); + return this; + } + + public Builder addBoolean(@NonNull String name) { + if (propertyIndices.containsKey(name)) { + throw new IllegalArgumentException( + "Property with name " + name + " already exists on builder!"); + } + PropertyType property = new BooleanProperty(name); + this.properties.add(property); + propertyIndices.put(name, properties.size() - 1); + return this; + } + + public Builder addEnum(@NonNull String name, List values) { + if (propertyIndices.containsKey(name)) { + throw new IllegalArgumentException( + "Property with name " + name + " already exists on builder!"); + } + PropertyType property = new EnumProperty(name, values); + this.properties.add(property); + propertyIndices.put(name, properties.size() - 1); + return this; + } + + public Builder addEnum(@NonNull String name, String... values) { + if (propertyIndices.containsKey(name)) { + throw new IllegalArgumentException( + "Property with name " + name + " already exists on builder!"); + } + List valuesList = Arrays.asList(values); // Convert array to list + PropertyType property = new EnumProperty(name, valuesList); + this.properties.add(property); + propertyIndices.put(name, properties.size() - 1); + return this; + } + + public GeyserEntityProperties build() { + return new GeyserEntityProperties(properties, propertyIndices); + } + } +} \ No newline at end of file diff --git a/core/src/main/java/org/geysermc/geyser/entity/properties/GeyserEntityPropertyManager.java b/core/src/main/java/org/geysermc/geyser/entity/properties/GeyserEntityPropertyManager.java new file mode 100644 index 000000000..29026b172 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/entity/properties/GeyserEntityPropertyManager.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2019-2023 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.entity.properties; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.cloudburstmc.protocol.bedrock.data.entity.FloatEntityProperty; +import org.cloudburstmc.protocol.bedrock.data.entity.IntEntityProperty; +import org.geysermc.geyser.entity.properties.type.EnumProperty; +import org.geysermc.geyser.entity.properties.type.PropertyType; + +import java.util.List; + +public class GeyserEntityPropertyManager { + + private final GeyserEntityProperties properties; + + private final ObjectArrayList intEntityProperties = new ObjectArrayList<>(); + private final ObjectArrayList floatEntityProperties = new ObjectArrayList<>(); + + public GeyserEntityPropertyManager(GeyserEntityProperties properties) { + this.properties = properties; + } + + public void add(String propertyName, int value) { + int index = properties.getPropertyIndex(propertyName); + intEntityProperties.add(new IntEntityProperty(index, value)); + } + + public void add(String propertyName, boolean value) { + int index = properties.getPropertyIndex(propertyName); + intEntityProperties.add(new IntEntityProperty(index, value ? 1 : 0)); + } + + public void add(String propertyName, String value) { + int index = properties.getPropertyIndex(propertyName); + PropertyType property = properties.getProperties().get(index); + int enumIndex = ((EnumProperty) property).getIndex(value); + intEntityProperties.add(new IntEntityProperty(index, enumIndex)); + } + + public void add(String propertyName, float value) { + int index = properties.getPropertyIndex(propertyName); + floatEntityProperties.add(new FloatEntityProperty(index, value)); + } + + public boolean hasFloatProperties() { + return !this.floatEntityProperties.isEmpty(); + } + + public boolean hasIntProperties() { + return !this.intEntityProperties.isEmpty(); + } + + public boolean hasProperties() { + return hasFloatProperties() || hasIntProperties(); + } + + public ObjectArrayList intProperties() { + return this.intEntityProperties; + } + + public void applyIntProperties(List properties) { + properties.addAll(intEntityProperties); + intEntityProperties.clear(); + } + + public ObjectArrayList floatProperties() { + return this.floatEntityProperties; + } + + public void applyFloatProperties(List properties) { + properties.addAll(floatEntityProperties); + floatEntityProperties.clear(); + } +} \ No newline at end of file diff --git a/core/src/main/java/org/geysermc/geyser/entity/properties/type/BooleanProperty.java b/core/src/main/java/org/geysermc/geyser/entity/properties/type/BooleanProperty.java new file mode 100644 index 000000000..6fc64ad4b --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/entity/properties/type/BooleanProperty.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2019-2024 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.entity.properties.type; + +import org.cloudburstmc.nbt.NbtMap; + +public class BooleanProperty implements PropertyType { + private final String name; + + public BooleanProperty(String name) { + this.name = name; + } + + @Override + public NbtMap nbtMap() { + return NbtMap.builder() + .putString("name", name) + .putInt("type", 2) + .build(); + } +} \ No newline at end of file diff --git a/core/src/main/java/org/geysermc/geyser/entity/properties/type/EnumProperty.java b/core/src/main/java/org/geysermc/geyser/entity/properties/type/EnumProperty.java new file mode 100644 index 000000000..9bc45f560 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/entity/properties/type/EnumProperty.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2019-2024 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.entity.properties.type; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtType; + +import java.util.List; + +public class EnumProperty implements PropertyType { + private final String name; + private final List values; + private final Object2IntMap valueIndexMap; + + public EnumProperty(String name, List values) { + this.name = name; + this.values = values; + this.valueIndexMap = new Object2IntOpenHashMap<>(values.size()); + for (int i = 0; i < values.size(); i++) { + valueIndexMap.put(values.get(i), i); + } + } + + @Override + public NbtMap nbtMap() { + return NbtMap.builder() + .putString("name", name) + .putList("values", NbtType.STRING, values) + .putInt("type", 3) + .build(); + } + + public int getIndex(String value) { + return valueIndexMap.getOrDefault(value, -1); + } +} \ No newline at end of file diff --git a/core/src/main/java/org/geysermc/geyser/entity/properties/type/FloatProperty.java b/core/src/main/java/org/geysermc/geyser/entity/properties/type/FloatProperty.java new file mode 100644 index 000000000..8b808ebc3 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/entity/properties/type/FloatProperty.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2019-2023 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.entity.properties.type; + +import org.cloudburstmc.nbt.NbtMap; + +public class FloatProperty implements PropertyType { + private final String name; + private final float max; + private final float min; + + public FloatProperty(String name, float min, float max) { + this.name = name; + this.max = max; + this.min = min; + } + + @Override + public NbtMap nbtMap() { + return NbtMap.builder() + .putString("name", name) + .putFloat("max", max) + .putFloat("min", min) + .putInt("type", 1) + .build(); + } +} \ No newline at end of file diff --git a/core/src/main/java/org/geysermc/geyser/entity/properties/type/IntProperty.java b/core/src/main/java/org/geysermc/geyser/entity/properties/type/IntProperty.java new file mode 100644 index 000000000..9e38db7c7 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/entity/properties/type/IntProperty.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2019-2024 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.entity.properties.type; + +import org.cloudburstmc.nbt.NbtMap; + +public class IntProperty implements PropertyType { + private final String name; + private final int max; + private final int min; + + public IntProperty(String name, int min, int max) { + this.name = name; + this.max = max; + this.min = min; + } + + @Override + public NbtMap nbtMap() { + return NbtMap.builder() + .putString("name", name) + .putInt("max", max) + .putInt("min", min) + .putInt("type", 0) + .build(); + } +} \ No newline at end of file diff --git a/core/src/main/java/org/geysermc/geyser/entity/properties/type/PropertyType.java b/core/src/main/java/org/geysermc/geyser/entity/properties/type/PropertyType.java new file mode 100644 index 000000000..a64d7246a --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/entity/properties/type/PropertyType.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2019-2024 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.entity.properties.type; + +import org.cloudburstmc.nbt.NbtMap; + +public interface PropertyType { + NbtMap nbtMap(); +} \ No newline at end of file diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java b/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java index f1d6bfb98..fecd72f67 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java @@ -39,6 +39,7 @@ import org.cloudburstmc.protocol.bedrock.packet.*; import org.geysermc.geyser.api.entity.type.GeyserEntity; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.GeyserDirtyMetadata; +import org.geysermc.geyser.entity.properties.GeyserEntityPropertyManager; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.util.EntityUtils; @@ -117,6 +118,8 @@ public class Entity implements GeyserEntity { @Setter(AccessLevel.PROTECTED) // For players private boolean flagsDirty = false; + protected final GeyserEntityPropertyManager propertyManager; + public Entity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { this.session = session; @@ -131,6 +134,8 @@ public class Entity implements GeyserEntity { this.valid = false; + this.propertyManager = new GeyserEntityPropertyManager(definition.registeredProperties()); + setPosition(position); setAirSupply(getMaxAir()); @@ -348,6 +353,23 @@ public class Entity implements GeyserEntity { } } + /** + * Sends the Bedrock entity properties to the client + */ + public void updateBedrockEntityProperties() { + if (!valid) { + return; + } + + if (propertyManager.hasProperties()) { + SetEntityDataPacket entityDataPacket = new SetEntityDataPacket(); + entityDataPacket.setRuntimeEntityId(geyserId); + propertyManager.applyIntProperties(entityDataPacket.getProperties().getIntProperties()); + propertyManager.applyFloatProperties(entityDataPacket.getProperties().getFloatProperties()); + session.sendUpstreamPacket(entityDataPacket); + } + } + public void setFlags(ByteEntityMetadata entityMetadata) { byte xd = entityMetadata.getPrimitiveValue(); setFlag(EntityFlag.ON_FIRE, ((xd & 0x01) == 0x01) && !getFlag(EntityFlag.FIRE_IMMUNE)); // Otherwise immune entities sometimes flicker onfire diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ArmadilloEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ArmadilloEntity.java index d89b4e3f7..205c8cbd9 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ArmadilloEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ArmadilloEntity.java @@ -28,11 +28,27 @@ package org.geysermc.geyser.entity.type.living.animal; import org.cloudburstmc.math.vector.Vector3f; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.ArmadilloState; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ObjectEntityMetadata; import java.util.UUID; public class ArmadilloEntity extends AnimalEntity { - public ArmadilloEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { + public ArmadilloEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, + EntityDefinition definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); } + + // TODO: This is completely wrong; probably need to store the previous IDLE/ROLLING/SCARED state and check for transitions (pain) + public void setArmadilloState(ObjectEntityMetadata entityMetadata) { + ArmadilloState armadilloState = entityMetadata.getValue(); + + switch (armadilloState) { + case IDLE -> propertyManager.add("minecraft:armadillo_state", "unrolled"); + case ROLLING -> propertyManager.add("minecraft:armadillo_state", "rolled_up"); + case SCARED -> propertyManager.add("minecraft:armadillo_state", "rolled_up_peeking"); + } + + updateBedrockEntityProperties(); + } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/BeeEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/BeeEntity.java index d6aa9615d..28ebad473 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/BeeEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/BeeEntity.java @@ -58,7 +58,8 @@ public class BeeEntity extends AnimalEntity { // If the bee has stung dirtyMetadata.put(EntityDataTypes.MARK_VARIANT, (xd & 0x04) == 0x04 ? 1 : 0); // If the bee has nectar or not - setFlag(EntityFlag.POWERED, (xd & 0x08) == 0x08); + propertyManager.add("minecraft:has_nectar", (xd & 0x08) == 0x08); + updateBedrockEntityProperties(); } public void setAngerTime(IntEntityMetadata entityMetadata) { diff --git a/core/src/main/java/org/geysermc/geyser/registry/Registries.java b/core/src/main/java/org/geysermc/geyser/registry/Registries.java index f19898016..54d013140 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/Registries.java +++ b/core/src/main/java/org/geysermc/geyser/registry/Registries.java @@ -112,6 +112,11 @@ public final class Registries { */ public static final SimpleMappedRegistry> ENTITY_DEFINITIONS = SimpleMappedRegistry.create(RegistryLoaders.empty(() -> new EnumMap<>(EntityType.class))); + /** + * A registry holding a list of all the known entity properties to be sent to the client after start game. + */ + public static final SimpleRegistry> BEDROCK_ENTITY_PROPERTIES = SimpleRegistry.create(RegistryLoaders.empty(HashSet::new)); + /** * A map containing all Java entity identifiers and their respective Geyser definitions */ diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 82717050f..175d9eac2 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -638,6 +638,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { public void connect() { startGame(); sentSpawnPacket = true; + syncEntityProperties(); // Set the hardcoded shield ID to the ID we just defined in StartGamePacket // upstream.getSession().getHardcodedBlockingId().set(this.itemMappings.getStoredItems().shield().getBedrockId()); @@ -1562,9 +1563,20 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { startGamePacket.setRewindHistorySize(0); startGamePacket.setServerAuthoritativeBlockBreaking(false); + // Entity properties for older versions + startGamePacket.getExperiments().add(new ExperimentData("upcoming_creator_features", true)); + upstream.sendPacket(startGamePacket); } + private void syncEntityProperties() { + for (NbtMap nbtMap : Registries.BEDROCK_ENTITY_PROPERTIES.get()) { + SyncEntityPropertyPacket syncEntityPropertyPacket = new SyncEntityPropertyPacket(); + syncEntityPropertyPacket.setData(nbtMap); + upstream.sendPacket(syncEntityPropertyPacket); + } + } + /** * @return the next Bedrock item network ID to use for a new item */ From 16cb76f52338293f0599c682c1a3674d125a832b Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Thu, 25 Apr 2024 17:38:03 +0200 Subject: [PATCH 292/344] neoforge 1.20.5 boots --- .../main/resources/META-INF/{mods.toml => neoforge.mods.toml} | 2 +- build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename bootstrap/mod/neoforge/src/main/resources/META-INF/{mods.toml => neoforge.mods.toml} (91%) diff --git a/bootstrap/mod/neoforge/src/main/resources/META-INF/mods.toml b/bootstrap/mod/neoforge/src/main/resources/META-INF/neoforge.mods.toml similarity index 91% rename from bootstrap/mod/neoforge/src/main/resources/META-INF/mods.toml rename to bootstrap/mod/neoforge/src/main/resources/META-INF/neoforge.mods.toml index 1110568e8..ff2823aa2 100644 --- a/bootstrap/mod/neoforge/src/main/resources/META-INF/mods.toml +++ b/bootstrap/mod/neoforge/src/main/resources/META-INF/neoforge.mods.toml @@ -20,6 +20,6 @@ config = "geyser.mixins.json" [[dependencies.geyser_neoforge]] modId="minecraft" type="required" - versionRange="[1.20.4,1.21)" + versionRange="[1.20.5,1.21)" ordering="NONE" side="BOTH" \ No newline at end of file diff --git a/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts b/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts index 3d41a3dd6..950c0184b 100644 --- a/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts @@ -23,7 +23,7 @@ indra { tasks { processResources { // Spigot, BungeeCord, Velocity, Fabric, ViaProxy, NeoForge - filesMatching(listOf("plugin.yml", "bungee.yml", "velocity-plugin.json", "fabric.mod.json", "viaproxy.yml", "META-INF/mods.toml")) { + filesMatching(listOf("plugin.yml", "bungee.yml", "velocity-plugin.json", "fabric.mod.json", "viaproxy.yml", "META-INF/neoforge.mods.toml")) { expand( "id" to "geyser", "name" to "Geyser", From 8e3a3ea45337d44bec2b3af8dbfaa615c9a01a7a Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Fri, 26 Apr 2024 01:00:14 +0200 Subject: [PATCH 293/344] implement curse of binding check for wolf armor removal --- .../geyser/entity/type/LivingEntity.java | 38 +++++++++++++++++-- .../entity/type/living/ArmorStandEntity.java | 17 +++++---- .../living/animal/tameable/WolfEntity.java | 15 +++++++- .../type/living/monster/PiglinEntity.java | 2 +- .../living/monster/raid/PillagerEntity.java | 2 +- .../translator/item/ItemTranslator.java | 8 ++-- .../entity/JavaEntityEventTranslator.java | 7 +--- .../entity/JavaSetEquipmentTranslator.java | 22 +++++------ .../org/geysermc/geyser/util/BlockUtils.java | 4 +- .../org/geysermc/geyser/util/ItemUtils.java | 5 ++- 10 files changed, 81 insertions(+), 39 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java index 5823ba3b2..b1e97a0d6 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java @@ -47,6 +47,7 @@ import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.item.ItemTranslator; import org.geysermc.geyser.util.AttributeUtils; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.Attribute; @@ -57,6 +58,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEn import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.FloatEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import java.util.*; @@ -69,7 +71,7 @@ public class LivingEntity extends Entity { protected ItemData leggings = ItemData.AIR; protected ItemData boots = ItemData.AIR; protected ItemData hand = ItemData.AIR; - protected ItemData offHand = ItemData.AIR; + protected ItemData offhand = ItemData.AIR; @Getter(value = AccessLevel.NONE) protected float health = 1f; // The default value in Java Edition before any entity metadata is sent @@ -85,6 +87,36 @@ public class LivingEntity extends Entity { super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); } + public void setHelmet(ItemStack stack) { + this.helmet = ItemTranslator.translateToBedrock(session, stack); + } + + public void setChestplate(ItemStack stack) { + this.chestplate = ItemTranslator.translateToBedrock(session, stack); + } + + public void setLeggings(ItemStack stack) { + this.leggings = ItemTranslator.translateToBedrock(session, stack); + } + + public void setBoots(ItemStack stack) { + this.boots = ItemTranslator.translateToBedrock(session, stack); + } + + public void setHand(ItemStack stack) { + this.hand = ItemTranslator.translateToBedrock(session, stack); + } + + public void setOffhand(ItemStack stack) { + this.offhand = ItemTranslator.translateToBedrock(session, stack); + } + + public void switchHands() { + ItemData offhand = this.offhand; + this.offhand = this.hand; + this.hand = offhand; + } + @Override protected void initializeMetadata() { super.initializeMetadata(); @@ -135,7 +167,7 @@ public class LivingEntity extends Entity { protected boolean hasShield(boolean offhand) { ItemMapping shieldMapping = session.getItemMappings().getStoredItems().shield(); if (offhand) { - return offHand.getDefinition().equals(shieldMapping.getBedrockDefinition()); + return this.offhand.getDefinition().equals(shieldMapping.getBedrockDefinition()); } else { return hand.getDefinition().equals(shieldMapping.getBedrockDefinition()); } @@ -247,7 +279,7 @@ public class LivingEntity extends Entity { MobEquipmentPacket offHandPacket = new MobEquipmentPacket(); offHandPacket.setRuntimeEntityId(geyserId); - offHandPacket.setItem(offHand); + offHandPacket.setItem(offhand); offHandPacket.setHotbarSlot(-1); offHandPacket.setInventorySlot(0); offHandPacket.setContainerId(ContainerId.OFFHAND); diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java index c64f2f218..fce51e741 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java @@ -43,6 +43,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetad import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import java.util.Optional; import java.util.UUID; @@ -257,38 +258,38 @@ public class ArmorStandEntity extends LivingEntity { } @Override - public void setHelmet(ItemData helmet) { + public void setHelmet(ItemStack helmet) { super.setHelmet(helmet); updateSecondEntityStatus(true); } @Override - public void setChestplate(ItemData chestplate) { + public void setChestplate(ItemStack chestplate) { super.setChestplate(chestplate); updateSecondEntityStatus(true); } @Override - public void setLeggings(ItemData leggings) { + public void setLeggings(ItemStack leggings) { super.setLeggings(leggings); updateSecondEntityStatus(true); } @Override - public void setBoots(ItemData boots) { + public void setBoots(ItemStack boots) { super.setBoots(boots); updateSecondEntityStatus(true); } @Override - public void setHand(ItemData hand) { + public void setHand(ItemStack hand) { super.setHand(hand); updateSecondEntityStatus(true); } @Override - public void setOffHand(ItemData offHand) { - super.setOffHand(offHand); + public void setOffhand(ItemStack offHand) { + super.setOffhand(offHand); updateSecondEntityStatus(true); } @@ -324,7 +325,7 @@ public class ArmorStandEntity extends LivingEntity { } boolean isNametagEmpty = nametag.isEmpty(); if (!isNametagEmpty && (!helmet.equals(ItemData.AIR) || !chestplate.equals(ItemData.AIR) || !leggings.equals(ItemData.AIR) - || !boots.equals(ItemData.AIR) || !hand.equals(ItemData.AIR) || !offHand.equals(ItemData.AIR))) { + || !boots.equals(ItemData.AIR) || !hand.equals(ItemData.AIR) || !offhand.equals(ItemData.AIR))) { // Reset scale of the proper armor stand this.dirtyMetadata.put(EntityDataTypes.SCALE, getScale()); // Set the proper armor stand to invisible to show armor diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java index 29c3526fe..833d0e175 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java @@ -33,15 +33,19 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.inventory.GeyserItemStack; +import org.geysermc.geyser.inventory.item.Enchantment; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.DyeItem; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; +import org.geysermc.geyser.util.ItemUtils; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import java.util.Collections; import java.util.Locale; @@ -60,6 +64,8 @@ public class WolfEntity extends TameableEntity { private byte collarColor = 14; // Red - default + private boolean isCurseOfBinding = false; + public WolfEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); } @@ -119,6 +125,12 @@ public class WolfEntity extends TameableEntity { return WOLF_FOODS.contains(item) && !isBaby(); } + @Override + public void setChestplate(ItemStack stack) { + super.setChestplate(stack); + isCurseOfBinding = ItemUtils.getEnchantmentLevel(stack.getDataComponents(), Enchantment.JavaEnchantment.BINDING_CURSE) > 0; + } + @Override protected boolean canBeLeashed() { return !getFlag(EntityFlag.ANGRY) && super.canBeLeashed(); @@ -146,7 +158,8 @@ public class WolfEntity extends TameableEntity { if (itemInHand.asItem() == Items.WOLF_ARMOR && !this.chestplate.isValid() && !getFlag(EntityFlag.BABY)) { return InteractiveTag.EQUIP_WOLF_ARMOR; } - if (itemInHand.asItem() == Items.SHEARS && this.chestplate.isValid()) { // TODO: check curse of binding + if (itemInHand.asItem() == Items.SHEARS && this.chestplate.isValid() + && (!isCurseOfBinding || session.getGameMode().equals(GameMode.CREATIVE))) { return InteractiveTag.REMOVE_WOLF_ARMOR; } if (Items.WOLF_ARMOR.isValidRepairItem(itemInHand.asItem()) && getFlag(EntityFlag.SITTING) && diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java index db2a3ecc3..9c43ab23a 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java @@ -66,7 +66,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 - setFlag(EntityFlag.ADMIRING, session.getTagCache().is(ItemTag.PIGLIN_LOVED, session.getItemMappings().getMapping(this.offHand).getJavaItem())); + setFlag(EntityFlag.ADMIRING, session.getTagCache().is(ItemTag.PIGLIN_LOVED, session.getItemMappings().getMapping(this.offhand).getJavaItem())); super.updateBedrockMetadata(); super.updateOffHand(session); diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/PillagerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/PillagerEntity.java index d2f8377d3..1d2d9115b 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/PillagerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/PillagerEntity.java @@ -59,7 +59,7 @@ public class PillagerEntity extends AbstractIllagerEntity { protected void checkForCrossbow() { ItemMapping crossbow = session.getItemMappings().getStoredItems().crossbow(); boolean hasCrossbow = this.hand.getDefinition() == crossbow.getBedrockDefinition() - || this.offHand.getDefinition() == crossbow.getBedrockDefinition(); + || this.offhand.getDefinition() == crossbow.getBedrockDefinition(); setFlag(EntityFlag.USING_ITEM, hasCrossbow); setFlag(EntityFlag.CHARGED, hasCrossbow); diff --git a/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java index 24362f800..a744c4822 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java @@ -360,7 +360,7 @@ public final class ItemTranslator { } if (mapping.getJavaItem().equals(Items.PLAYER_HEAD)) { - CustomSkull customSkull = getCustomSkull(session, itemStack.getComponents()); + CustomSkull customSkull = getCustomSkull(itemStack.getComponents()); if (customSkull != null) { itemDefinition = session.getItemMappings().getCustomBlockItemDefinitions().get(customSkull.getCustomBlockData()); } @@ -552,7 +552,7 @@ public final class ItemTranslator { builder.blockDefinition(blockDefinition); } - private static @Nullable CustomSkull getCustomSkull(GeyserSession session, DataComponents components) { + private static @Nullable CustomSkull getCustomSkull(DataComponents components) { if (components == null) { return null; } @@ -563,7 +563,7 @@ public final class ItemTranslator { try { textures = profile.getTextures(false); } catch (PropertyException e) { - session.getGeyser().getLogger().debug("Failed to get textures from GameProfile: " + e); + GeyserImpl.getInstance().getLogger().debug("Failed to get textures from GameProfile: " + e); } if (textures == null || textures.isEmpty()) { @@ -583,7 +583,7 @@ public final class ItemTranslator { } private static void translatePlayerHead(GeyserSession session, DataComponents components, ItemData.Builder builder) { - CustomSkull customSkull = getCustomSkull(session, components); + CustomSkull customSkull = getCustomSkull(components); if (customSkull != null) { CustomBlockData customBlockData = customSkull.getCustomBlockData(); ItemDefinition itemDefinition = session.getItemMappings().getCustomBlockItemDefinitions().get(customBlockData); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaEntityEventTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaEntityEventTranslator.java index fbabd4afa..db9874af4 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaEntityEventTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaEntityEventTranslator.java @@ -25,12 +25,10 @@ package org.geysermc.geyser.translator.protocol.java.entity; -import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundEntityEventPacket; import org.cloudburstmc.protocol.bedrock.data.ParticleType; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType; -import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket; import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket; import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEvent2Packet; @@ -46,6 +44,7 @@ import org.geysermc.geyser.entity.type.living.monster.WardenEntity; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundEntityEventPacket; import java.util.concurrent.ThreadLocalRandom; @@ -223,9 +222,7 @@ public class JavaEntityEventTranslator extends PacketTranslator { @@ -58,7 +56,7 @@ public class JavaSetEquipmentTranslator extends PacketTranslator { ItemStack javaItem = equipment.getItem(); @@ -71,28 +69,28 @@ public class JavaSetEquipmentTranslator extends PacketTranslator { // BODY is sent for llamas with a carpet equipped, as of 1.20.5 - livingEntity.setChestplate(item); + livingEntity.setChestplate(stack); armorUpdated = true; } case LEGGINGS -> { - livingEntity.setLeggings(item); + livingEntity.setLeggings(stack); armorUpdated = true; } case BOOTS -> { - livingEntity.setBoots(item); + livingEntity.setBoots(stack); armorUpdated = true; } case MAIN_HAND -> { - livingEntity.setHand(item); + livingEntity.setHand(stack); mainHandUpdated = true; } case OFF_HAND -> { - livingEntity.setOffHand(item); + livingEntity.setOffhand(stack); offHandUpdated = true; } } diff --git a/core/src/main/java/org/geysermc/geyser/util/BlockUtils.java b/core/src/main/java/org/geysermc/geyser/util/BlockUtils.java index 0fc7a39e7..70102c2b0 100644 --- a/core/src/main/java/org/geysermc/geyser/util/BlockUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/BlockUtils.java @@ -145,7 +145,7 @@ public final class BlockUtils { toolCanBreak = canToolTierBreakBlock(session, blockMapping, toolTier); } - int toolEfficiencyLevel = ItemUtils.getEnchantmentLevel(components, Enchantment.JavaEnchantment.EFFICIENCY.ordinal()); + int toolEfficiencyLevel = ItemUtils.getEnchantmentLevel(components, Enchantment.JavaEnchantment.EFFICIENCY); int hasteLevel = 0; int miningFatigueLevel = 0; @@ -160,7 +160,7 @@ public final class BlockUtils { boolean waterInEyes = session.getCollisionManager().isWaterInEyes(); boolean insideOfWaterWithoutAquaAffinity = waterInEyes && - ItemUtils.getEnchantmentLevel(session.getPlayerInventory().getItem(5).getComponents(), Enchantment.JavaEnchantment.AQUA_AFFINITY.ordinal()) < 1; + ItemUtils.getEnchantmentLevel(session.getPlayerInventory().getItem(5).getComponents(), Enchantment.JavaEnchantment.AQUA_AFFINITY) < 1; return calculateBreakTime(blockMapping.getHardness(), toolTier, canHarvestWithHand, correctTool, toolCanBreak, toolType, isShearsEffective, toolEfficiencyLevel, hasteLevel, miningFatigueLevel, insideOfWaterWithoutAquaAffinity, session.getPlayerEntity().isOnGround()); diff --git a/core/src/main/java/org/geysermc/geyser/util/ItemUtils.java b/core/src/main/java/org/geysermc/geyser/util/ItemUtils.java index 1b47c3a00..c9d9903d4 100644 --- a/core/src/main/java/org/geysermc/geyser/util/ItemUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/ItemUtils.java @@ -27,6 +27,7 @@ package org.geysermc.geyser.util; import net.kyori.adventure.text.Component; import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.geyser.inventory.item.Enchantment; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.FishingRodItem; import org.geysermc.geyser.item.type.Item; @@ -36,7 +37,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemEnchantm public class ItemUtils { - public static int getEnchantmentLevel(@Nullable DataComponents components, int enchantmentId) { + public static int getEnchantmentLevel(@Nullable DataComponents components, Enchantment.JavaEnchantment enchantment) { if (components == null) { return 0; } @@ -46,7 +47,7 @@ public class ItemUtils { return 0; } - return enchantmentData.getEnchantments().getOrDefault(enchantmentId, 0); + return enchantmentData.getEnchantments().getOrDefault(enchantment.ordinal(), 0); } /** From 3656395ce11b028ae3c1c5b8fbe4f783664b846d Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Thu, 25 Apr 2024 21:03:17 -0400 Subject: [PATCH 294/344] Armadillo states --- .../entity/properties/type/EnumProperty.java | 2 +- .../type/living/animal/ArmadilloEntity.java | 25 ++++++++++++++++--- .../entity/JavaEntityEventTranslator.java | 6 +++++ gradle/libs.versions.toml | 2 +- 4 files changed, 30 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/entity/properties/type/EnumProperty.java b/core/src/main/java/org/geysermc/geyser/entity/properties/type/EnumProperty.java index 9bc45f560..05e12ba61 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/properties/type/EnumProperty.java +++ b/core/src/main/java/org/geysermc/geyser/entity/properties/type/EnumProperty.java @@ -50,7 +50,7 @@ public class EnumProperty implements PropertyType { public NbtMap nbtMap() { return NbtMap.builder() .putString("name", name) - .putList("values", NbtType.STRING, values) + .putList("enum", NbtType.STRING, values) .putInt("type", 3) .build(); } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ArmadilloEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ArmadilloEntity.java index 205c8cbd9..51fe09383 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ArmadilloEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ArmadilloEntity.java @@ -32,23 +32,42 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.ArmadilloSt import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ObjectEntityMetadata; import java.util.UUID; +import java.util.concurrent.TimeUnit; public class ArmadilloEntity extends AnimalEntity { + private ArmadilloState armadilloState = ArmadilloState.IDLE; + public ArmadilloEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); } - // TODO: This is completely wrong; probably need to store the previous IDLE/ROLLING/SCARED state and check for transitions (pain) public void setArmadilloState(ObjectEntityMetadata entityMetadata) { - ArmadilloState armadilloState = entityMetadata.getValue(); + armadilloState = entityMetadata.getValue(); switch (armadilloState) { case IDLE -> propertyManager.add("minecraft:armadillo_state", "unrolled"); case ROLLING -> propertyManager.add("minecraft:armadillo_state", "rolled_up"); - case SCARED -> propertyManager.add("minecraft:armadillo_state", "rolled_up_peeking"); + case SCARED -> propertyManager.add("minecraft:armadillo_state", "rolled_up_relaxing"); + case UNROLLING -> propertyManager.add("minecraft:armadillo_state", "rolled_up_unrolling"); } updateBedrockEntityProperties(); } + + public void onPeeking() { + // Technically we should wait if not currently scared + if (armadilloState == ArmadilloState.SCARED) { + propertyManager.add("minecraft:armadillo_state", "rolled_up_peeking"); + updateBedrockEntityProperties(); + + // Needed for consecutive peeks + session.scheduleInEventLoop(() -> { + if (armadilloState == ArmadilloState.SCARED) { + propertyManager.add("minecraft:armadillo_state", "rolled_up_relaxing"); + updateBedrockEntityProperties(); + } + }, 250, TimeUnit.MILLISECONDS); + } + } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaEntityEventTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaEntityEventTranslator.java index db9874af4..e119d39ce 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaEntityEventTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaEntityEventTranslator.java @@ -40,6 +40,7 @@ import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.EvokerFangsEntity; import org.geysermc.geyser.entity.type.FishingHookEntity; import org.geysermc.geyser.entity.type.LivingEntity; +import org.geysermc.geyser.entity.type.living.animal.ArmadilloEntity; import org.geysermc.geyser.entity.type.living.monster.WardenEntity; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; @@ -257,6 +258,11 @@ public class JavaEntityEventTranslator extends PacketTranslator Date: Fri, 26 Apr 2024 14:50:48 +0200 Subject: [PATCH 295/344] idea: deal with cookies and transfer --- .../api/event/bedrock/SessionLoginEvent.java | 43 ++++++++++- .../api/event/java/ServerTransferEvent.java | 71 +++++++++++++++++++ .../platform/spigot/GeyserSpigotInjector.java | 3 +- .../geyser/item/type/WrittenBookItem.java | 1 - .../geyser/network/netty/LocalSession.java | 7 +- .../geyser/session/GeyserSession.java | 11 ++- .../player/JavaCookieRequestTranslator.java | 42 +++++++++++ .../player/JavaStoreCookieTranslator.java | 37 ++++++++++ .../player/JavaTransferPacketTranslator.java | 43 +++++++++++ 9 files changed, 251 insertions(+), 7 deletions(-) create mode 100644 api/src/main/java/org/geysermc/geyser/api/event/java/ServerTransferEvent.java create mode 100644 core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaCookieRequestTranslator.java create mode 100644 core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaStoreCookieTranslator.java create mode 100644 core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaTransferPacketTranslator.java diff --git a/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionLoginEvent.java b/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionLoginEvent.java index c3c8198c1..522562d11 100644 --- a/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionLoginEvent.java +++ b/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionLoginEvent.java @@ -32,6 +32,9 @@ import org.geysermc.geyser.api.connection.GeyserConnection; import org.geysermc.geyser.api.event.connection.ConnectionEvent; import org.geysermc.geyser.api.network.RemoteServer; +import java.util.Map; +import java.util.Objects; + /** * Called when a session has logged in, and is about to connect to a remote java server. * This event is cancellable, and can be used to prevent the player from connecting to the remote server. @@ -40,10 +43,16 @@ public final class SessionLoginEvent extends ConnectionEvent implements Cancella private RemoteServer remoteServer; private boolean cancelled; private String disconnectReason; + private Map cookies; + private boolean transferring; - public SessionLoginEvent(@NonNull GeyserConnection connection, @NonNull RemoteServer remoteServer) { + public SessionLoginEvent(@NonNull GeyserConnection connection, + @NonNull RemoteServer remoteServer, + @NonNull Map cookies) { super(connection); this.remoteServer = remoteServer; + this.cookies = cookies; + this.transferring = false; } /** @@ -106,4 +115,36 @@ public final class SessionLoginEvent extends ConnectionEvent implements Cancella public void remoteServer(@NonNull RemoteServer remoteServer) { this.remoteServer = remoteServer; } + + /** + * Sets a map of cookies from a possible previous session. The Java server can send and request these + * to store information on the client across server transfers. + */ + public void cookies(@NonNull Map cookies) { + Objects.requireNonNull(cookies); + this.cookies = cookies; + } + + /** + * Gets a map of the sessions cookies, if set. + * @return the connections cookies + */ + public @NonNull Map cookies() { + return cookies; + } + + /** + * Determines the connection intent of the connection + */ + public void transferring(boolean transferring) { + this.transferring = transferring; + } + + /** + * Gets whether this login attempt to the Java server + * has the transfer intent + */ + public boolean transferring() { + return this.transferring; + } } diff --git a/api/src/main/java/org/geysermc/geyser/api/event/java/ServerTransferEvent.java b/api/src/main/java/org/geysermc/geyser/api/event/java/ServerTransferEvent.java new file mode 100644 index 000000000..afdf596c2 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/event/java/ServerTransferEvent.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2019-2024 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.api.event.java; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.api.connection.GeyserConnection; +import org.geysermc.geyser.api.event.connection.ConnectionEvent; + +import java.util.Map; + +public class ServerTransferEvent extends ConnectionEvent { + + private final String host; + private final int port; + private final Map cookies; + + public ServerTransferEvent(@NonNull GeyserConnection connection, String host, int port, Map cookies) { + super(connection); + this.host = host; + this.port = port; + this.cookies = cookies; + } + + /** + * The host that the Java server requests a transfer to. + * @return the host + */ + public String host() { + return this.host; + } + + /** + * The port that the Java server requests a transfer to. + * @return the port + */ + public int port() { + return this.port; + } + + /** + * Gets a map of the sessions current cookies. + * @return the connections cookies + */ + public @NonNull Map cookies() { + return cookies; + } + +} diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java index 43ecf7154..6aa5d563f 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java @@ -175,8 +175,9 @@ public class GeyserSpigotInjector extends GeyserInjector { MinecraftProtocol protocol = new MinecraftProtocol(); LocalSession session = new LocalSession(bootstrap.getGeyserConfig().getRemote().address(), bootstrap.getGeyserConfig().getRemote().port(), this.serverSocketAddress, - InetAddress.getLoopbackAddress().getHostAddress(), protocol, protocol.createHelper()); + InetAddress.getLoopbackAddress().getHostAddress(), protocol, protocol.createHelper(), false); session.connect(); + session.disconnect(""); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java b/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java index a11c4f583..4a2028fc7 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java @@ -70,6 +70,5 @@ public class WrittenBookItem extends Item { builder.putString("title", bookContent.getTitle().getRaw()) .putString("author", bookContent.getAuthor()) .putInt("generation", bookContent.getGeneration()); - // TODO isResolved } } diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java b/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java index 19b0b423f..b5598d063 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java @@ -54,11 +54,14 @@ public final class LocalSession extends TcpSession { private final String clientIp; private final PacketCodecHelper codecHelper; - public LocalSession(String host, int port, SocketAddress targetAddress, String clientIp, PacketProtocol protocol, MinecraftCodecHelper codecHelper) { + private final boolean transferring; + + public LocalSession(String host, int port, SocketAddress targetAddress, String clientIp, PacketProtocol protocol, MinecraftCodecHelper codecHelper, boolean transferring) { super(host, port, protocol); this.targetAddress = targetAddress; this.clientIp = clientIp; this.codecHelper = codecHelper; + this.transferring = transferring; } @Override @@ -79,7 +82,7 @@ public final class LocalSession extends TcpSession { public void initChannel(@NonNull LocalChannelWithRemoteAddress channel) { channel.spoofedRemoteAddress(new InetSocketAddress(clientIp, 0)); PacketProtocol protocol = getPacketProtocol(); - protocol.newClientSession(LocalSession.this, false); + protocol.newClientSession(LocalSession.this, transferring); refreshReadTimeoutHandler(channel); refreshWriteTimeoutHandler(channel); diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 175d9eac2..869999357 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -569,6 +569,12 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { @Setter private @Nullable ItemData currentBook = null; + /** + * Stores cookies sent by the Java server. + */ + @Setter @Getter + private Map cookies = new Object2ObjectOpenHashMap<>(); + private final GeyserCameraData cameraData; private final GeyserEntityData entityData; @@ -853,7 +859,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { * After getting whatever credentials needed, we attempt to join the Java server. */ private void connectDownstream() { - SessionLoginEvent loginEvent = new SessionLoginEvent(this, remoteServer); + SessionLoginEvent loginEvent = new SessionLoginEvent(this, remoteServer, new Object2ObjectOpenHashMap<>()); GeyserImpl.getInstance().eventBus().fire(loginEvent); if (loginEvent.isCancelled()) { String disconnectReason = loginEvent.disconnectReason() == null ? @@ -862,6 +868,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { return; } + this.cookies = loginEvent.cookies(); this.remoteServer = loginEvent.remoteServer(); boolean floodgate = this.remoteServer.authType() == AuthType.FLOODGATE; @@ -873,7 +880,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { // We're going to connect through the JVM and not through TCP downstream = new LocalSession(this.remoteServer.address(), this.remoteServer.port(), geyser.getBootstrap().getSocketAddress(), upstream.getAddress().getAddress().getHostAddress(), - this.protocol, this.protocol.createHelper()); + this.protocol, this.protocol.createHelper(), loginEvent.transferring()); this.downstream = new DownstreamSession(downstream); } else { downstream = new TcpClientSession(this.remoteServer.address(), this.remoteServer.port(), this.protocol); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaCookieRequestTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaCookieRequestTranslator.java new file mode 100644 index 000000000..06f020423 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaCookieRequestTranslator.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019-2024 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.translator.protocol.java.entity.player; + +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.protocol.PacketTranslator; +import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundCookieRequestPacket; +import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ServerboundCookieResponsePacket; + +public class JavaCookieRequestTranslator extends PacketTranslator { + @Override + public void translate(GeyserSession session, ClientboundCookieRequestPacket packet) { + ServerboundCookieResponsePacket responsePacket = new ServerboundCookieResponsePacket( + packet.getKey(), + session.getCookies().get(packet.getKey()) + ); + session.sendDownstreamPacket(responsePacket); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaStoreCookieTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaStoreCookieTranslator.java new file mode 100644 index 000000000..499dfda8d --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaStoreCookieTranslator.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2019-2024 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.translator.protocol.java.entity.player; + +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.protocol.PacketTranslator; +import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundStoreCookiePacket; + +public class JavaStoreCookieTranslator extends PacketTranslator { + @Override + public void translate(GeyserSession session, ClientboundStoreCookiePacket packet) { + session.getCookies().put(packet.getKey(), packet.getPayload()); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaTransferPacketTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaTransferPacketTranslator.java new file mode 100644 index 000000000..1e9bd1537 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaTransferPacketTranslator.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019-2024 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.translator.protocol.java.entity.player; + +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.event.java.ServerTransferEvent; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.protocol.PacketTranslator; +import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundTransferPacket; + +public class JavaTransferPacketTranslator extends PacketTranslator { + @Override + public void translate(GeyserSession session, ClientboundTransferPacket packet) { + GeyserImpl.getInstance().eventBus().fire(new ServerTransferEvent( + session, + packet.getHost(), + packet.getPort(), + session.getCookies())); + } +} From f67c131b8d06f938a10f9eb0f52a6f4ab2b1423a Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Fri, 26 Apr 2024 15:36:26 +0200 Subject: [PATCH 296/344] Forcibly disconnect players even if no server target was set in the JavaTransferEvent --- .../api/event/java/ServerTransferEvent.java | 52 +++++++++++++++++++ .../player/JavaCookieRequestTranslator.java | 2 + .../player/JavaStoreCookieTranslator.java | 2 + .../player/JavaTransferPacketTranslator.java | 15 +++++- 4 files changed, 69 insertions(+), 2 deletions(-) diff --git a/api/src/main/java/org/geysermc/geyser/api/event/java/ServerTransferEvent.java b/api/src/main/java/org/geysermc/geyser/api/event/java/ServerTransferEvent.java index afdf596c2..b3b580ec3 100644 --- a/api/src/main/java/org/geysermc/geyser/api/event/java/ServerTransferEvent.java +++ b/api/src/main/java/org/geysermc/geyser/api/event/java/ServerTransferEvent.java @@ -26,15 +26,22 @@ package org.geysermc.geyser.api.event.java; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.common.value.qual.IntRange; import org.geysermc.geyser.api.connection.GeyserConnection; import org.geysermc.geyser.api.event.connection.ConnectionEvent; import java.util.Map; +/** + * Fired when the Java server sends a transfer request to a different Java server. + * Geyser Extensions can listen to this event and set a target server ip/port for Bedrock players to be transferred to. + */ public class ServerTransferEvent extends ConnectionEvent { private final String host; private final int port; + private String bedrockHost; + private int bedrockPort; private final Map cookies; public ServerTransferEvent(@NonNull GeyserConnection connection, String host, int port, Map cookies) { @@ -42,10 +49,13 @@ public class ServerTransferEvent extends ConnectionEvent { this.host = host; this.port = port; this.cookies = cookies; + this.bedrockHost = null; + this.bedrockPort = -1; } /** * The host that the Java server requests a transfer to. + * * @return the host */ public String host() { @@ -54,14 +64,56 @@ public class ServerTransferEvent extends ConnectionEvent { /** * The port that the Java server requests a transfer to. + * * @return the port */ public int port() { return this.port; } + /** + * The host that the Bedrock player should try and connect to. + * If this is not set, the Bedrock player will just be disconnected. + * + * @return the host where the Bedrock client will be transferred to, or null if not set. + */ + public String bedrockHost() { + return this.bedrockHost; + } + + /** + * The port that the Bedrock player should try and connect to. + * If this is not set, the Bedrock player will just be disconnected. + * + * @return the port where the Bedrock client will be transferred to, or -1 if not set. + */ + public int bedrockPort() { + return this.bedrockPort; + } + + /** + * Sets the host for the Bedrock player to be transferred to + */ + public void bedrockHost(@NonNull String host) { + if (host == null || host.isBlank()) { + throw new IllegalArgumentException("Server address cannot be null or blank"); + } + this.bedrockHost = host; + } + + /** + * Sets the port for the Bedrock player to be transferred to + */ + public void bedrockPort(@IntRange(from = 0, to = 65535) int port) { + if (port < 0 || port > 65535) { + throw new IllegalArgumentException("Server port must be between 0 and 65535, was " + port); + } + this.bedrockPort = port; + } + /** * Gets a map of the sessions current cookies. + * * @return the connections cookies */ public @NonNull Map cookies() { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaCookieRequestTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaCookieRequestTranslator.java index 06f020423..5266ebabd 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaCookieRequestTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaCookieRequestTranslator.java @@ -27,9 +27,11 @@ package org.geysermc.geyser.translator.protocol.java.entity.player; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; +import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundCookieRequestPacket; import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ServerboundCookieResponsePacket; +@Translator(packet = ClientboundCookieRequestPacket.class) public class JavaCookieRequestTranslator extends PacketTranslator { @Override public void translate(GeyserSession session, ClientboundCookieRequestPacket packet) { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaStoreCookieTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaStoreCookieTranslator.java index 499dfda8d..19237b646 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaStoreCookieTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaStoreCookieTranslator.java @@ -27,8 +27,10 @@ package org.geysermc.geyser.translator.protocol.java.entity.player; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; +import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundStoreCookiePacket; +@Translator(packet = ClientboundStoreCookiePacket.class) public class JavaStoreCookieTranslator extends PacketTranslator { @Override public void translate(GeyserSession session, ClientboundStoreCookiePacket packet) { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaTransferPacketTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaTransferPacketTranslator.java index 1e9bd1537..86fd70677 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaTransferPacketTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaTransferPacketTranslator.java @@ -28,16 +28,27 @@ package org.geysermc.geyser.translator.protocol.java.entity.player; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.event.java.ServerTransferEvent; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.translator.protocol.PacketTranslator; +import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundTransferPacket; +@Translator(packet = ClientboundTransferPacket.class) public class JavaTransferPacketTranslator extends PacketTranslator { @Override public void translate(GeyserSession session, ClientboundTransferPacket packet) { - GeyserImpl.getInstance().eventBus().fire(new ServerTransferEvent( + ServerTransferEvent event = new ServerTransferEvent( session, packet.getHost(), packet.getPort(), - session.getCookies())); + session.getCookies()); + + GeyserImpl.getInstance().eventBus().fire(event); + + if (event.bedrockHost() != null && !event.bedrockHost().isBlank() && event.bedrockPort() != -1) { + session.transfer(event.bedrockHost(), event.bedrockPort()); + } else { + session.disconnect(MinecraftLocale.getLocaleString("disconnect.transfer", session.locale())); + } } } From 5015a2ef895a2f51a1bc3d08c824d98025d3e8ff Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Fri, 26 Apr 2024 15:41:05 +0200 Subject: [PATCH 297/344] bump project version to 2.3.0 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index a7c0bf93d..dd61d2556 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,5 +7,5 @@ org.gradle.vfs.watch=false group=org.geysermc id=geyser -version=2.2.3-SNAPSHOT +version=2.3.0-SNAPSHOT description=Allows for players from Minecraft: Bedrock Edition to join Minecraft: Java Edition servers. From a57e7b54dc93ad23c82c1c3c4233678b5f16dffe Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 26 Apr 2024 16:36:47 +0200 Subject: [PATCH 298/344] Update ViaVersion api usage to be compatible with ViaVersion 4.10 (#4606) --- .../world/manager/GeyserSpigotLegacyNativeWorldManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotLegacyNativeWorldManager.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotLegacyNativeWorldManager.java index 021db5ec1..d3d492553 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotLegacyNativeWorldManager.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotLegacyNativeWorldManager.java @@ -58,7 +58,7 @@ public class GeyserSpigotLegacyNativeWorldManager extends GeyserSpigotNativeWorl int newBlockId = oldBlockId; // protocolList should *not* be null; we checked for that before initializing this class for (int i = protocolList.size() - 1; i >= 0; i--) { - MappingData mappingData = protocolList.get(i).getProtocol().getMappingData(); + MappingData mappingData = protocolList.get(i).protocol().getMappingData(); if (mappingData != null) { newBlockId = mappingData.getNewBlockStateId(newBlockId); } From 42a9ba617bb11c7da5073eb7c3c8ec60a3102984 Mon Sep 17 00:00:00 2001 From: RK_01 <50594595+RaphiMC@users.noreply.github.com> Date: Fri, 26 Apr 2024 20:06:37 +0200 Subject: [PATCH 299/344] Update ViaProxy platform (#4607) * Update ViaProxy API usage * Don't reference ViaProxy API in dummy application --- .../viaproxy/GeyserViaProxyConfiguration.java | 4 ++-- .../platform/viaproxy/GeyserViaProxyDumpInfo.java | 5 ++--- .../geyser/platform/viaproxy/GeyserViaProxyMain.java | 3 +-- .../platform/viaproxy/GeyserViaProxyPlugin.java | 11 +++++------ bootstrap/viaproxy/src/main/resources/viaproxy.yml | 2 +- gradle/libs.versions.toml | 2 +- 6 files changed, 12 insertions(+), 15 deletions(-) diff --git a/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyConfiguration.java b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyConfiguration.java index ad249eb3b..bf9d6816c 100644 --- a/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyConfiguration.java +++ b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyConfiguration.java @@ -26,7 +26,7 @@ package org.geysermc.geyser.platform.viaproxy; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import net.raphimc.vialegacy.api.LegacyProtocolVersion; -import net.raphimc.viaproxy.cli.options.Options; +import net.raphimc.viaproxy.ViaProxy; import org.geysermc.geyser.configuration.GeyserJacksonConfiguration; import java.io.File; @@ -43,7 +43,7 @@ public class GeyserViaProxyConfiguration extends GeyserJacksonConfiguration { @Override public int getPingPassthroughInterval() { int interval = super.getPingPassthroughInterval(); - if (interval < 15 && Options.PROTOCOL_VERSION != null && Options.PROTOCOL_VERSION.olderThanOrEqualTo(LegacyProtocolVersion.r1_6_4)) { + if (interval < 15 && ViaProxy.getConfig().getTargetVersion() != null && ViaProxy.getConfig().getTargetVersion().olderThanOrEqualTo(LegacyProtocolVersion.r1_6_4)) { // <= 1.6.4 servers sometimes block incoming connections from an IP address if too many connections are made interval = 15; } diff --git a/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyDumpInfo.java b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyDumpInfo.java index 08f3d5371..0bfc9d022 100644 --- a/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyDumpInfo.java +++ b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyDumpInfo.java @@ -26,7 +26,6 @@ package org.geysermc.geyser.platform.viaproxy; import lombok.Getter; import net.raphimc.viaproxy.ViaProxy; -import net.raphimc.viaproxy.cli.options.Options; import net.raphimc.viaproxy.plugins.ViaProxyPlugin; import org.geysermc.geyser.dump.BootstrapDumpInfo; import org.geysermc.geyser.text.AsteriskSerializer; @@ -49,8 +48,8 @@ public class GeyserViaProxyDumpInfo extends BootstrapDumpInfo { public GeyserViaProxyDumpInfo() { this.platformVersion = ViaProxy.VERSION; - this.onlineMode = Options.ONLINE_MODE; - if (Options.BIND_ADDRESS instanceof InetSocketAddress inetSocketAddress) { + this.onlineMode = ViaProxy.getConfig().isProxyOnlineMode(); + if (ViaProxy.getConfig().getBindAddress() instanceof InetSocketAddress inetSocketAddress) { this.serverIP = inetSocketAddress.getHostString(); this.serverPort = inetSocketAddress.getPort(); } else { diff --git a/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyMain.java b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyMain.java index 675c92534..582a97d78 100644 --- a/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyMain.java +++ b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyMain.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.platform.viaproxy; -import net.raphimc.viaproxy.plugins.PluginManager; import org.geysermc.geyser.GeyserMain; public class GeyserViaProxyMain extends GeyserMain { @@ -39,7 +38,7 @@ public class GeyserViaProxyMain extends GeyserMain { } public String getPluginFolder() { - return PluginManager.PLUGINS_DIR.getName(); + return "plugins"; } } diff --git a/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyPlugin.java b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyPlugin.java index 47745df7d..30404e705 100644 --- a/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyPlugin.java +++ b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyPlugin.java @@ -27,7 +27,6 @@ package org.geysermc.geyser.platform.viaproxy; import net.lenni0451.lambdaevents.EventHandler; import net.raphimc.vialegacy.api.LegacyProtocolVersion; import net.raphimc.viaproxy.ViaProxy; -import net.raphimc.viaproxy.cli.options.Options; import net.raphimc.viaproxy.plugins.PluginManager; import net.raphimc.viaproxy.plugins.ViaProxyPlugin; import net.raphimc.viaproxy.plugins.events.ConsoleCommandEvent; @@ -137,7 +136,7 @@ public class GeyserViaProxyPlugin extends ViaProxyPlugin implements GeyserBootst GeyserImpl.start(); - if (Options.PROTOCOL_VERSION != null && Options.PROTOCOL_VERSION.newerThanOrEqualTo(LegacyProtocolVersion.b1_8tob1_8_1)) { + if (ViaProxy.getConfig().getTargetVersion() != null && ViaProxy.getConfig().getTargetVersion().newerThanOrEqualTo(LegacyProtocolVersion.b1_8tob1_8_1)) { // Only initialize the ping passthrough if the protocol version is above beta 1.7.3, as that's when the status protocol was added this.pingPassthrough = GeyserLegacyPingPassthrough.init(this.geyser); } @@ -186,19 +185,19 @@ public class GeyserViaProxyPlugin extends ViaProxyPlugin implements GeyserBootst @NotNull @Override public String getServerBindAddress() { - if (Options.BIND_ADDRESS instanceof InetSocketAddress socketAddress) { + if (ViaProxy.getConfig().getBindAddress() instanceof InetSocketAddress socketAddress) { return socketAddress.getHostString(); } else { - throw new IllegalStateException("Unsupported bind address type: " + Options.BIND_ADDRESS.getClass().getName()); + throw new IllegalStateException("Unsupported bind address type: " + ViaProxy.getConfig().getBindAddress().getClass().getName()); } } @Override public int getServerPort() { - if (Options.BIND_ADDRESS instanceof InetSocketAddress socketAddress) { + if (ViaProxy.getConfig().getBindAddress() instanceof InetSocketAddress socketAddress) { return socketAddress.getPort(); } else { - throw new IllegalStateException("Unsupported bind address type: " + Options.BIND_ADDRESS.getClass().getName()); + throw new IllegalStateException("Unsupported bind address type: " + ViaProxy.getConfig().getBindAddress().getClass().getName()); } } diff --git a/bootstrap/viaproxy/src/main/resources/viaproxy.yml b/bootstrap/viaproxy/src/main/resources/viaproxy.yml index f42cda77b..66fbdb932 100644 --- a/bootstrap/viaproxy/src/main/resources/viaproxy.yml +++ b/bootstrap/viaproxy/src/main/resources/viaproxy.yml @@ -2,4 +2,4 @@ name: "${name}-ViaProxy" version: "${version}" author: "${author}" main: "org.geysermc.geyser.platform.viaproxy.GeyserViaProxyPlugin" -min-version: "3.2.0" +min-version: "3.2.1" diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2d32159f0..b051e8852 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -29,7 +29,7 @@ adapters = "1.11-SNAPSHOT" commodore = "2.2" bungeecord = "a7c6ede" velocity = "3.1.1" -viaproxy = "3.2.0-SNAPSHOT" +viaproxy = "3.2.1" fabric-minecraft = "1.20.4" fabric-loader = "0.15.2" fabric-api = "0.91.2+1.20.4" From 2fa7585db3538ebb386edb861abf792f1f35489c Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Fri, 26 Apr 2024 21:44:59 -0400 Subject: [PATCH 300/344] Switch to Cloudburst NBT only --- .../java/org/geysermc/geyser/GeyserImpl.java | 3 +- .../geyser/entity/type/LivingEntity.java | 7 +- .../entity/type/player/PlayerEntity.java | 18 +- .../geyser/inventory/GeyserItemStack.java | 43 +++-- .../geysermc/geyser/inventory/Inventory.java | 13 +- .../geyser/inventory/item/Potion.java | 6 + .../geyser/inventory/recipe/TrimRecipe.java | 12 +- .../updater/AnvilInventoryUpdater.java | 60 +++---- .../geyser/item/DyeableLeatherItem.java | 15 -- .../geysermc/geyser/item/type/ArmorItem.java | 16 -- .../geysermc/geyser/item/type/ArrowItem.java | 16 +- .../geysermc/geyser/item/type/BannerItem.java | 58 +++---- .../geyser/item/type/CompassItem.java | 4 +- .../geyser/item/type/CrossbowItem.java | 22 --- .../geyser/item/type/DyeableArmorItem.java | 9 - .../item/type/DyeableHorseArmorItem.java | 9 - .../geyser/item/type/EnchantedBookItem.java | 30 ++++ .../geyser/item/type/FireworkRocketItem.java | 69 ++++---- .../geyser/item/type/FireworkStarItem.java | 19 +-- .../geyser/item/type/GoatHornItem.java | 17 +- .../org/geysermc/geyser/item/type/Item.java | 117 +++++++------ .../geysermc/geyser/item/type/MapItem.java | 14 -- .../geysermc/geyser/item/type/PotionItem.java | 10 +- .../geyser/item/type/ShulkerBoxItem.java | 9 - .../item/type/TropicalFishBucketItem.java | 19 +-- .../geyser/item/type/WritableBookItem.java | 25 --- .../geyser/item/type/WrittenBookItem.java | 3 +- .../geysermc/geyser/level/JavaDimension.java | 33 +--- .../geyser/session/cache/LodestoneCache.java | 18 +- .../org/geysermc/geyser/skin/SkinManager.java | 22 +-- .../geysermc/geyser/text/TextDecoration.java | 33 ++-- .../inventory/InventoryTranslator.java | 2 +- .../inventory/PlayerInventoryTranslator.java | 4 +- .../inventory/ShulkerInventoryTranslator.java | 2 +- .../translator/item/ItemTranslator.java | 156 ++---------------- .../entity/BannerBlockEntityTranslator.java | 27 +-- .../entity/BeaconBlockEntityTranslator.java | 15 +- .../entity/BedBlockEntityTranslator.java | 9 +- .../block/entity/BlockEntityTranslator.java | 15 +- .../BrushableBlockEntityTranslator.java | 29 ++-- .../entity/CampfireBlockEntityTranslator.java | 34 ++-- .../CommandBlockBlockEntityTranslator.java | 33 ++-- .../DecoratedPotBlockEntityTranslator.java | 21 +-- .../DoubleChestBlockEntityTranslator.java | 18 +- .../entity/EmptyBlockEntityTranslator.java | 5 +- .../EndGatewayBlockEntityTranslator.java | 34 +--- .../JigsawBlockBlockEntityTranslator.java | 23 ++- .../ShulkerBoxBlockEntityTranslator.java | 7 +- .../entity/SignBlockEntityTranslator.java | 37 ++--- .../entity/SkullBlockEntityTranslator.java | 66 ++++---- .../entity/SpawnerBlockEntityTranslator.java | 64 ++++--- .../StructureBlockBlockEntityTranslator.java | 69 ++++---- .../TrialSpawnerBlockEntityTranslator.java | 11 +- .../level/JavaBlockEntityDataTranslator.java | 27 ++- .../JavaLevelChunkWithLightTranslator.java | 5 +- .../BlockSoundInteractionTranslator.java | 31 +--- .../translator/text/MessageTranslator.java | 18 +- gradle/libs.versions.toml | 2 +- 58 files changed, 586 insertions(+), 927 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index 5c4313f09..d5635acf9 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -45,7 +45,6 @@ import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; import org.geysermc.api.Geyser; import org.geysermc.cumulus.form.Form; import org.geysermc.cumulus.form.util.FormBuilder; -import org.geysermc.erosion.packet.Packets; import org.geysermc.floodgate.crypto.AesCipher; import org.geysermc.floodgate.crypto.AesKeyProducer; import org.geysermc.floodgate.crypto.Base64Topping; @@ -384,7 +383,7 @@ public class GeyserImpl implements GeyserApi { this.newsHandler = new NewsHandler(BRANCH, this.buildNumber()); - Packets.initGeyser(); + //Packets.initGeyser(); if (Epoll.isAvailable()) { this.erosionUnixListener = new UnixSocketClientListener(); diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java index 5823ba3b2..baaf91f59 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java @@ -25,8 +25,6 @@ package org.geysermc.geyser.entity.type; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.StringTag; import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; @@ -57,6 +55,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEn import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.FloatEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import java.util.*; @@ -194,9 +193,9 @@ public class LivingEntity extends Entity { /** * Checks to see if a nametag interaction would go through. */ + // Implementation note for 1.20.5: this code was moved to the NameTag item. protected final InteractionResult checkInteractWithNameTag(GeyserItemStack itemStack) { - CompoundTag nbt = itemStack.getNbt(); - if (nbt != null && nbt.get("display") instanceof CompoundTag displayTag && displayTag.get("Name") instanceof StringTag) { + if (itemStack.getComponent(DataComponentType.CUSTOM_NAME) != null) { // The mob shall be named return InteractionResult.SUCCESS; } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java index 1ca387259..25040063e 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java @@ -25,14 +25,14 @@ package org.geysermc.geyser.entity.type.player; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.StringTag; import lombok.Getter; import lombok.Setter; import net.kyori.adventure.text.Component; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; +import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.protocol.bedrock.data.Ability; import org.cloudburstmc.protocol.bedrock.data.AbilityLayer; import org.cloudburstmc.protocol.bedrock.data.GameType; @@ -298,11 +298,11 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity { dirtyMetadata.put(EntityDataTypes.MARK_VARIANT, ~entityMetadata.getPrimitiveValue() & 0xff); } - public void setLeftParrot(EntityMetadata entityMetadata) { + public void setLeftParrot(EntityMetadata entityMetadata) { setParrot(entityMetadata.getValue(), true); } - public void setRightParrot(EntityMetadata entityMetadata) { + public void setRightParrot(EntityMetadata entityMetadata) { setParrot(entityMetadata.getValue(), false); } @@ -310,7 +310,7 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity { * Sets the parrot occupying the shoulder. Bedrock Edition requires a full entity whereas Java Edition just * spawns it from the NBT data provided */ - protected void setParrot(CompoundTag tag, boolean isLeft) { + protected void setParrot(NbtMap tag, boolean isLeft) { if (tag != null && !tag.isEmpty()) { if ((isLeft && leftParrot != null) || (!isLeft && rightParrot != null)) { // No need to update a parrot's data when it already exists @@ -320,7 +320,7 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity { ParrotEntity parrot = new ParrotEntity(session, 0, session.getEntityCache().getNextEntityId().incrementAndGet(), null, EntityDefinitions.PARROT, position, motion, getYaw(), getPitch(), getHeadYaw()); parrot.spawnEntity(); - parrot.getDirtyMetadata().put(EntityDataTypes.VARIANT, (Integer) tag.get("Variant").getValue()); + parrot.getDirtyMetadata().put(EntityDataTypes.VARIANT, (Integer) tag.get("Variant")); // Different position whether the parrot is left or right float offset = isLeft ? 0.4f : -0.4f; parrot.getDirtyMetadata().put(EntityDataTypes.SEAT_OFFSET, Vector3f.from(offset, -0.22, -0.1)); @@ -437,11 +437,11 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity { } else if (numberFormat instanceof FixedFormat fixedFormat) { numberString = MessageTranslator.convertMessage(fixedFormat.getValue()); } else if (numberFormat instanceof StyledFormat styledFormat) { - CompoundTag styledAmount = styledFormat.getStyle().clone(); - styledAmount.put(new StringTag("text", String.valueOf(amount))); + NbtMapBuilder styledAmount = styledFormat.getStyle().toBuilder(); + styledAmount.putString("text", String.valueOf(amount)); numberString = MessageTranslator.convertJsonMessage( - NbtComponentSerializer.tagComponentToJson(styledAmount).toString()); + NbtComponentSerializer.tagComponentToJson(styledAmount.build()).toString(), session.locale()); } else { numberString = String.valueOf(amount); } diff --git a/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java b/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java index f75c1fdd9..fa62769fe 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java @@ -25,11 +25,7 @@ package org.geysermc.geyser.inventory; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import lombok.AccessLevel; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.Getter; +import lombok.*; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; @@ -43,6 +39,8 @@ import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; +import java.util.HashMap; + @Data public class GeyserItemStack { public static final GeyserItemStack EMPTY = new GeyserItemStack(Items.AIR_ID, 0, null); @@ -52,7 +50,7 @@ public class GeyserItemStack { private DataComponents components; private int netId; - @Getter(AccessLevel.NONE) + @Getter(AccessLevel.NONE) @Setter(AccessLevel.NONE) @EqualsAndHashCode.Exclude private Item item; @@ -67,6 +65,14 @@ public class GeyserItemStack { this.netId = netId; } + public static @NonNull GeyserItemStack of(int javaId, int amount) { + return of(javaId, amount, null); + } + + public static @NonNull GeyserItemStack of(int javaId, int amount, DataComponents components) { + return new GeyserItemStack(javaId, amount, components); + } + public static @NonNull GeyserItemStack from(@Nullable ItemStack itemStack) { return itemStack == null ? EMPTY : new GeyserItemStack(itemStack.getId(), itemStack.getAmount(), itemStack.getDataComponents()); } @@ -79,16 +85,27 @@ public class GeyserItemStack { return isEmpty() ? 0 : amount; } - public @Nullable CompoundTag getNbt() { - Thread.dumpStack(); - return null; - } - public @Nullable DataComponents getComponents() { return isEmpty() ? null : components; } - public boolean getComponent(DataComponentType type, boolean def) { + @NonNull + public DataComponents getOrCreateComponents() { + if (components == null) { + return components = new DataComponents(new HashMap<>()); + } + return components; + } + + @Nullable + public T getComponent(@NonNull DataComponentType type) { + if (components == null) { + return null; + } + return components.get(type); + } + + public boolean getComponent(@NonNull DataComponentType type, boolean def) { if (components == null) { return def; } @@ -100,7 +117,7 @@ public class GeyserItemStack { return def; } - public int getComponent(DataComponentType type, int def) { + public int getComponent(@NonNull DataComponentType type, int def) { if (components == null) { return def; } diff --git a/core/src/main/java/org/geysermc/geyser/inventory/Inventory.java b/core/src/main/java/org/geysermc/geyser/inventory/Inventory.java index 4e8257ff8..09d04f17c 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/Inventory.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/Inventory.java @@ -25,9 +25,6 @@ package org.geysermc.geyser.inventory; -import com.github.steveice10.opennbt.tag.builtin.ByteTag; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; import lombok.Getter; import lombok.Setter; import lombok.ToString; @@ -39,6 +36,7 @@ import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.ItemTranslator; import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import org.jetbrains.annotations.Range; import java.util.Arrays; @@ -137,12 +135,9 @@ public abstract class Inventory { // Lodestone caching if (newItem.asItem() == Items.COMPASS) { - CompoundTag nbt = newItem.getNbt(); - if (nbt != null) { - Tag lodestoneTag = nbt.get("LodestoneTracked"); - if (lodestoneTag instanceof ByteTag) { - session.getLodestoneCache().cacheInventoryItem(newItem); - } + var tracker = newItem.getComponent(DataComponentType.LODESTONE_TRACKER); + if (tracker != null) { + session.getLodestoneCache().cacheInventoryItem(newItem, tracker); } } } diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/Potion.java b/core/src/main/java/org/geysermc/geyser/inventory/item/Potion.java index 7ce0ee278..79b9565fb 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/item/Potion.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/item/Potion.java @@ -25,8 +25,10 @@ package org.geysermc.geyser.inventory.item; +import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; import lombok.Getter; import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.PotionContents; import java.util.Locale; @@ -85,6 +87,10 @@ public enum Potion { this.bedrockId = (short) bedrockId; } + public PotionContents toComponent() { + return new PotionContents(this.ordinal(), -1, Int2ObjectMaps.emptyMap()); + } + public static @Nullable Potion getByJavaIdentifier(String javaIdentifier) { for (Potion potion : VALUES) { if (potion.javaIdentifier.equals(javaIdentifier)) { diff --git a/core/src/main/java/org/geysermc/geyser/inventory/recipe/TrimRecipe.java b/core/src/main/java/org/geysermc/geyser/inventory/recipe/TrimRecipe.java index 860ccfd89..37eb905a4 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/recipe/TrimRecipe.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/recipe/TrimRecipe.java @@ -25,9 +25,6 @@ package org.geysermc.geyser.inventory.recipe; -import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.StringTag; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.TextColor; import org.cloudburstmc.protocol.bedrock.data.TrimMaterial; @@ -37,6 +34,7 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.descriptor.ItemTagDescri import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.text.MessageTranslator; +import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry; /** * Stores information on trim materials and patterns, including smithing armor hacks for pre-1.20. @@ -54,11 +52,11 @@ public final class TrimRecipe { // Color is used when hovering over the item // Find the nearest legacy color from the RGB Java gives us to work with // Also yes this is a COMPLETE hack but it works ok!!!!! - StringTag colorTag = ((CompoundTag) entry.getData().get("description")).get("color"); - TextColor color = TextColor.fromHexString(colorTag.getValue()); + String colorTag = entry.getData().getCompound("description").getString("color"); + TextColor color = TextColor.fromHexString(colorTag); String legacy = MessageTranslator.convertMessage(Component.space().color(color)); - String itemIdentifier = ((StringTag) entry.getData().get("ingredient")).getValue(); + String itemIdentifier = entry.getData().getString("ingredient"); ItemMapping itemMapping = session.getItemMappings().getMapping(itemIdentifier); if (itemMapping == null) { // This should never happen so not sure what to do here. @@ -71,7 +69,7 @@ public final class TrimRecipe { public static TrimPattern readTrimPattern(GeyserSession session, RegistryEntry entry) { String key = stripNamespace(entry.getId()); - String itemIdentifier = ((StringTag) entry.getData().get("template_item")).getValue(); + String itemIdentifier = entry.getData().getString("template_item"); ItemMapping itemMapping = session.getItemMappings().getMapping(itemIdentifier); if (itemMapping == null) { // This should never happen so not sure what to do here. diff --git a/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java b/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java index d6324ba23..1021a5fb9 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java @@ -25,13 +25,6 @@ package org.geysermc.geyser.inventory.updater; -import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; -import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; -import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundRenameItemPacket; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.ListTag; -import com.github.steveice10.opennbt.tag.builtin.StringTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntMaps; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; @@ -53,7 +46,12 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.inventory.InventoryTranslator; import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.util.ItemUtils; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemEnchantments; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundRenameItemPacket; +import java.util.Map; import java.util.Objects; public class AnvilInventoryUpdater extends InventoryUpdater { @@ -310,9 +308,9 @@ public class AnvilInventoryUpdater extends InventoryUpdater { */ private int calcMergeEnchantmentCost(GeyserSession session, GeyserItemStack input, GeyserItemStack material, boolean bedrock) { boolean hasCompatible = false; - Object2IntMap combinedEnchantments = getEnchantments(input, bedrock); + Object2IntMap combinedEnchantments = getEnchantments(input); int cost = 0; - for (Object2IntMap.Entry entry : getEnchantments(material, bedrock).object2IntEntrySet()) { + for (Object2IntMap.Entry entry : getEnchantments(material).object2IntEntrySet()) { JavaEnchantment enchantment = entry.getKey(); EnchantmentData data = Registries.ENCHANTMENTS.get(enchantment); if (data == null) { @@ -371,42 +369,26 @@ public class AnvilInventoryUpdater extends InventoryUpdater { return cost; } - private Object2IntMap getEnchantments(GeyserItemStack itemStack, boolean bedrock) { - if (itemStack.getNbt() == null) { - return Object2IntMaps.emptyMap(); - } - Object2IntMap enchantments = new Object2IntOpenHashMap<>(); - Tag enchantmentTag; + private Object2IntMap getEnchantments(GeyserItemStack itemStack) { + ItemEnchantments enchantmentComponent; if (isEnchantedBook(itemStack)) { - enchantmentTag = itemStack.getNbt().get("StoredEnchantments"); + enchantmentComponent = itemStack.getComponent(DataComponentType.STORED_ENCHANTMENTS); } else { - enchantmentTag = itemStack.getNbt().get("Enchantments"); + enchantmentComponent = itemStack.getComponent(DataComponentType.ENCHANTMENTS); } - if (enchantmentTag instanceof ListTag listTag) { - for (Tag tag : listTag.getValue()) { - if (tag instanceof CompoundTag enchantTag) { - if (enchantTag.get("id") instanceof StringTag javaEnchId) { - JavaEnchantment enchantment = JavaEnchantment.getByJavaIdentifier(javaEnchId.getValue()); - if (enchantment == null) { - GeyserImpl.getInstance().getLogger().debug("Unknown Java enchantment in anvil: " + javaEnchId.getValue()); - continue; - } - - Tag javaEnchLvl = enchantTag.get("lvl"); - if (javaEnchLvl == null || !(javaEnchLvl.getValue() instanceof Number number)) - continue; - - // Handle duplicate enchantments - if (bedrock) { - enchantments.putIfAbsent(enchantment, number.intValue()); - } else { - enchantments.mergeInt(enchantment, number.intValue(), Math::max); - } - } + if (enchantmentComponent != null) { + Object2IntMap enchantments = new Object2IntOpenHashMap<>(); + for (Map.Entry entry : enchantmentComponent.getEnchantments().entrySet()) { + JavaEnchantment enchantment = JavaEnchantment.of(entry.getKey()); + if (enchantment == null) { + GeyserImpl.getInstance().getLogger().debug("Unknown Java enchantment in anvil: " + entry.getKey()); + continue; } + enchantments.put(enchantment, entry.getValue().intValue()); } + return enchantments; } - return enchantments; + return Object2IntMaps.emptyMap(); } private boolean isEnchantedBook(GeyserItemStack itemStack) { diff --git a/core/src/main/java/org/geysermc/geyser/item/DyeableLeatherItem.java b/core/src/main/java/org/geysermc/geyser/item/DyeableLeatherItem.java index e884ecec5..eabdbee87 100644 --- a/core/src/main/java/org/geysermc/geyser/item/DyeableLeatherItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/DyeableLeatherItem.java @@ -25,8 +25,6 @@ package org.geysermc.geyser.item; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.IntTag; import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; @@ -41,17 +39,4 @@ public interface DyeableLeatherItem { } builder.putInt("customColor", dyedItemColor.getRgb()); } - - static void translateNbtToJava(CompoundTag tag) { - IntTag color = tag.get("customColor"); - if (color == null) { - return; - } - CompoundTag displayTag = tag.get("display"); - if (displayTag == null) { - displayTag = new CompoundTag("display"); - } - displayTag.put(color); - tag.remove("customColor"); - } } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java index fb9f35629..76f951c66 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java @@ -25,15 +25,12 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.StringTag; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.protocol.bedrock.data.TrimMaterial; import org.cloudburstmc.protocol.bedrock.data.TrimPattern; import org.geysermc.geyser.item.ArmorMaterial; -import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.mcprotocollib.protocol.data.game.item.component.ArmorTrim; @@ -70,19 +67,6 @@ public class ArmorItem extends Item { } } - @Override - public void translateNbtToJava(@NonNull CompoundTag tag, @NonNull ItemMapping mapping) { - super.translateNbtToJava(tag, mapping); - - if (tag.get("Trim") instanceof CompoundTag trim) { - StringTag material = trim.remove("Material"); - StringTag pattern = trim.remove("Pattern"); - // java has a lowercase key, and namespaced value - trim.put(new StringTag("material", "minecraft:" + material.getValue())); - trim.put(new StringTag("pattern", "minecraft:" + pattern.getValue())); - } - } - @Override public boolean isValidRepairItem(Item other) { return material.getRepairIngredient() == other; diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java index f3c832a31..f2548e170 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java @@ -25,14 +25,16 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.opennbt.tag.builtin.StringTag; +import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; +import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.item.TippedArrowPotion; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; -import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.PotionContents; public class ArrowItem extends Item { public ArrowItem(String javaIdentifier, Builder builder) { @@ -40,13 +42,13 @@ public class ArrowItem extends Item { } @Override - public @NonNull ItemStack translateToJava(@NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) { + public @NonNull GeyserItemStack translateToJava(@NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) { TippedArrowPotion tippedArrowPotion = TippedArrowPotion.getByBedrockId(itemData.getDamage()); - ItemStack itemStack = super.translateToJava(itemData, mapping, mappings); + GeyserItemStack itemStack = super.translateToJava(itemData, mapping, mappings); if (tippedArrowPotion != null) { - itemStack = Items.TIPPED_ARROW.newItemStack(itemStack.getAmount(), itemStack.getDataComponents()); - StringTag potionTag = new StringTag("Potion", tippedArrowPotion.getJavaIdentifier()); - //itemStack.getDataComponents().put(DataComponentType.POTION_CONTENTS, new PotionContents()); + itemStack = Items.TIPPED_ARROW.newItemStack(itemStack.getAmount(), itemStack.getComponents()); + PotionContents contents = new PotionContents(tippedArrowPotion.ordinal(), -1, Int2ObjectMaps.emptyMap()); + itemStack.getOrCreateComponents().put(DataComponentType.POTION_CONTENTS, contents); } return itemStack; } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java index 29a98e598..232f340ea 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.opennbt.tag.builtin.*; import it.unimi.dsi.fastutil.Pair; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtList; @@ -52,7 +51,7 @@ public class BannerItem extends BlockItem { * the correct ominous banner pattern if Bedrock pulls the item from creative. */ private static final List> OMINOUS_BANNER_PATTERN; - private static final ListTag OMINOUS_BANNER_PATTERN_BLOCK; + private static final List OMINOUS_BANNER_PATTERN_BLOCK; static { // Construct what an ominous banner is supposed to look like @@ -67,7 +66,7 @@ public class BannerItem extends BlockItem { Pair.of(BannerPattern.BORDER, DyeColor.BLACK) ); - OMINOUS_BANNER_PATTERN_BLOCK = new ListTag("patterns"); + OMINOUS_BANNER_PATTERN_BLOCK = new ArrayList<>(); for (Pair pair : OMINOUS_BANNER_PATTERN) { OMINOUS_BANNER_PATTERN_BLOCK.add(getJavaBannerPatternTag(pair.left(), pair.right())); } @@ -92,7 +91,7 @@ public class BannerItem extends BlockItem { return true; } - public static boolean isOminous(ListTag blockEntityPatterns) { + public static boolean isOminous(List blockEntityPatterns) { return OMINOUS_BANNER_PATTERN_BLOCK.equals(blockEntityPatterns); } @@ -102,10 +101,10 @@ public class BannerItem extends BlockItem { * @param patterns The patterns to convert * @return The new converted patterns */ - public static NbtList convertBannerPattern(ListTag patterns) { + public static NbtList convertBannerPattern(List patterns) { List tagsList = new ArrayList<>(); - for (Tag patternTag : patterns.getValue()) { - NbtMap bedrockBannerPattern = getBedrockBannerPattern((CompoundTag) patternTag); + for (NbtMap patternTag : patterns) { + NbtMap bedrockBannerPattern = getBedrockBannerPattern(patternTag); if (bedrockBannerPattern != null) { tagsList.add(bedrockBannerPattern); } @@ -120,9 +119,9 @@ public class BannerItem extends BlockItem { * @param pattern Java edition pattern nbt * @return The Bedrock edition format pattern nbt */ - private static NbtMap getBedrockBannerPattern(CompoundTag pattern) { - BannerPattern bannerPattern = BannerPattern.getByJavaIdentifier((String) pattern.get("pattern").getValue()); - DyeColor dyeColor = DyeColor.getByJavaIdentifier((String) pattern.get("color").getValue()); + private static NbtMap getBedrockBannerPattern(NbtMap pattern) { + BannerPattern bannerPattern = BannerPattern.getByJavaIdentifier(pattern.getString("pattern")); + DyeColor dyeColor = DyeColor.getByJavaIdentifier(pattern.getString("color")); if (bannerPattern == null || dyeColor == null) { return null; } @@ -133,11 +132,11 @@ public class BannerItem extends BlockItem { .build(); } - public static CompoundTag getJavaBannerPatternTag(BannerPattern bannerPattern, DyeColor dyeColor) { - CompoundTag tag = new CompoundTag(""); - tag.put(new StringTag("pattern", bannerPattern.getJavaIdentifier())); - tag.put(new StringTag("color", dyeColor.getJavaIdentifier())); - return tag; + public static NbtMap getJavaBannerPatternTag(BannerPattern bannerPattern, DyeColor dyeColor) { + return NbtMap.builder() + .putString("pattern", bannerPattern.getJavaIdentifier()) + .putString("color", dyeColor.getJavaIdentifier()) + .build(); } /** @@ -190,31 +189,14 @@ public class BannerItem extends BlockItem { } @Override - public void translateNbtToJava(@NonNull CompoundTag tag, @NonNull ItemMapping mapping) { // TODO - super.translateNbtToJava(tag, mapping); + public void translateNbtToJava(@NonNull NbtMap bedrockTag, @NonNull DataComponents components, @NonNull ItemMapping mapping) { // TODO + super.translateNbtToJava(bedrockTag, components, mapping); - if (tag.get("Type") instanceof IntTag type && type.getValue() == 1) { + if (bedrockTag.getInt("Type") == 1) { // Ominous banner pattern - tag.remove("Type"); - CompoundTag blockEntityTag = new CompoundTag("BlockEntityTag"); - blockEntityTag.put(OMINOUS_BANNER_PATTERN_BLOCK); - - tag.put(blockEntityTag); - } else if (tag.get("Patterns") instanceof ListTag patterns && patterns.getElementType() == CompoundTag.class) { - CompoundTag blockEntityTag = new CompoundTag("BlockEntityTag"); - - ListTag javaPatterns = new ListTag("patterns"); - for (Tag pattern : patterns.getValue()) { - BannerPattern bannerPattern = BannerPattern.getByBedrockIdentifier((String) ((CompoundTag) pattern).get("Pattern").getValue()); - DyeColor dyeColor = DyeColor.getById((int) ((CompoundTag) pattern).get("Color").getValue()); - if (bannerPattern != null && dyeColor != null) { - javaPatterns.add(getJavaBannerPatternTag(bannerPattern, dyeColor)); - } - } - blockEntityTag.put(javaPatterns); - - tag.put(blockEntityTag); - tag.remove("Patterns"); // Remove the old Bedrock patterns list + // TODO more registry stuff + //components.put(DataComponentType.BANNER_PATTERNS); } + // Bedrock's creative inventory does not support other patterns as of 1.20.5 } } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java b/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java index aa34f76ba..712e75a23 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java @@ -28,11 +28,11 @@ package org.geysermc.geyser.item.type; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; +import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; -import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; import org.geysermc.mcprotocollib.protocol.data.game.item.component.LodestoneTracker; @@ -78,7 +78,7 @@ public class CompassItem extends Item { } @Override - public @NonNull ItemStack translateToJava(@NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) { + public @NonNull GeyserItemStack translateToJava(@NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) { if (mapping.getBedrockIdentifier().equals("minecraft:lodestone_compass")) { // Revert the entry back to the compass mapping = mappings.getStoredItems().compass(); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/CrossbowItem.java b/core/src/main/java/org/geysermc/geyser/item/type/CrossbowItem.java index 9a10c701c..7e1181c4e 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/CrossbowItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/CrossbowItem.java @@ -25,10 +25,6 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.opennbt.tag.builtin.ByteTag; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.ListTag; -import com.github.steveice10.opennbt.tag.builtin.StringTag; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; @@ -63,22 +59,4 @@ public class CrossbowItem extends Item { builder.putCompound("chargedItem", newProjectile.build()); } } - - @Override - public void translateNbtToJava(@NonNull CompoundTag tag, @NonNull ItemMapping mapping) { - super.translateNbtToJava(tag, mapping); - - if (tag.get("chargedItem") != null) { - CompoundTag chargedItem = tag.get("chargedItem"); - - CompoundTag newProjectile = new CompoundTag(""); - newProjectile.put(new ByteTag("Count", (byte) chargedItem.get("Count").getValue())); - newProjectile.put(new StringTag("id", (String) chargedItem.get("Name").getValue())); - - ListTag chargedProjectiles = new ListTag("ChargedProjectiles"); - chargedProjectiles.add(newProjectile); - - tag.put(chargedProjectiles); - } - } } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/DyeableArmorItem.java b/core/src/main/java/org/geysermc/geyser/item/type/DyeableArmorItem.java index e57470607..d4bf838bd 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/DyeableArmorItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/DyeableArmorItem.java @@ -25,11 +25,9 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.item.ArmorMaterial; import org.geysermc.geyser.item.DyeableLeatherItem; -import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; @@ -45,11 +43,4 @@ public class DyeableArmorItem extends ArmorItem implements DyeableLeatherItem { DyeableLeatherItem.translateComponentsToBedrock(components, builder); } - - @Override - public void translateNbtToJava(@NonNull CompoundTag tag, @NonNull ItemMapping mapping) { - super.translateNbtToJava(tag, mapping); - - DyeableLeatherItem.translateNbtToJava(tag); - } } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/DyeableHorseArmorItem.java b/core/src/main/java/org/geysermc/geyser/item/type/DyeableHorseArmorItem.java index 881598648..b50a3b847 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/DyeableHorseArmorItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/DyeableHorseArmorItem.java @@ -25,10 +25,8 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.item.DyeableLeatherItem; -import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; @@ -44,11 +42,4 @@ public class DyeableHorseArmorItem extends Item implements DyeableLeatherItem { DyeableLeatherItem.translateComponentsToBedrock(components, builder); } - - @Override - public void translateNbtToJava(@NonNull CompoundTag tag, @NonNull ItemMapping mapping) { - super.translateNbtToJava(tag, mapping); - - DyeableLeatherItem.translateNbtToJava(tag); - } } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java b/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java index 952967475..98e98b4b8 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java @@ -25,9 +25,14 @@ package org.geysermc.geyser.item.type; +import it.unimi.dsi.fastutil.ints.Int2IntMap; +import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtType; +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.inventory.item.Enchantment; +import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; @@ -62,4 +67,29 @@ public class EnchantedBookItem extends Item { builder.putList("ench", NbtType.COMPOUND, bedrockEnchants); } } + + @Override + public void translateNbtToJava(@NonNull NbtMap bedrockTag, @NonNull DataComponents components, @NonNull ItemMapping mapping) { + super.translateNbtToJava(bedrockTag, components, mapping); + + List enchantmentTag = bedrockTag.getList("ench", NbtType.COMPOUND); + if (enchantmentTag != null) { + Int2IntMap javaEnchantments = new Int2IntOpenHashMap(enchantmentTag.size()); + for (NbtMap bedrockEnchantment : enchantmentTag) { + short bedrockId = bedrockEnchantment.getShort("id"); + + Enchantment enchantment = Enchantment.getByBedrockId(bedrockId); + if (enchantment != null) { + int level = bedrockEnchantment.getShort("lvl", (short) 1); + // TODO + javaEnchantments.put(Enchantment.JavaEnchantment.valueOf(enchantment.name()).ordinal(), level); + } else { + GeyserImpl.getInstance().getLogger().debug("Unknown bedrock enchantment: " + bedrockId); + } + } + if (!javaEnchantments.isEmpty()) { + components.put(DataComponentType.STORED_ENCHANTMENTS, new ItemEnchantments(javaEnchantments, true)); + } + } + } } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java b/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java index e5656b494..1265956da 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java @@ -25,9 +25,7 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.opennbt.tag.builtin.ByteTag; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.IntArrayTag; +import it.unimi.dsi.fastutil.ints.IntArrays; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; @@ -36,7 +34,6 @@ import org.geysermc.geyser.level.FireworkColor; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; -import org.geysermc.geyser.util.MathUtils; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; import org.geysermc.mcprotocollib.protocol.data.game.item.component.Fireworks; @@ -73,8 +70,23 @@ public class FireworkRocketItem extends Item { } @Override - public void translateNbtToJava(@NonNull CompoundTag tag, @NonNull ItemMapping mapping) { - super.translateNbtToJava(tag, mapping); + public void translateNbtToJava(@NonNull NbtMap bedrockTag, @NonNull DataComponents components, @NonNull ItemMapping mapping) { + super.translateNbtToJava(bedrockTag, components, mapping); + + NbtMap fireworksTag = bedrockTag.getCompound("Fireworks"); + if (!fireworksTag.isEmpty()) { + List explosions = fireworksTag.getList("Explosions", NbtType.COMPOUND); + if (!explosions.isEmpty()) { + List javaExplosions = new ArrayList<>(); + for (NbtMap explosion : explosions) { + Fireworks.FireworkExplosion javaExplosion = translateExplosionToJava(explosion); + if (javaExplosion != null) { + javaExplosions.add(javaExplosion); + } + } + components.put(DataComponentType.FIREWORKS, new Fireworks(1, javaExplosions)); + } + } } static NbtMap translateExplosionToBedrock(Fireworks.FireworkExplosion explosion) { @@ -111,45 +123,22 @@ public class FireworkRocketItem extends Item { return newExplosionData.build(); } - static CompoundTag translateExplosionToJava(CompoundTag explosion, String newName) { - CompoundTag newExplosionData = new CompoundTag(newName); - - if (explosion.get("FireworkType") != null) { - newExplosionData.put(new ByteTag("Type", MathUtils.getNbtByte(explosion.get("FireworkType").getValue()))); - } - - if (explosion.get("FireworkColor") != null) { - byte[] oldColors = (byte[]) explosion.get("FireworkColor").getValue(); - int[] colors = new int[oldColors.length]; + /** + * The only thing that the Bedrock creative inventory has - as of 1.20.80 - is color. + */ + static Fireworks.FireworkExplosion translateExplosionToJava(NbtMap explosion) { + byte[] javaColors = explosion.getByteArray("FireworkColor", null); + if (javaColors != null) { + int[] colors = new int[javaColors.length]; int i = 0; - for (byte color : oldColors) { + for (byte color : javaColors) { colors[i++] = FireworkColor.fromBedrockId(color); } - newExplosionData.put(new IntArrayTag("Colors", colors)); + return new Fireworks.FireworkExplosion(0, colors, IntArrays.EMPTY_ARRAY, false, false); + } else { + return null; } - - if (explosion.get("FireworkFade") != null) { - byte[] oldColors = (byte[]) explosion.get("FireworkFade").getValue(); - int[] colors = new int[oldColors.length]; - - int i = 0; - for (byte color : oldColors) { - colors[i++] = FireworkColor.fromBedrockId(color); - } - - newExplosionData.put(new IntArrayTag("FadeColors", colors)); - } - - if (explosion.get("FireworkTrail") != null) { - newExplosionData.put(new ByteTag("Trail", MathUtils.getNbtByte(explosion.get("FireworkTrail").getValue()))); - } - - if (explosion.get("FireworkFlicker") != null) { - newExplosionData.put(new ByteTag("Flicker", MathUtils.getNbtByte(explosion.get("FireworkFlicker").getValue()))); - } - - return newExplosionData; } } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/FireworkStarItem.java b/core/src/main/java/org/geysermc/geyser/item/type/FireworkStarItem.java index ab6b7f300..18234975d 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/FireworkStarItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/FireworkStarItem.java @@ -25,8 +25,6 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtMap; import org.geysermc.geyser.registry.type.ItemMapping; @@ -80,15 +78,16 @@ public class FireworkStarItem extends Item { } @Override - public void translateNbtToJava(@NonNull CompoundTag tag, @NonNull ItemMapping mapping) { - super.translateNbtToJava(tag, mapping); + public void translateNbtToJava(@NonNull NbtMap bedrockTag, @NonNull DataComponents components, @NonNull ItemMapping mapping) { + super.translateNbtToJava(bedrockTag, components, mapping); - Tag explosion = tag.remove("FireworksItem"); - if (explosion instanceof CompoundTag) { - CompoundTag newExplosion = FireworkRocketItem.translateExplosionToJava((CompoundTag) explosion, "Explosion"); - tag.put(newExplosion); + NbtMap explosion = bedrockTag.getCompound("FireworksItem"); + if (!explosion.isEmpty()) { + Fireworks.FireworkExplosion newExplosion = FireworkRocketItem.translateExplosionToJava(explosion); + if (newExplosion == null) { + return; + } + components.put(DataComponentType.FIREWORK_EXPLOSION, newExplosion); } - // Remove custom color, if any, since this only exists on Bedrock - tag.remove("customColor"); } } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java b/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java index 0ff78676c..c31e15578 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java @@ -25,14 +25,12 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.opennbt.tag.builtin.StringTag; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; -import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.mcprotocollib.protocol.data.game.Holder; -import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; import org.geysermc.mcprotocollib.protocol.data.game.item.component.Instrument; @@ -80,18 +78,11 @@ public class GoatHornItem extends Item { } @Override - public @NonNull ItemStack translateToJava(@NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) { - ItemStack itemStack = super.translateToJava(itemData, mapping, mappings); + public @NonNull GeyserItemStack translateToJava(@NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) { + GeyserItemStack itemStack = super.translateToJava(itemData, mapping, mappings); int damage = itemData.getDamage(); - if (damage < 0 || damage >= INSTRUMENTS.size()) { - GeyserImpl.getInstance().getLogger().debug("Unknown goat horn instrument for damage: " + damage); - damage = 0; - } - - String instrument = INSTRUMENTS.get(damage); - StringTag instrumentTag = new StringTag("instrument", "minecraft:" + instrument); - //itemStack.getNbt().put(instrumentTag); + itemStack.getOrCreateComponents().put(DataComponentType.INSTRUMENT, Holder.ofId(damage)); return itemStack; } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/Item.java b/core/src/main/java/org/geysermc/geyser/item/type/Item.java index 64e2dcbc6..8fcb19ad5 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/Item.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/Item.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.opennbt.tag.builtin.*; import net.kyori.adventure.text.Component; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -33,6 +32,7 @@ import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtType; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.item.Enchantment; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.registry.type.ItemMapping; @@ -44,7 +44,6 @@ import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.geyser.translator.item.ItemTranslator; import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.mcprotocollib.protocol.data.game.Identifier; -import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemEnchantments; @@ -108,11 +107,8 @@ public class Item { return builder; } - public @NonNull ItemStack translateToJava(@NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) { - if (itemData.getTag() == null) { - return new ItemStack(javaId, itemData.getCount(), null); - } - return new ItemStack(javaId, itemData.getCount(), null/*ItemTranslator.translateToJavaNBT("", itemData.getTag())*/); + public @NonNull GeyserItemStack translateToJava(@NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) { + return GeyserItemStack.of(javaId, itemData.getCount()); } public ItemMapping toBedrockDefinition(DataComponents components, ItemMappings mappings) { @@ -162,57 +158,60 @@ public class Item { * * Therefore, if translation cannot be achieved for a certain item, it is not necessarily bad. */ - public void translateNbtToJava(@NonNull CompoundTag tag, @NonNull ItemMapping mapping) { - CompoundTag displayTag = tag.get("display"); - if (displayTag != null) { - if (displayTag.contains("Name")) { - StringTag nameTag = displayTag.get("Name"); - displayTag.put(new StringTag("Name", MessageTranslator.convertToJavaMessage(nameTag.getValue()))); - } + public void translateNbtToJava(@NonNull NbtMap bedrockTag, @NonNull DataComponents components, @NonNull ItemMapping mapping) { + // TODO see if any items from the creative menu need this +// CompoundTag displayTag = tag.get("display"); +// if (displayTag != null) { +// if (displayTag.contains("Name")) { +// StringTag nameTag = displayTag.get("Name"); +// displayTag.put(new StringTag("Name", MessageTranslator.convertToJavaMessage(nameTag.getValue()))); +// } +// +// if (displayTag.contains("Lore")) { +// ListTag loreTag = displayTag.get("Lore"); +// List lore = new ArrayList<>(); +// for (Tag subTag : loreTag.getValue()) { +// if (!(subTag instanceof StringTag)) continue; +// lore.add(new StringTag("", MessageTranslator.convertToJavaMessage(((StringTag) subTag).getValue()))); +// } +// displayTag.put(new ListTag("Lore", lore)); +// } +// } - if (displayTag.contains("Lore")) { - ListTag loreTag = displayTag.get("Lore"); - List lore = new ArrayList<>(); - for (Tag subTag : loreTag.getValue()) { - if (!(subTag instanceof StringTag)) continue; - lore.add(new StringTag("", MessageTranslator.convertToJavaMessage(((StringTag) subTag).getValue()))); - } - displayTag.put(new ListTag("Lore", lore)); - } - } - - ListTag enchantmentTag = tag.remove("ench"); - if (enchantmentTag != null) { - List enchantments = new ArrayList<>(); - for (Tag value : enchantmentTag.getValue()) { - if (!(value instanceof CompoundTag tagValue)) - continue; - - ShortTag bedrockId = tagValue.get("id"); - if (bedrockId == null) continue; - - Enchantment enchantment = Enchantment.getByBedrockId(bedrockId.getValue()); - if (enchantment != null) { - CompoundTag javaTag = new CompoundTag(""); - Map javaValue = javaTag.getValue(); - javaValue.put("id", new StringTag("id", enchantment.getJavaIdentifier())); - ShortTag levelTag = tagValue.get("lvl"); - javaValue.put("lvl", new IntTag("lvl", levelTag != null ? levelTag.getValue() : 1)); - javaTag.setValue(javaValue); - - enchantments.add(javaTag); - } else { - GeyserImpl.getInstance().getLogger().debug("Unknown bedrock enchantment: " + bedrockId); - } - } - if (!enchantments.isEmpty()) { - if ((this instanceof EnchantedBookItem)) { - tag.put(new ListTag("StoredEnchantments", enchantments)); - } else { - tag.put(new ListTag("Enchantments", enchantments)); - } - } - } + // TODO no creative item should have enchantments *except* enchanted books +// List enchantmentTag = bedrockTag.getList("ench", NbtType.COMPOUND); +// if (enchantmentTag != null) { +// List enchantments = new ArrayList<>(); +// for (Tag value : enchantmentTag.getValue()) { +// if (!(value instanceof CompoundTag tagValue)) +// continue; +// +// ShortTag bedrockId = tagValue.get("id"); +// if (bedrockId == null) continue; +// +// Enchantment enchantment = Enchantment.getByBedrockId(bedrockId.getValue()); +// if (enchantment != null) { +// CompoundTag javaTag = new CompoundTag(""); +// Map javaValue = javaTag.getValue(); +// javaValue.put("id", new StringTag("id", enchantment.getJavaIdentifier())); +// ShortTag levelTag = tagValue.get("lvl"); +// javaValue.put("lvl", new IntTag("lvl", levelTag != null ? levelTag.getValue() : 1)); +// javaTag.setValue(javaValue); +// +// enchantments.add(javaTag); +// } else { +// GeyserImpl.getInstance().getLogger().debug("Unknown bedrock enchantment: " + bedrockId); +// } +// } +// if (!enchantments.isEmpty()) { +// if ((this instanceof EnchantedBookItem)) { +// bedrockTag.put(new ListTag("StoredEnchantments", enchantments)); +// components.put(DataComponentType.STORED_ENCHANTMENTS, enchantments); +// } else { +// components.put(DataComponentType.ENCHANTMENTS, enchantments); +// } +// } +// } } protected final @Nullable NbtMap remapEnchantment(GeyserSession session, int enchantId, int level, BedrockItemBuilder builder) { @@ -243,8 +242,8 @@ public class Item { /* Translation methods end */ - public ItemStack newItemStack(int count, DataComponents components) { - return new ItemStack(this.javaId, count, components); + public GeyserItemStack newItemStack(int count, DataComponents components) { + return GeyserItemStack.of(this.javaId, count, components); } public void setJavaId(int javaId) { // TODO like this? diff --git a/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java b/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java index f6492a169..5d8a1667d 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java @@ -25,10 +25,7 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.IntTag; import org.checkerframework.checker.nullness.qual.NonNull; -import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; @@ -52,15 +49,4 @@ public class MapItem extends Item { builder.putInt("map_name_index", mapValue); builder.putByte("map_display_players", (byte) 1); } - - @Override - public void translateNbtToJava(@NonNull CompoundTag tag, @NonNull ItemMapping mapping) { - super.translateNbtToJava(tag, mapping); - - IntTag mapNameIndex = tag.remove("map_name_index"); - if (mapNameIndex != null) { - tag.put(new IntTag("map", mapNameIndex.getValue())); - tag.remove("map_uuid"); - } - } } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java b/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java index 13d7ccd5e..b69f7d35f 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java @@ -25,16 +25,15 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.opennbt.tag.builtin.StringTag; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.item.Potion; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.translator.item.CustomItemTranslator; -import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; import org.geysermc.mcprotocollib.protocol.data.game.item.component.PotionContents; @@ -69,12 +68,11 @@ public class PotionItem extends Item { } @Override - public @NonNull ItemStack translateToJava(@NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) { + public @NonNull GeyserItemStack translateToJava(@NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) { Potion potion = Potion.getByBedrockId(itemData.getDamage()); - ItemStack itemStack = super.translateToJava(itemData, mapping, mappings); + GeyserItemStack itemStack = super.translateToJava(itemData, mapping, mappings); if (potion != null) { - StringTag potionTag = new StringTag("Potion", potion.getJavaIdentifier()); - //itemStack.getNbt().put(potionTag); + itemStack.getOrCreateComponents().put(DataComponentType.POTION_CONTENTS, potion.toComponent()); } return itemStack; } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java index 2f2f45c5b..6b2d589d6 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; @@ -85,12 +84,4 @@ public class ShulkerBoxItem extends BlockItem { } builder.putList("Items", NbtType.COMPOUND, itemsList); } - - @Override - public void translateNbtToJava(@NonNull CompoundTag tag, @NonNull ItemMapping mapping) { - super.translateNbtToJava(tag, mapping); - - // Remove any extraneous Bedrock tag and don't touch the Java one - tag.remove("Items"); - } } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/TropicalFishBucketItem.java b/core/src/main/java/org/geysermc/geyser/item/type/TropicalFishBucketItem.java index 8c00cb049..7c5ad26f6 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/TropicalFishBucketItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/TropicalFishBucketItem.java @@ -25,13 +25,12 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.Style; import net.kyori.adventure.text.format.TextDecoration; import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.nbt.NbtMap; import org.geysermc.geyser.entity.type.living.animal.TropicalFishEntity; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.MinecraftLocale; @@ -58,26 +57,22 @@ public class TropicalFishBucketItem extends Item { builder.putString("CustomName", MinecraftLocale.getLocaleString("entity.minecraft.tropical_fish", session.locale())); // Add Java's client side lore tag // Do you know how frequently Java NBT used to be before 1.20.5? It was a lot. And now it's just this lowly check. - CompoundTag entityTag = components.get(DataComponentType.BUCKET_ENTITY_DATA); + NbtMap entityTag = components.get(DataComponentType.BUCKET_ENTITY_DATA); if (entityTag != null && !entityTag.isEmpty()) { //TODO test - Tag bucketVariant = entityTag.get("BucketVariantTag"); - if (bucketVariant == null || !(bucketVariant.getValue() instanceof Number)) { - return; - } + int bucketVariant = entityTag.getInt("BucketVariantTag"); List lore = builder.getOrCreateLore(); - int varNumber = ((Number) bucketVariant.getValue()).intValue(); - int predefinedVariantId = TropicalFishEntity.getPredefinedId(varNumber); + int predefinedVariantId = TropicalFishEntity.getPredefinedId(bucketVariant); if (predefinedVariantId != -1) { Component tooltip = Component.translatable("entity.minecraft.tropical_fish.predefined." + predefinedVariantId, LORE_STYLE); lore.add(0, MessageTranslator.convertMessage(tooltip, session.locale())); } else { - Component typeTooltip = Component.translatable("entity.minecraft.tropical_fish.type." + TropicalFishEntity.getVariantName(varNumber), LORE_STYLE); + Component typeTooltip = Component.translatable("entity.minecraft.tropical_fish.type." + TropicalFishEntity.getVariantName(bucketVariant), LORE_STYLE); lore.add(0, MessageTranslator.convertMessage(typeTooltip, session.locale())); - byte baseColor = TropicalFishEntity.getBaseColor(varNumber); - byte patternColor = TropicalFishEntity.getPatternColor(varNumber); + byte baseColor = TropicalFishEntity.getBaseColor(bucketVariant); + byte patternColor = TropicalFishEntity.getPatternColor(bucketVariant); Component colorTooltip = Component.translatable("color.minecraft." + TropicalFishEntity.getColorName(baseColor), LORE_STYLE); if (baseColor != patternColor) { colorTooltip = colorTooltip.append(Component.text(", ", LORE_STYLE)) diff --git a/core/src/main/java/org/geysermc/geyser/item/type/WritableBookItem.java b/core/src/main/java/org/geysermc/geyser/item/type/WritableBookItem.java index 097a5e65b..55ad16b20 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/WritableBookItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/WritableBookItem.java @@ -25,15 +25,10 @@ package org.geysermc.geyser.item.type; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.ListTag; -import com.github.steveice10.opennbt.tag.builtin.StringTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; -import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.geyser.translator.text.MessageTranslator; @@ -69,24 +64,4 @@ public class WritableBookItem extends Item { builder.putList("pages", NbtType.COMPOUND, bedrockPages); } - - @Override - public void translateNbtToJava(@NonNull CompoundTag tag, @NonNull ItemMapping mapping) { - super.translateNbtToJava(tag, mapping); - - if (!tag.contains("pages")) { - return; - } - List pages = new ArrayList<>(); - ListTag pagesTag = tag.get("pages"); - for (Tag subTag : pagesTag.getValue()) { - if (!(subTag instanceof CompoundTag pageTag)) - continue; - - StringTag textTag = pageTag.get("text"); - pages.add(new StringTag("", textTag.getValue())); - } - tag.remove("pages"); - tag.put(new ListTag("pages", pages)); - } } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java b/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java index a11c4f583..dd41a5e89 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/WrittenBookItem.java @@ -62,7 +62,7 @@ public class WrittenBookItem extends Item { for (Filterable page : bookContent.getPages()) { NbtMapBuilder pageBuilder = NbtMap.builder(); pageBuilder.putString("photoname", ""); - pageBuilder.putString("text", MessageTranslator.convertMessage(page.getRaw())); + pageBuilder.putString("text", MessageTranslator.convertMessage(session, page.getRaw())); bedrockPages.add(pageBuilder.build()); } builder.putList("pages", NbtType.COMPOUND, bedrockPages); @@ -70,6 +70,5 @@ public class WrittenBookItem extends Item { builder.putString("title", bookContent.getTitle().getRaw()) .putString("author", bookContent.getAuthor()) .putInt("generation", bookContent.getGeneration()); - // TODO isResolved } } diff --git a/core/src/main/java/org/geysermc/geyser/level/JavaDimension.java b/core/src/main/java/org/geysermc/geyser/level/JavaDimension.java index 27b2430bd..6112dc6cf 100644 --- a/core/src/main/java/org/geysermc/geyser/level/JavaDimension.java +++ b/core/src/main/java/org/geysermc/geyser/level/JavaDimension.java @@ -25,13 +25,9 @@ package org.geysermc.geyser.level; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.IntTag; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import org.cloudburstmc.nbt.NbtMap; import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry; -import java.util.List; - /** * Represents the information we store from the current Java dimension * @param piglinSafe Whether piglins and hoglins are safe from conversion in this dimension. @@ -39,33 +35,16 @@ import java.util.List; */ public record JavaDimension(int minY, int maxY, boolean piglinSafe, double worldCoordinateScale) { - public static void load(List entries, Int2ObjectMap map) { - for (int i = 0; i < entries.size(); i++) { - RegistryEntry entry = entries.get(i); - CompoundTag dimension = entry.getData(); - int minY = ((IntTag) dimension.get("min_y")).getValue(); - int maxY = ((IntTag) dimension.get("height")).getValue(); - // Logical height can be ignored probably - seems to be for artificial limits like the Nether. - - // Set if piglins/hoglins should shake - boolean piglinSafe = ((Number) dimension.get("piglin_safe").getValue()).byteValue() != (byte) 0; - // Load world coordinate scale for the world border - double coordinateScale = ((Number) dimension.get("coordinate_scale").getValue()).doubleValue(); - - map.put(i, new JavaDimension(minY, maxY, piglinSafe, coordinateScale)); - } - } - public static JavaDimension read(RegistryEntry entry) { - CompoundTag dimension = entry.getData(); - int minY = ((IntTag) dimension.get("min_y")).getValue(); - int maxY = ((IntTag) dimension.get("height")).getValue(); + NbtMap dimension = entry.getData(); + int minY = dimension.getInt("min_y"); + int maxY = dimension.getInt("height"); // Logical height can be ignored probably - seems to be for artificial limits like the Nether. // Set if piglins/hoglins should shake - boolean piglinSafe = ((Number) dimension.get("piglin_safe").getValue()).byteValue() != (byte) 0; + boolean piglinSafe = dimension.getBoolean("piglin_safe"); // Load world coordinate scale for the world border - double coordinateScale = ((Number) dimension.get("coordinate_scale").getValue()).doubleValue(); + double coordinateScale = dimension.getDouble("coordinate_scale"); return new JavaDimension(minY, maxY, piglinSafe, coordinateScale); } diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/LodestoneCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/LodestoneCache.java index f9515dbb4..50cdf4b5b 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/LodestoneCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/LodestoneCache.java @@ -25,15 +25,13 @@ package org.geysermc.geyser.session.cache; -import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.GlobalPos; -import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; -import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; -import org.geysermc.mcprotocollib.protocol.data.game.item.component.LodestoneTracker; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.inventory.GeyserItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.GlobalPos; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.LodestoneTracker; import java.util.Map; import java.util.WeakHashMap; @@ -54,17 +52,7 @@ public final class LodestoneCache { */ private int id = 1; - public void cacheInventoryItem(GeyserItemStack itemStack) { - DataComponents components = itemStack.getComponents(); - if (components == null) { - // invalid - return; - } - LodestoneTracker tracker = components.get(DataComponentType.LODESTONE_TRACKER); - if (tracker == null) { - return; - } - + public void cacheInventoryItem(GeyserItemStack itemStack, LodestoneTracker tracker) { GlobalPos position = tracker.getPos(); if (position == null) { diff --git a/core/src/main/java/org/geysermc/geyser/skin/SkinManager.java b/core/src/main/java/org/geysermc/geyser/skin/SkinManager.java index 33a51fe8f..4f3a94688 100644 --- a/core/src/main/java/org/geysermc/geyser/skin/SkinManager.java +++ b/core/src/main/java/org/geysermc/geyser/skin/SkinManager.java @@ -26,10 +26,9 @@ package org.geysermc.geyser.skin; import com.fasterxml.jackson.databind.JsonNode; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.ListTag; -import com.github.steveice10.opennbt.tag.builtin.StringTag; import org.checkerframework.checker.nullness.qual.Nullable; +import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtType; import org.cloudburstmc.protocol.bedrock.data.skin.ImageData; import org.cloudburstmc.protocol.bedrock.data.skin.SerializedSkin; import org.cloudburstmc.protocol.bedrock.packet.PlayerListPacket; @@ -45,6 +44,7 @@ import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.Base64; import java.util.Collections; +import java.util.List; import java.util.UUID; import java.util.function.Consumer; @@ -224,22 +224,22 @@ public class SkinManager { * @param tag tag to build the GameProfileData from * @return The built GameProfileData, or null if this wasn't a valid tag */ - public static @Nullable GameProfileData from(CompoundTag tag) { - if (!(tag.get("Properties") instanceof CompoundTag propertiesTag)) { + public static @Nullable GameProfileData from(NbtMap tag) { + NbtMap properties = tag.getCompound("Properties", null); + if (properties == null) { return null; } - if (!(propertiesTag.get("textures") instanceof ListTag texturesTag) || texturesTag.size() == 0) { + List textures = properties.getList("textures", NbtType.COMPOUND); + if (textures.isEmpty()) { return null; } - if (!(texturesTag.get(0) instanceof CompoundTag texturesData)) { - return null; - } - if (!(texturesData.get("Value") instanceof StringTag skinDataValue)) { + String skinDataValue = textures.get(0).getString("Value", null); + if (skinDataValue == null) { return null; } try { - return loadFromJson(skinDataValue.getValue()); + return loadFromJson(skinDataValue); } catch (IOException e) { GeyserImpl.getInstance().getLogger().debug("Something went wrong while processing skin for tag " + tag); if (GeyserImpl.getInstance().getConfig().isDebugMode()) { diff --git a/core/src/main/java/org/geysermc/geyser/text/TextDecoration.java b/core/src/main/java/org/geysermc/geyser/text/TextDecoration.java index a85153d13..b2222d3b9 100644 --- a/core/src/main/java/org/geysermc/geyser/text/TextDecoration.java +++ b/core/src/main/java/org/geysermc/geyser/text/TextDecoration.java @@ -25,15 +25,14 @@ package org.geysermc.geyser.text; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.ListTag; -import com.github.steveice10.opennbt.tag.builtin.StringTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.Style; +import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtType; import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry; import java.util.EnumSet; +import java.util.List; import java.util.Locale; import java.util.Set; @@ -42,28 +41,28 @@ public final class TextDecoration { private final Style style; private final Set parameters; - public TextDecoration(CompoundTag tag) { - translationKey = (String) tag.get("translation_key").getValue(); + public TextDecoration(NbtMap tag) { + translationKey = tag.getString("translation_key"); - CompoundTag styleTag = tag.get("style"); + NbtMap styleTag = tag.getCompound("style"); Style.Builder builder = Style.style(); - if (styleTag != null) { - StringTag color = styleTag.get("color"); + if (!styleTag.isEmpty()) { + String color = styleTag.getString("color", null); if (color != null) { - builder.color(NamedTextColor.NAMES.value(color.getValue())); + builder.color(NamedTextColor.NAMES.value(color)); } //TODO implement the rest - Tag italic = styleTag.get("italic"); - if (italic != null && ((Number) italic.getValue()).byteValue() == (byte) 1) { + boolean italic = styleTag.getBoolean("italic"); + if (italic) { builder.decorate(net.kyori.adventure.text.format.TextDecoration.ITALIC); } } style = builder.build(); this.parameters = EnumSet.noneOf(Parameter.class); - ListTag parameters = tag.get("parameters"); - for (Tag parameter : parameters) { - this.parameters.add(Parameter.valueOf(((String) parameter.getValue()).toUpperCase(Locale.ROOT))); + List parameters = tag.getList("parameters", NbtType.STRING); + for (String parameter : parameters) { + this.parameters.add(Parameter.valueOf(parameter.toUpperCase(Locale.ROOT))); } } @@ -90,8 +89,8 @@ public final class TextDecoration { public static TextDecoration readChatType(RegistryEntry entry) { // Note: The ID is NOT ALWAYS THE SAME! ViaVersion as of 1.19 adds two registry entries that do NOT match vanilla. - CompoundTag tag = entry.getData(); - CompoundTag chat = tag.get("chat"); + NbtMap tag = entry.getData(); + NbtMap chat = tag.getCompound("chat", null); TextDecoration textDecoration = null; if (chat != null) { textDecoration = new TextDecoration(chat); diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java index 0914aeba8..5e4ffcafd 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java @@ -224,7 +224,7 @@ public abstract class InventoryTranslator { //only set the head if the destination is the head slot GeyserItemStack javaItem = inventory.getItem(sourceSlot); if (javaItem.asItem() == Items.PLAYER_HEAD - && javaItem.getNbt() != null) { + && javaItem.getComponents() != null) { FakeHeadProvider.setHead(session, session.getPlayerEntity(), javaItem.getComponents()); } } else if (sourceSlot == 5) { diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java index 142651eb4..7459ccf30 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java @@ -94,7 +94,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { contents[i - 5] = item.getItemData(session); if (i == 5 && item.asItem() == Items.PLAYER_HEAD && - item.getNbt() != null) { + item.getComponents() != null) { FakeHeadProvider.setHead(session, session.getPlayerEntity(), item.getComponents()); } } @@ -138,7 +138,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { if (slot == 5) { // Check for custom skull if (javaItem.asItem() == Items.PLAYER_HEAD - && javaItem.getNbt() != null) { + && javaItem.getComponents() != null) { FakeHeadProvider.setHead(session, session.getPlayerEntity(), javaItem.getComponents()); } else { FakeHeadProvider.restoreOriginalSkin(session, session.getPlayerEntity()); diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/ShulkerInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/ShulkerInventoryTranslator.java index 543f519c9..f9879499a 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/ShulkerInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/ShulkerInventoryTranslator.java @@ -58,7 +58,7 @@ public class ShulkerInventoryTranslator extends AbstractBlockInventoryTranslator .putInt("z", position.getZ()) .putString("CustomName", inventory.getTitle()); // Don't reset facing property - shulkerBoxTranslator.translateTag(tag, null, javaBlockState); + shulkerBoxTranslator.translateTag(session, tag, null, javaBlockState); BlockEntityDataPacket dataPacket = new BlockEntityDataPacket(); dataPacket.setData(tag.build()); diff --git a/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java index 24362f800..df54eff79 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java @@ -29,22 +29,11 @@ import com.github.steveice10.mc.auth.data.GameProfile; import com.github.steveice10.mc.auth.data.GameProfile.Texture; import com.github.steveice10.mc.auth.data.GameProfile.TextureType; import com.github.steveice10.mc.auth.exception.property.PropertyException; -import org.geysermc.mcprotocollib.protocol.data.game.Identifier; -import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.ModifierOperation; -import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; -import org.geysermc.mcprotocollib.protocol.data.game.item.component.AdventureModePredicate; -import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; -import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; -import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemAttributeModifiers; -import com.github.steveice10.opennbt.tag.builtin.*; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; -import org.cloudburstmc.nbt.NbtList; import org.cloudburstmc.nbt.NbtMap; -import org.cloudburstmc.nbt.NbtMapBuilder; -import org.cloudburstmc.nbt.NbtType; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; @@ -63,6 +52,13 @@ import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.util.InventoryUtils; +import org.geysermc.mcprotocollib.protocol.data.game.Identifier; +import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.ModifierOperation; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.AdventureModePredicate; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemAttributeModifiers; import java.text.DecimalFormat; import java.util.ArrayList; @@ -93,16 +89,17 @@ public final class ItemTranslator { ItemMapping bedrockItem = mappings.getMapping(data); Item javaItem = bedrockItem.getJavaItem(); - ItemStack itemStack = javaItem.translateToJava(data, bedrockItem, mappings); + GeyserItemStack itemStack = javaItem.translateToJava(data, bedrockItem, mappings); -// if (itemStack.getNbt() != null) { -// javaItem.translateNbtToJava(itemStack.getNbt(), bedrockItem); -// if (itemStack.getNbt().isEmpty()) { -// // Otherwise, seems to cause issues with villagers accepting books, and I don't see how this will break anything else. - Camotoy -// itemStack = new ItemStack(itemStack.getId(), itemStack.getAmount(), null); -// } -// } - return itemStack; + NbtMap nbt = data.getTag(); + if (nbt != null && !nbt.isEmpty()) { + DataComponents components = new DataComponents(new HashMap<>()); + javaItem.translateNbtToJava(nbt, components, bedrockItem); + if (!components.getDataComponents().isEmpty()) { + itemStack.setComponents(components); + } + } + return itemStack.getItemStack(); } public static ItemData.@NonNull Builder translateToBedrock(GeyserSession session, int javaId, int count, DataComponents components) { @@ -375,125 +372,6 @@ public final class ItemTranslator { } } - public static NbtMap translateNbtToBedrock(CompoundTag tag) { - if (!tag.getValue().isEmpty()) { - NbtMapBuilder builder = NbtMap.builder(); - for (Tag javaTag : tag.values()) { - Object translatedTag = translateToBedrockNBT(javaTag); - if (translatedTag == null) - continue; - - builder.put(javaTag.getName(), translatedTag); - } - return builder.build(); - } - return NbtMap.EMPTY; - } - - private static @Nullable Object translateToBedrockNBT(Tag tag) { - if (tag instanceof CompoundTag compoundTag) { - return translateNbtToBedrock(compoundTag); - } - - if (tag instanceof ListTag listTag) { - List tagList = new ArrayList<>(); - for (Tag value : listTag) { - tagList.add(translateToBedrockNBT(value)); - } - NbtType type = NbtType.COMPOUND; - if (!tagList.isEmpty()) { - type = NbtType.byClass(tagList.get(0).getClass()); - } - //noinspection unchecked,rawtypes - return new NbtList(type, tagList); - } - - if (tag instanceof LongArrayTag) { - //Long array tag does not exist in BE - //LongArrayTag longArrayTag = (LongArrayTag) tag; - //return new org.cloudburstmc.nbt.tag.LongArrayTag(longArrayTag.getName(), longArrayTag.getValue()); - return null; - } - - return tag.getValue(); - } - - public static CompoundTag translateToJavaNBT(String name, NbtMap tag) { - CompoundTag javaTag = new CompoundTag(name); - Map javaValue = javaTag.getValue(); - if (tag != null && !tag.isEmpty()) { - for (Map.Entry entry : tag.entrySet()) { - Tag translatedTag = translateToJavaNBT(entry.getKey(), entry.getValue()); - if (translatedTag == null) - continue; - - javaValue.put(translatedTag.getName(), translatedTag); - } - } - - javaTag.setValue(javaValue); - return javaTag; - } - - private static @Nullable Tag translateToJavaNBT(String name, Object object) { - if (object instanceof int[]) { - return new IntArrayTag(name, (int[]) object); - } - - if (object instanceof byte[]) { - return new ByteArrayTag(name, (byte[]) object); - } - - if (object instanceof Byte) { - return new ByteTag(name, (byte) object); - } - - if (object instanceof Float) { - return new FloatTag(name, (float) object); - } - - if (object instanceof Double) { - return new DoubleTag(name, (double) object); - } - - if (object instanceof Integer) { - return new IntTag(name, (int) object); - } - - if (object instanceof long[]) { - return new LongArrayTag(name, (long[]) object); - } - - if (object instanceof Long) { - return new LongTag(name, (long) object); - } - - if (object instanceof Short) { - return new ShortTag(name, (short) object); - } - - if (object instanceof String) { - return new StringTag(name, (String) object); - } - - if (object instanceof List) { - List tags = new ArrayList<>(); - - for (Object value : (List) object) { - Tag javaTag = translateToJavaNBT("", value); - if (javaTag != null) - tags.add(javaTag); - } - return new ListTag(name, tags); - } - - if (object instanceof NbtMap map) { - return translateToJavaNBT(name, map); - } - - return null; - } - /** * Translates the display name of the item * @param session the Bedrock client's session diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BannerBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BannerBlockEntityTranslator.java index bc08dd93b..c87d1a217 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BannerBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BannerBlockEntityTranslator.java @@ -25,40 +25,43 @@ package org.geysermc.geyser.translator.level.block.entity; -import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.ListTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; +import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; +import org.cloudburstmc.nbt.NbtType; import org.geysermc.geyser.item.type.BannerItem; import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; + +import java.util.List; @BlockEntity(type = BlockEntityType.BANNER) public class BannerBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState { @Override - public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) { + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) { int bannerColor = BlockStateValues.getBannerColor(blockState); if (bannerColor != -1) { - builder.put("Base", 15 - bannerColor); + bedrockNbt.putInt("Base", 15 - bannerColor); } - if (tag == null) { + if (javaNbt == null) { return; } - if (tag.get("patterns") instanceof ListTag patterns) { + List patterns = javaNbt.getList("patterns", NbtType.COMPOUND); + if (!patterns.isEmpty()) { if (BannerItem.isOminous(patterns)) { // This is an ominous banner; don't try to translate the raw patterns (it doesn't translate correctly) // and tell the Bedrock client that this is an ominous banner - builder.putInt("Type", 1); + bedrockNbt.putInt("Type", 1); } else { - builder.put("Patterns", BannerItem.convertBannerPattern(patterns)); + bedrockNbt.putList("Patterns", NbtType.COMPOUND, BannerItem.convertBannerPattern(patterns)); } } - Tag customName = tag.get("CustomName"); + String customName = javaNbt.getString("CustomName", null); if (customName != null) { - builder.put("CustomName", customName.getValue()); + bedrockNbt.putString("CustomName", customName); } } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BeaconBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BeaconBlockEntityTranslator.java index 0db362949..f7dee2864 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BeaconBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BeaconBlockEntityTranslator.java @@ -25,18 +25,19 @@ package org.geysermc.geyser.translator.level.block.entity; -import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; @BlockEntity(type = BlockEntityType.BEACON) public class BeaconBlockEntityTranslator extends BlockEntityTranslator { @Override - public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) { - int primary = getOrDefault(tag.get("Primary"), 0); + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) { + int primary = javaNbt.getInt("primary"); // The effects here generally map one-to-one Java <-> Bedrock. Only the newer ones get more complicated - builder.putInt("primary", primary == -1 ? 0 : primary); - int secondary = getOrDefault(tag.get("Secondary"), 0); - builder.putInt("secondary", secondary == -1 ? 0 : secondary); + bedrockNbt.putInt("primary", primary == -1 ? 0 : primary); + int secondary = javaNbt.getInt("secondary"); + bedrockNbt.putInt("secondary", secondary == -1 ? 0 : secondary); } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BedBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BedBlockEntityTranslator.java index 1c46edf0a..720ffea3c 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BedBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BedBlockEntityTranslator.java @@ -25,20 +25,21 @@ package org.geysermc.geyser.translator.level.block.entity; -import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; @BlockEntity(type = BlockEntityType.BED) public class BedBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState { @Override - public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) { + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) { byte bedcolor = BlockStateValues.getBedColor(blockState); // Just in case... if (bedcolor == -1) { bedcolor = 0; } - builder.put("color", bedcolor); + bedrockNbt.putByte("color", bedcolor); } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BlockEntityTranslator.java index 5f6487a24..45981377c 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BlockEntityTranslator.java @@ -25,13 +25,11 @@ package org.geysermc.geyser.translator.level.block.entity; -import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.BlockEntityUtils; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; /** * The class that all block entities (on both Java and Bedrock) should translate with @@ -40,11 +38,11 @@ public abstract class BlockEntityTranslator { protected BlockEntityTranslator() { } - public abstract void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState); + public abstract void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState); - public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, CompoundTag tag, int blockState) { + public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, NbtMap javaNbt, int blockState) { NbtMapBuilder tagBuilder = getConstantBedrockTag(type, x, y, z); - translateTag(tagBuilder, tag, blockState); + translateTag(session, tagBuilder, javaNbt, blockState); return tagBuilder.build(); } @@ -59,9 +57,4 @@ public abstract class BlockEntityTranslator { .putInt("z", z) .putString("id", bedrockId); } - - @SuppressWarnings("unchecked") - protected T getOrDefault(Tag tag, T defaultValue) { - return (tag != null && tag.getValue() != null) ? (T) tag.getValue() : defaultValue; - } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BrushableBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BrushableBlockEntityTranslator.java index d2777d372..4f9dfec46 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BrushableBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BrushableBlockEntityTranslator.java @@ -25,49 +25,46 @@ package org.geysermc.geyser.translator.level.block.entity; -import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; -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 org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.level.block.BlockStateValues; -import org.geysermc.geyser.network.GameProtocol; -import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.type.ItemMapping; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; @BlockEntity(type = BlockEntityType.BRUSHABLE_BLOCK) public class BrushableBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState { @Override - public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) { - if (!(tag.remove("item") instanceof CompoundTag itemTag)) { + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) { + NbtMap itemTag = javaNbt.getCompound("item"); + if (itemTag.isEmpty()) { return; } - Tag hitDirection = tag.get("hit_direction"); - if (hitDirection == null) { + byte hitDirection = javaNbt.getByte("hit_direction", (byte) -1); + if (hitDirection == -1) { // java server sends no direction when the item recedes back into the block (if player stops brushing) return; } - String id = ((StringTag) itemTag.get("id")).getValue(); + String id = itemTag.getString("id"); if (Items.AIR.javaIdentifier().equals(id)) { return; // server sends air when the block contains nothing } - ItemMapping mapping = Registries.ITEMS.forVersion(GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()).getMapping(id); + ItemMapping mapping = session.getItemMappings().getMapping(id); if (mapping == null) { return; } NbtMapBuilder itemBuilder = NbtMap.builder() .putString("Name", mapping.getBedrockIdentifier()) - .putByte("Count", (byte) itemTag.get("Count").getValue()); + .putByte("Count", (byte) itemTag.getByte("Count")); - builder.putCompound("item", itemBuilder.build()); + bedrockNbt.putCompound("item", itemBuilder.build()); // controls which side the item protrudes from - builder.putByte("brush_direction", ((Number) hitDirection.getValue()).byteValue()); + bedrockNbt.putByte("brush_direction", hitDirection); // controls how much the item protrudes - builder.putInt("brush_count", BlockStateValues.getBrushProgress(blockState)); + bedrockNbt.putInt("brush_count", BlockStateValues.getBrushProgress(blockState)); } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/CampfireBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/CampfireBlockEntityTranslator.java index 390615b9e..699319bb6 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/CampfireBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/CampfireBlockEntityTranslator.java @@ -25,37 +25,37 @@ package org.geysermc.geyser.translator.level.block.entity; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.ListTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; -import org.geysermc.geyser.network.GameProtocol; -import org.geysermc.geyser.registry.Registries; +import org.cloudburstmc.nbt.NbtType; import org.geysermc.geyser.registry.type.ItemMapping; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; +import java.util.List; + @BlockEntity(type = BlockEntityType.CAMPFIRE) public class CampfireBlockEntityTranslator extends BlockEntityTranslator { @Override - public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) { - if (tag.get("Items") instanceof ListTag items) { + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) { + List items = javaNbt.getList("Items", NbtType.COMPOUND); + if (items != null) { int i = 1; - for (Tag itemTag : items.getValue()) { - builder.put("Item" + i, getItem((CompoundTag) itemTag)); + for (NbtMap itemTag : items) { + bedrockNbt.put("Item" + i, getItem(session, itemTag)); i++; } } } - protected NbtMap getItem(CompoundTag tag) { - // TODO: Version independent mappings - ItemMapping mapping = Registries.ITEMS.forVersion(GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()).getMapping((String) tag.get("id").getValue()); - NbtMapBuilder tagBuilder = NbtMap.builder() - .putString("Name", mapping.getBedrockIdentifier()) - .putByte("Count", (byte) tag.get("Count").getValue()) - .putShort("Damage", (short) mapping.getBedrockData()); - tagBuilder.put("tag", NbtMap.builder().build()); + protected NbtMap getItem(GeyserSession session, NbtMap tag) { + ItemMapping mapping = session.getItemMappings().getMapping(tag.getString("id")); + if (mapping == null) { + mapping = ItemMapping.AIR; + } + NbtMapBuilder tagBuilder = BedrockItemBuilder.createItemNbt(mapping, tag.getByte("Count"), mapping.getBedrockData()); + tagBuilder.put("tag", NbtMap.builder().build()); // I don't think this is necessary... - Camo, 1.20.5/1.20.80 return tagBuilder.build(); } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/CommandBlockBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/CommandBlockBlockEntityTranslator.java index 31a7dbc69..0e00a19a8 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/CommandBlockBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/CommandBlockBlockEntityTranslator.java @@ -25,34 +25,31 @@ package org.geysermc.geyser.translator.level.block.entity; -import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; -import com.github.steveice10.opennbt.tag.builtin.*; +import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.text.MessageTranslator; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; @BlockEntity(type = BlockEntityType.COMMAND_BLOCK) public class CommandBlockBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState { @Override - public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) { - if (tag == null || tag.size() < 5) { + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) { + if (javaNbt == null || javaNbt.size() < 5) { return; // These values aren't here } // Java infers from the block state, but Bedrock needs it in the tag - builder.put("conditionalMode", BlockStateValues.getCommandBlockValues().getOrDefault(blockState, (byte) 0)); + bedrockNbt.putByte("conditionalMode", BlockStateValues.getCommandBlockValues().getOrDefault(blockState, (byte) 0)); // Java and Bedrock values - builder.put("conditionMet", ((ByteTag) tag.get("conditionMet")).getValue()); - builder.put("auto", ((ByteTag) tag.get("auto")).getValue()); - builder.put("CustomName", MessageTranslator.convertJsonMessage(((StringTag) tag.get("CustomName")).getValue())); - builder.put("powered", ((ByteTag) tag.get("powered")).getValue()); - builder.put("Command", ((StringTag) tag.get("Command")).getValue()); - builder.put("SuccessCount", ((IntTag) tag.get("SuccessCount")).getValue()); - builder.put("TrackOutput", ((ByteTag) tag.get("TrackOutput")).getValue()); - builder.put("UpdateLastExecution", ((ByteTag) tag.get("UpdateLastExecution")).getValue()); - if (tag.get("LastExecution") != null) { - builder.put("LastExecution", ((LongTag) tag.get("LastExecution")).getValue()); - } else { - builder.put("LastExecution", (long) 0); - } + bedrockNbt.putByte("conditionMet", javaNbt.getByte("conditionMet")); + bedrockNbt.putByte("auto", javaNbt.getByte("auto")); + bedrockNbt.putString("CustomName", MessageTranslator.convertJsonMessage(javaNbt.getString("CustomName"), session.locale())); + bedrockNbt.putByte("powered", javaNbt.getByte("powered")); + bedrockNbt.putString("Command", javaNbt.getString("Command")); + bedrockNbt.putInt("SuccessCount", javaNbt.getInt("SuccessCount")); + bedrockNbt.putByte("TrackOutput", javaNbt.getByte("TrackOutput")); + bedrockNbt.putByte("UpdateLastExecution", javaNbt.getByte("UpdateLastExecution")); + bedrockNbt.putLong("LastExecution", javaNbt.getLong("LastExecution")); // Note: may not be present? Was a null check before 1.20.5 } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DecoratedPotBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DecoratedPotBlockEntityTranslator.java index 3ab61c489..b24558b45 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DecoratedPotBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DecoratedPotBlockEntityTranslator.java @@ -25,33 +25,22 @@ package org.geysermc.geyser.translator.level.block.entity; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.ListTag; -import com.github.steveice10.opennbt.tag.builtin.StringTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; +import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; +import org.geysermc.geyser.session.GeyserSession; import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; -import java.util.ArrayList; -import java.util.List; - @BlockEntity(type = BlockEntityType.DECORATED_POT) public class DecoratedPotBlockEntityTranslator extends BlockEntityTranslator { @Override - public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) { - if (tag == null) { + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) { + if (javaNbt == null) { return; } // exact same format - if (tag.get("sherds") instanceof ListTag sherds) { - List translated = new ArrayList<>(4); - for (Tag sherd : sherds) { - translated.add(((StringTag) sherd).getValue()); - } - builder.putList("sherds", NbtType.STRING, translated); - } + bedrockNbt.putList("sherds", NbtType.STRING, javaNbt.getList("sherds", NbtType.STRING)); } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DoubleChestBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DoubleChestBlockEntityTranslator.java index 141520ed9..dcb39d22c 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DoubleChestBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DoubleChestBlockEntityTranslator.java @@ -25,8 +25,8 @@ package org.geysermc.geyser.translator.level.block.entity; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.cloudburstmc.math.vector.Vector3i; +import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.DoubleChestValue; @@ -47,17 +47,17 @@ public class DoubleChestBlockEntityTranslator extends BlockEntityTranslator impl @Override public void updateBlock(GeyserSession session, int blockState, Vector3i position) { NbtMapBuilder tagBuilder = getConstantBedrockTag(BlockEntityUtils.getBedrockBlockEntityId(BlockEntityType.CHEST), position.getX(), position.getY(), position.getZ()); - translateTag(tagBuilder, null, blockState); + translateTag(session, tagBuilder, null, blockState); BlockEntityUtils.updateBlockEntity(session, tagBuilder.build(), position); } @Override - public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) { + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) { DoubleChestValue chestValues = BlockStateValues.getDoubleChestValues().get(blockState); if (chestValues != null) { - int x = (int) builder.get("x"); - int z = (int) builder.get("z"); - translateChestValue(builder, chestValues, x, z); + int x = (int) bedrockNbt.get("x"); + int z = (int) bedrockNbt.get("z"); + translateChestValue(bedrockNbt, chestValues, x, z); } } @@ -88,10 +88,10 @@ public class DoubleChestBlockEntityTranslator extends BlockEntityTranslator impl x = x + (chestValues.isLeft() ? 1 : -1); } } - builder.put("pairx", x); - builder.put("pairz", z); + builder.putInt("pairx", x); + builder.putInt("pairz", z); if (!chestValues.isLeft()) { - builder.put("pairlead", (byte) 1); + builder.putInt("pairlead", (byte) 1); } } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/EmptyBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/EmptyBlockEntityTranslator.java index 1a7958c62..9ce0aff0a 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/EmptyBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/EmptyBlockEntityTranslator.java @@ -25,11 +25,12 @@ package org.geysermc.geyser.translator.level.block.entity; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; +import org.geysermc.geyser.session.GeyserSession; public class EmptyBlockEntityTranslator extends BlockEntityTranslator { @Override - public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) { + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) { } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/EndGatewayBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/EndGatewayBlockEntityTranslator.java index 633992431..97428eec1 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/EndGatewayBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/EndGatewayBlockEntityTranslator.java @@ -25,44 +25,28 @@ package org.geysermc.geyser.translator.level.block.entity; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.IntTag; -import com.github.steveice10.opennbt.tag.builtin.LongTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; import org.cloudburstmc.nbt.NbtList; +import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; +import org.geysermc.geyser.session.GeyserSession; import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; -import java.util.LinkedHashMap; - @BlockEntity(type = BlockEntityType.END_GATEWAY) public class EndGatewayBlockEntityTranslator extends BlockEntityTranslator { @Override - public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) { - Tag ageTag = tag.get("Age"); - if (ageTag instanceof LongTag) { - builder.put("Age", (int) ((long) ageTag.getValue())); - } + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) { + bedrockNbt.putInt("Age", (int) javaNbt.getLong("Age")); // Java sometimes does not provide this tag, but Bedrock crashes if it doesn't exist // Linked coordinates IntList tagsList = new IntArrayList(); // Yes, the axis letters are capitalized - tagsList.add(getExitPortalCoordinate(tag, "X")); - tagsList.add(getExitPortalCoordinate(tag, "Y")); - tagsList.add(getExitPortalCoordinate(tag, "Z")); - builder.put("ExitPortal", new NbtList<>(NbtType.INT, tagsList)); - } - - private int getExitPortalCoordinate(CompoundTag tag, String axis) { - // Return 0 if it doesn't exist, otherwise give proper value - if (tag.get("ExitPortal") != null) { - LinkedHashMap compoundTag = (LinkedHashMap) tag.get("ExitPortal").getValue(); - IntTag intTag = (IntTag) compoundTag.get(axis); - return intTag.getValue(); - } - return 0; + NbtMap exitPortal = javaNbt.getCompound("ExitPortal"); + tagsList.add(exitPortal.getInt("X", 0)); + tagsList.add(exitPortal.getInt("Y", 0)); + tagsList.add(exitPortal.getInt( "Z", 0)); + bedrockNbt.put("ExitPortal", new NbtList<>(NbtType.INT, tagsList)); } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/JigsawBlockBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/JigsawBlockBlockEntityTranslator.java index 34c051a34..bd83e3d54 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/JigsawBlockBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/JigsawBlockBlockEntityTranslator.java @@ -25,28 +25,27 @@ package org.geysermc.geyser.translator.level.block.entity; -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 org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.session.GeyserSession; import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; @BlockEntity(type = BlockEntityType.JIGSAW) public class JigsawBlockBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState { @Override - public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) { - Tag jointTag = tag.get("joint"); - if (jointTag instanceof StringTag) { - builder.put("joint", ((StringTag) jointTag).getValue()); + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) { + String joint = javaNbt.getString("joint", null); + if (joint != null) { + bedrockNbt.putString("joint", joint); } else { // Tag is not present in at least 1.14.4 Paper // Minecraft 1.18.1 deliberately has a fallback here, but not for any other value - builder.put("joint", BlockStateValues.getHorizontalFacingJigsaws().contains(blockState) ? "aligned" : "rollable"); + bedrockNbt.putString("joint", BlockStateValues.getHorizontalFacingJigsaws().contains(blockState) ? "aligned" : "rollable"); } - builder.put("name", getOrDefault(tag.get("name"), "")); - builder.put("target_pool", getOrDefault(tag.get("pool"), "")); - builder.put("final_state", ((StringTag) tag.get("final_state")).getValue()); - builder.put("target", getOrDefault(tag.get("target"), "")); + bedrockNbt.putString("name", javaNbt.getString("name")); + bedrockNbt.putString("target_pool", javaNbt.getString("target_pool")); + bedrockNbt.putString("final_state", javaNbt.getString("final_state")); + bedrockNbt.putString("target", javaNbt.getString("target")); } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/ShulkerBoxBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/ShulkerBoxBlockEntityTranslator.java index 529ed731e..ba2ddd815 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/ShulkerBoxBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/ShulkerBoxBlockEntityTranslator.java @@ -25,10 +25,11 @@ package org.geysermc.geyser.translator.level.block.entity; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.checkerframework.checker.nullness.qual.Nullable; +import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.inventory.ShulkerInventoryTranslator; import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; @@ -39,12 +40,12 @@ public class ShulkerBoxBlockEntityTranslator extends BlockEntityTranslator imple * where {@code tag} is passed as null. */ @Override - public void translateTag(NbtMapBuilder builder, @Nullable CompoundTag tag, int blockState) { + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, @Nullable NbtMap javaNbt, int blockState) { byte direction = BlockStateValues.getShulkerBoxDirection(blockState); // Just in case... if (direction == -1) { direction = 1; } - builder.put("facing", direction); + bedrockNbt.putByte("facing", direction); } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SignBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SignBlockEntityTranslator.java index 38a4f59c5..bbf0dbcb3 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SignBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SignBlockEntityTranslator.java @@ -25,15 +25,16 @@ package org.geysermc.geyser.translator.level.block.entity; -import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.ListTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; +import org.cloudburstmc.nbt.NbtType; +import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.util.SignUtils; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; + +import java.util.List; @BlockEntity(type = BlockEntityType.SIGN) public class SignBlockEntityTranslator extends BlockEntityTranslator { @@ -72,25 +73,21 @@ public class SignBlockEntityTranslator extends BlockEntityTranslator { } @Override - public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) { - builder.putCompound("FrontText", translateSide(tag.get("front_text"))); - builder.putCompound("BackText", translateSide(tag.get("back_text"))); - var waxed = tag.get("is_waxed"); - builder.putBoolean("IsWaxed", waxed != null && waxed.getValue() instanceof Number number && number.byteValue() != 0); + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) { + bedrockNbt.putCompound("FrontText", translateSide(javaNbt.getCompound("front_text"))); + bedrockNbt.putCompound("BackText", translateSide(javaNbt.getCompound("back_text"))); + bedrockNbt.putBoolean("IsWaxed", javaNbt.getBoolean("is_waxed")); } - private NbtMap translateSide(Tag tag) { - if (!(tag instanceof CompoundTag signData)) { - return NbtMap.EMPTY; - } + private NbtMap translateSide(NbtMap javaNbt) { NbtMapBuilder builder = NbtMap.builder(); StringBuilder signText = new StringBuilder(); - Tag messages = signData.get("messages"); - if (messages instanceof ListTag listTag) { - var it = listTag.iterator(); + List messages = javaNbt.getList("messages", NbtType.STRING); + if (!messages.isEmpty()) { + var it = messages.iterator(); while (it.hasNext()) { - String signLine = (String) it.next().getValue(); + String signLine = it.next(); signLine = MessageTranslator.convertMessageLenient(signLine); // Check the character width on the sign to ensure there is no overflow that is usually hidden @@ -133,13 +130,13 @@ public class SignBlockEntityTranslator extends BlockEntityTranslator { builder.putString("Text", signText.toString()); // Java Edition 1.14 added the ability to change the text color of the whole sign using dye - Tag color = signData.get("color"); + String color = javaNbt.getString("color", null); if (color != null) { - builder.putInt("SignTextColor", getBedrockSignColor(color.getValue().toString())); + builder.putInt("SignTextColor", getBedrockSignColor(color)); } // Glowing text - boolean isGlowing = getOrDefault(signData.get("has_glowing_text"), (byte) 0) != (byte) 0; + boolean isGlowing = javaNbt.getBoolean("has_glowing_text"); builder.putBoolean("IgnoreLighting", isGlowing); return builder.build(); } diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java index 38a056bd0..b1ab017e8 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java @@ -25,24 +25,22 @@ package org.geysermc.geyser.translator.level.block.entity; -import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.IntArrayTag; -import com.github.steveice10.opennbt.tag.builtin.ListTag; -import com.github.steveice10.opennbt.tag.builtin.StringTag; import org.checkerframework.checker.nullness.qual.Nullable; +import org.cloudburstmc.math.vector.Vector3i; +import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtMapBuilder; +import org.cloudburstmc.nbt.NbtType; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket; import org.geysermc.geyser.GeyserImpl; -import org.cloudburstmc.math.vector.Vector3i; -import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.SkullCache; import org.geysermc.geyser.skin.SkinProvider; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; import java.nio.charset.StandardCharsets; -import java.util.LinkedHashMap; +import java.util.List; import java.util.Locale; import java.util.UUID; import java.util.concurrent.CompletableFuture; @@ -52,56 +50,60 @@ import java.util.concurrent.ExecutionException; public class SkullBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState { @Override - public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) { + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) { byte skullVariant = BlockStateValues.getSkullVariant(blockState); float rotation = BlockStateValues.getSkullRotation(blockState) * 22.5f; // Just in case... if (skullVariant == -1) { skullVariant = 0; } - builder.put("Rotation", rotation); - builder.put("SkullType", skullVariant); + bedrockNbt.putFloat("Rotation", rotation); + bedrockNbt.putByte("SkullType", skullVariant); if (BlockStateValues.isSkullPowered(blockState)) { - builder.putBoolean("MouthMoving", true); + bedrockNbt.putBoolean("MouthMoving", true); } } - private static UUID getUUID(CompoundTag profile) { - if (profile.get("id") instanceof IntArrayTag uuidTag && uuidTag.length() == 4) { - int[] uuidAsArray = uuidTag.getValue(); + private static UUID getUUID(NbtMap profile) { + int[] uuidAsArray = profile.getIntArray("id"); + if (uuidAsArray.length == 4) { // thank u viaversion return new UUID((long) uuidAsArray[0] << 32 | ((long) uuidAsArray[1] & 0xFFFFFFFFL), (long) uuidAsArray[2] << 32 | ((long) uuidAsArray[3] & 0xFFFFFFFFL)); } // Convert username to an offline UUID String username = null; - if (profile.get("name") instanceof StringTag nameTag) { - username = nameTag.getValue().toLowerCase(Locale.ROOT); + String nameTag = profile.getString("name", null); + if (nameTag != null) { + username = nameTag.toLowerCase(Locale.ROOT); } return UUID.nameUUIDFromBytes(("OfflinePlayer:" + username).getBytes(StandardCharsets.UTF_8)); } - private static CompletableFuture getTextures(CompoundTag profile, UUID uuid) { - ListTag properties = profile.get("properties"); - if (properties == null) { + private static CompletableFuture<@Nullable String> getTextures(NbtMap profile, UUID uuid) { + List properties = profile.getList("properties", NbtType.COMPOUND); + if (properties.isEmpty()) { if (uuid != null && uuid.version() == 4) { String uuidString = uuid.toString().replace("-", ""); return SkinProvider.requestTexturesFromUUID(uuidString); - } else if (profile.get("name") instanceof StringTag nameTag) { - // Fall back to username if UUID was missing or was an offline mode UUID - return SkinProvider.requestTexturesFromUsername(nameTag.getValue()); + } else { + String nameTag = profile.getString("name", null); + if (nameTag != null) { + // Fall back to username if UUID was missing or was an offline mode UUID + return SkinProvider.requestTexturesFromUsername(nameTag); + } } return CompletableFuture.completedFuture(null); } - LinkedHashMap tag1 = (LinkedHashMap) properties.get(0).getValue(); - StringTag texture = (StringTag) tag1.get("value"); - return CompletableFuture.completedFuture(texture.getValue()); + NbtMap tag1 = properties.get(0); + String texture = tag1.getString("value", null); + return CompletableFuture.completedFuture(texture); } - public static @Nullable BlockDefinition translateSkull(GeyserSession session, CompoundTag tag, Vector3i blockPosition, int blockState) { - CompoundTag profile = tag.get("profile"); - if (profile == null) { + public static @Nullable BlockDefinition translateSkull(GeyserSession session, NbtMap javaNbt, Vector3i blockPosition, int blockState) { + NbtMap profile = javaNbt.getCompound("profile"); + if (profile.isEmpty()) { session.getSkullCache().removeSkull(blockPosition); return null; } @@ -112,13 +114,13 @@ public class SkullBlockEntityTranslator extends BlockEntityTranslator implements try { String texture = texturesFuture.get(); if (texture == null) { - session.getGeyser().getLogger().debug("Custom skull with invalid profile tag: " + blockPosition + " " + tag); + session.getGeyser().getLogger().debug("Custom skull with invalid profile tag: " + blockPosition + " " + javaNbt); return null; } SkullCache.Skull skull = session.getSkullCache().putSkull(blockPosition, uuid, texture, blockState); return skull.getBlockDefinition(); } catch (InterruptedException | ExecutionException e) { - session.getGeyser().getLogger().debug("Failed to acquire textures for custom skull: " + blockPosition + " " + tag); + session.getGeyser().getLogger().debug("Failed to acquire textures for custom skull: " + blockPosition + " " + javaNbt); if (GeyserImpl.getInstance().getConfig().isDebugMode()) { e.printStackTrace(); } @@ -129,7 +131,7 @@ public class SkullBlockEntityTranslator extends BlockEntityTranslator implements // profile contained a username, so we have to wait for it to be retrieved texturesFuture.whenComplete((texturesProperty, throwable) -> { if (texturesProperty == null) { - session.getGeyser().getLogger().debug("Custom skull with invalid profile tag: " + blockPosition + " " + tag); + session.getGeyser().getLogger().debug("Custom skull with invalid profile tag: " + blockPosition + " " + javaNbt); return; } if (session.getEventLoop().inEventLoop()) { diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SpawnerBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SpawnerBlockEntityTranslator.java index 5611bf90c..05b763e6b 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SpawnerBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SpawnerBlockEntityTranslator.java @@ -25,10 +25,6 @@ package org.geysermc.geyser.translator.level.block.entity; -import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; -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 org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3i; @@ -38,17 +34,18 @@ import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; @BlockEntity(type = BlockEntityType.MOB_SPAWNER) public class SpawnerBlockEntityTranslator extends BlockEntityTranslator { @Override - public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, CompoundTag tag, int blockState) { + public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, NbtMap javaNbt, int blockState) { // Sending an empty EntityIdentifier to empty the spawner is ignored by the client, so we send a whole new spawner! // Fixes https://github.com/GeyserMC/Geyser/issues/4214 - CompoundTag spawnData = tag.get("SpawnData"); + NbtMap spawnData = javaNbt.getCompound("SpawnData"); if (spawnData != null) { - CompoundTag entityTag = spawnData.get("entity"); + NbtMap entityTag = spawnData.getCompound("entity"); if (entityTag.isEmpty()) { Vector3i position = Vector3i.from(x, y, z); // Set to air and back to reset the spawner - "just" updating the spawner doesn't work @@ -66,62 +63,63 @@ public class SpawnerBlockEntityTranslator extends BlockEntityTranslator { } } - return super.getBlockEntityTag(session, type, x, y, z, tag, blockState); + return super.getBlockEntityTag(session, type, x, y, z, javaNbt, blockState); } @Override - public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) { - Tag current; + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) { + Object current; - if ((current = tag.get("MaxNearbyEntities")) != null) { - builder.put("MaxNearbyEntities", current.getValue()); + // TODO use primitive get and put methods + if ((current = javaNbt.get("MaxNearbyEntities")) != null) { + bedrockNbt.put("MaxNearbyEntities", current); } - if ((current = tag.get("RequiredPlayerRange")) != null) { - builder.put("RequiredPlayerRange", current.getValue()); + if ((current = javaNbt.get("RequiredPlayerRange")) != null) { + bedrockNbt.put("RequiredPlayerRange", current); } - if ((current = tag.get("SpawnCount")) != null) { - builder.put("SpawnCount", current.getValue()); + if ((current = javaNbt.get("SpawnCount")) != null) { + bedrockNbt.put("SpawnCount", current); } - if ((current = tag.get("MaxSpawnDelay")) != null) { - builder.put("MaxSpawnDelay", current.getValue()); + if ((current = javaNbt.get("MaxSpawnDelay")) != null) { + bedrockNbt.put("MaxSpawnDelay", current); } - if ((current = tag.get("Delay")) != null) { - builder.put("Delay", current.getValue()); + if ((current = javaNbt.get("Delay")) != null) { + bedrockNbt.put("Delay", current); } - if ((current = tag.get("SpawnRange")) != null) { - builder.put("SpawnRange", current.getValue()); + if ((current = javaNbt.get("SpawnRange")) != null) { + bedrockNbt.put("SpawnRange", current); } - if ((current = tag.get("MinSpawnDelay")) != null) { - builder.put("MinSpawnDelay", current.getValue()); + if ((current = javaNbt.get("MinSpawnDelay")) != null) { + bedrockNbt.put("MinSpawnDelay", current); } - translateSpawnData(builder, tag.get("SpawnData")); + translateSpawnData(bedrockNbt, javaNbt.getCompound("SpawnData", null)); - builder.put("isMovable", (byte) 1); + bedrockNbt.put("isMovable", (byte) 1); } - static void translateSpawnData(@NonNull NbtMapBuilder builder, @Nullable CompoundTag spawnData) { + static void translateSpawnData(@NonNull NbtMapBuilder builder, @Nullable NbtMap spawnData) { if (spawnData == null) { return; } - CompoundTag entityTag = spawnData.get("entity"); - if (entityTag.get("id") instanceof StringTag idTag) { + NbtMap entityTag = spawnData.getCompound("entity"); + String entityId = entityTag.getString("id"); + if (entityId != null) { // As of 1.19.3, spawners can be empty - String entityId = idTag.getValue(); builder.put("EntityIdentifier", entityId); EntityDefinition definition = Registries.JAVA_ENTITY_IDENTIFIERS.get(entityId); if (definition != null) { - builder.put("DisplayEntityWidth", definition.width()); - builder.put("DisplayEntityHeight", definition.height()); - builder.put("DisplayEntityScale", 1.0f); + builder.putFloat("DisplayEntityWidth", definition.width()); + builder.putFloat("DisplayEntityHeight", definition.height()); + builder.putFloat("DisplayEntityScale", 1.0f); } } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/StructureBlockBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/StructureBlockBlockEntityTranslator.java index 40b10de40..aefd97dd5 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/StructureBlockBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/StructureBlockBlockEntityTranslator.java @@ -25,8 +25,6 @@ package org.geysermc.geyser.translator.level.block.entity; -import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; @@ -35,22 +33,23 @@ import org.cloudburstmc.protocol.bedrock.data.structure.StructureRotation; import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.StructureBlockUtils; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; @BlockEntity(type = BlockEntityType.STRUCTURE_BLOCK) public class StructureBlockBlockEntityTranslator extends BlockEntityTranslator { @Override - public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, CompoundTag tag, int blockState) { + public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, NbtMap javaNbt, int blockState) { // Sending a structure with size 0 doesn't clear the outline. Hence, we have to force it by replacing the block :/ - int xStructureSize = getOrDefault(tag.get("sizeX"), 0); - int yStructureSize = getOrDefault(tag.get("sizeY"), 0); - int zStructureSize = getOrDefault(tag.get("sizeZ"), 0); + int xStructureSize = javaNbt.getInt("sizeX"); + int yStructureSize = javaNbt.getInt("sizeY"); + int zStructureSize = javaNbt.getInt("sizeZ"); Vector3i size = Vector3i.from(xStructureSize, yStructureSize, zStructureSize); if (size.equals(Vector3i.ZERO)) { Vector3i position = Vector3i.from(x, y, z); - String mode = getOrDefault(tag.get("mode"), ""); + String mode = javaNbt.getString("mode"); // Set to air and back to reset the structure block UpdateBlockPacket emptyBlockPacket = new UpdateBlockPacket(); @@ -66,18 +65,18 @@ public class StructureBlockBlockEntityTranslator extends BlockEntityTranslator { session.sendUpstreamPacket(spawnerBlockPacket); } - return super.getBlockEntityTag(session, type, x, y, z, tag, blockState); + return super.getBlockEntityTag(session, type, x, y, z, javaNbt, blockState); } @Override - public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) { - if (tag.size() < 5) { + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) { + if (javaNbt.size() < 5) { return; // These values aren't here } - builder.putString("structureName", getOrDefault(tag.get("name"), "")); + bedrockNbt.putString("structureName", javaNbt.getString("name")); - String mode = getOrDefault(tag.get("mode"), ""); + String mode = javaNbt.getString("mode"); int bedrockData = switch (mode) { case "LOAD" -> 2; case "CORNER" -> 3; @@ -85,53 +84,53 @@ public class StructureBlockBlockEntityTranslator extends BlockEntityTranslator { default -> 1; // SAVE }; - builder.putInt("data", bedrockData); - builder.putString("dataField", ""); // ??? possibly related to Java's "metadata" + bedrockNbt.putInt("data", bedrockData); + bedrockNbt.putString("dataField", ""); // ??? possibly related to Java's "metadata" // Mirror behaves different in Java and Bedrock - it requires modifying the position in space as well - String mirror = getOrDefault(tag.get("mirror"), ""); + String mirror = javaNbt.getString("mirror"); StructureMirror bedrockMirror = switch (mirror) { case "FRONT_BACK" -> StructureMirror.X; case "LEFT_RIGHT" -> StructureMirror.Z; default -> StructureMirror.NONE; }; - builder.putByte("mirror", (byte) bedrockMirror.ordinal()); + bedrockNbt.putByte("mirror", (byte) bedrockMirror.ordinal()); - builder.putByte("ignoreEntities", getOrDefault(tag.get("ignoreEntities"), (byte) 0)); - builder.putByte("isPowered", getOrDefault(tag.get("powered"), (byte) 0)); - builder.putLong("seed", getOrDefault(tag.get("seed"), 0L)); - builder.putByte("showBoundingBox", getOrDefault(tag.get("showboundingbox"), (byte) 0)); + bedrockNbt.putByte("ignoreEntities", javaNbt.getByte("ignoreEntities")); + bedrockNbt.putByte("isPowered", javaNbt.getByte("powered")); + bedrockNbt.putLong("seed", javaNbt.getLong("seed")); + bedrockNbt.putByte("showBoundingBox", javaNbt.getByte("showboundingbox")); - String rotation = getOrDefault(tag.get("rotation"), ""); + String rotation = javaNbt.getString("rotation"); StructureRotation bedrockRotation = switch (rotation) { case "CLOCKWISE_90" -> StructureRotation.ROTATE_90; case "CLOCKWISE_180" -> StructureRotation.ROTATE_180; case "COUNTERCLOCKWISE_90" -> StructureRotation.ROTATE_270; default -> StructureRotation.NONE; }; - builder.putByte("rotation", (byte) bedrockRotation.ordinal()); + bedrockNbt.putByte("rotation", (byte) bedrockRotation.ordinal()); - int xStructureSize = getOrDefault(tag.get("sizeX"), 0); - int yStructureSize = getOrDefault(tag.get("sizeY"), 0); - int zStructureSize = getOrDefault(tag.get("sizeZ"), 0); + int xStructureSize = javaNbt.getInt("sizeX"); + int yStructureSize = javaNbt.getInt("sizeY"); + int zStructureSize = javaNbt.getInt("sizeZ"); // The "positions" are also offsets on Java - int posX = getOrDefault(tag.get("posX"), 0); - int posY = getOrDefault(tag.get("posY"), 0); - int posZ = getOrDefault(tag.get("posZ"), 0); + int posX = javaNbt.getInt("posX"); + int posY = javaNbt.getInt("posY"); + int posZ = javaNbt.getInt("posZ"); Vector3i offset = StructureBlockUtils.calculateOffset(bedrockRotation, bedrockMirror, xStructureSize, zStructureSize); - builder.putInt("xStructureOffset", posX + offset.getX()); - builder.putInt("yStructureOffset", posY); - builder.putInt("zStructureOffset", posZ + offset.getZ()); + bedrockNbt.putInt("xStructureOffset", posX + offset.getX()); + bedrockNbt.putInt("yStructureOffset", posY); + bedrockNbt.putInt("zStructureOffset", posZ + offset.getZ()); - builder.putInt("xStructureSize", xStructureSize); - builder.putInt("yStructureSize", yStructureSize); - builder.putInt("zStructureSize", zStructureSize); + bedrockNbt.putInt("xStructureSize", xStructureSize); + bedrockNbt.putInt("yStructureSize", yStructureSize); + bedrockNbt.putInt("zStructureSize", zStructureSize); - builder.putFloat("integrity", getOrDefault(tag.get("integrity"), 0f)); // Is 1.0f by default on Java but 100.0f on Bedrock + bedrockNbt.putFloat("integrity", javaNbt.getFloat("integrity")); // Is 1.0f by default on Java but 100.0f on Bedrock // Java's "showair" is unrepresented } diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/TrialSpawnerBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/TrialSpawnerBlockEntityTranslator.java index da013cf3c..ff3f89f3f 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/TrialSpawnerBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/TrialSpawnerBlockEntityTranslator.java @@ -25,23 +25,24 @@ package org.geysermc.geyser.translator.level.block.entity; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; +import org.geysermc.geyser.session.GeyserSession; import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; @BlockEntity(type = BlockEntityType.TRIAL_SPAWNER) public class TrialSpawnerBlockEntityTranslator extends BlockEntityTranslator { @Override - public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) { - if (tag == null) { + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) { + if (javaNbt == null) { return; } // trial spawners have "spawn_data" instead of "SpawnData" - SpawnerBlockEntityTranslator.translateSpawnData(builder, tag.get("spawn_data")); + SpawnerBlockEntityTranslator.translateSpawnData(bedrockNbt, javaNbt.getCompound("spawn_data", null)); // Because trial spawners don't exist on bedrock yet - builder.put("id", "MobSpawner"); + bedrockNbt.put("id", "MobSpawner"); } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEntityDataTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEntityDataTranslator.java index 82b51dfdd..b13344fd3 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEntityDataTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEntityDataTranslator.java @@ -25,9 +25,8 @@ package org.geysermc.geyser.translator.protocol.java.level; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; import org.cloudburstmc.math.vector.Vector3i; +import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; import org.cloudburstmc.protocol.bedrock.data.structure.StructureMirror; @@ -71,7 +70,7 @@ public class JavaBlockEntityDataTranslator extends PacketTranslator 5 ) { - CompoundTag map = packet.getNbt(); + NbtMap map = packet.getNbt(); - String mode = getOrDefault(map.get("mode"), ""); + String mode = map.getString("mode"); if (!mode.equalsIgnoreCase("LOAD")) { return; } - String mirror = getOrDefault(map.get("mirror"), ""); + String mirror = map.getString("mirror"); StructureMirror bedrockMirror = switch (mirror) { case "FRONT_BACK" -> StructureMirror.X; case "LEFT_RIGHT" -> StructureMirror.Z; default -> StructureMirror.NONE; }; - String rotation = getOrDefault(map.get("rotation"), ""); + String rotation = map.getString("rotation"); StructureRotation bedrockRotation = switch (rotation) { case "CLOCKWISE_90" -> StructureRotation.ROTATE_90; case "CLOCKWISE_180" -> StructureRotation.ROTATE_180; @@ -129,10 +128,10 @@ public class JavaBlockEntityDataTranslator extends PacketTranslator StructureRotation.NONE; }; - String name = getOrDefault(map.get("name"), ""); - int sizeX = getOrDefault(map.get("sizeX"), 0); - int sizeY = getOrDefault(map.get("sizeY"), 0); - int sizeZ = getOrDefault(map.get("sizeZ"), 0); + String name = map.getString("name"); + int sizeX = map.getInt("sizeX"); + int sizeY = map.getInt("sizeY"); + int sizeZ = map.getInt("sizeZ"); session.getStructureBlockCache().setCurrentStructureBlock(null); @@ -149,10 +148,4 @@ public class JavaBlockEntityDataTranslator extends PacketTranslator T getOrDefault(Tag tag, T defaultValue) { - //noinspection unchecked - return (tag != null && tag.getValue() != null) ? (T) tag.getValue() : defaultValue; - } } 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 609574cdd..c3a399863 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 @@ -25,7 +25,6 @@ package org.geysermc.geyser.translator.protocol.java.level; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufOutputStream; @@ -385,7 +384,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator> 4) - (bedrockDimension.minY() >> 4); diff --git a/core/src/main/java/org/geysermc/geyser/translator/sound/BlockSoundInteractionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/sound/BlockSoundInteractionTranslator.java index ead619b68..02e5044bb 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/sound/BlockSoundInteractionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/sound/BlockSoundInteractionTranslator.java @@ -25,16 +25,12 @@ package org.geysermc.geyser.translator.sound; -import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.ListTag; -import com.github.steveice10.opennbt.tag.builtin.StringTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; import org.cloudburstmc.math.vector.Vector3f; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.util.BlockUtils; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import java.util.Map; @@ -104,25 +100,14 @@ public interface BlockSoundInteractionTranslator extends SoundInteractionTransla return true; } - CompoundTag tag = itemInHand.getNbt(); - if (tag == null) { - // No CanPlaceOn tag can exist - return false; - } - ListTag canPlaceOn = tag.get("CanPlaceOn"); - if (canPlaceOn == null || canPlaceOn.size() == 0) { - return false; + var canPlaceOn = itemInHand.getComponent(DataComponentType.CAN_PLACE_ON); + if (canPlaceOn == null || canPlaceOn.getPredicates().isEmpty()) { + // Component doesn't exist - no restrictions apply. + return true; } - String cleanIdentifier = BlockUtils.getCleanIdentifier(blockIdentifier); - - for (Tag t : canPlaceOn) { - if (t instanceof StringTag stringTag) { - if (cleanIdentifier.equals(stringTag.getValue())) { - // This operation would/could be a success! - return true; - } - } + for (var blockPredicate : canPlaceOn.getPredicates()) { + // I don't want to deal with this right now. TODO } // The block in world is not present in the CanPlaceOn tag on the item diff --git a/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java index 612b9c38b..3f1c902c7 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java @@ -187,14 +187,28 @@ public class MessageTranslator { } } + /** + * Convenience method for locale getting. + */ + public static String convertJsonMessage(GeyserSession session, String message) { + return convertJsonMessage(message, session.locale()); + } + public static String convertJsonMessage(String message, String locale) { return convertMessage(GSON_SERIALIZER.deserialize(message), locale); } - public static String convertJsonMessage(String message) { - return convertJsonMessage(message, GeyserLocale.getDefaultLocale()); + /** + * Convenience method for locale getting. + */ + public static String convertMessage(GeyserSession session, Component message) { + return convertMessage(message, session.locale()); } + /** + * DO NOT USE THIS METHOD unless where you're calling from does not have a (reliable) way of getting the + * context's locale. + */ public static String convertMessage(Component message) { return convertMessage(message, GeyserLocale.getDefaultLocale()); } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3cb136683..f8f979539 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ protocol-connection = "3.0.0.Beta1-20240411.165033-128" raknet = "1.0.0.CR3-20240416.144209-1" blockstateupdater="1.20.80-20240411.142413-1" mcauthlib = "d9d773e" -mcprotocollib = "1ca8808" # Revert from jitpack after release +mcprotocollib = "98410a1" # Revert from jitpack after release adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" From f47754be03819954a9d9499831b5e59595a0930a Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sat, 27 Apr 2024 15:49:19 -0400 Subject: [PATCH 301/344] Goat horns --- .../geyser/item/type/GoatHornItem.java | 28 ++----------------- .../translator/item/ItemTranslator.java | 5 ++-- 2 files changed, 5 insertions(+), 28 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java b/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java index c31e15578..cd21c0b6e 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java @@ -35,20 +35,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponen import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; import org.geysermc.mcprotocollib.protocol.data.game.item.component.Instrument; -import java.util.List; - public class GoatHornItem extends Item { - private static final List INSTRUMENTS = List.of( - "ponder_goat_horn", - "sing_goat_horn", - "seek_goat_horn", - "feel_goat_horn", - "admire_goat_horn", - "call_goat_horn", - "yearn_goat_horn", - "dream_goat_horn" // Called "Resist" on Bedrock 1.19.0 due to https://bugs.mojang.com/browse/MCPE-155059 - ); - public GoatHornItem(String javaIdentifier, Builder builder) { super(javaIdentifier, builder); } @@ -60,19 +47,8 @@ public class GoatHornItem extends Item { return builder; } Holder instrument = components.get(DataComponentType.INSTRUMENT); - // TODO registry - if (instrument != null) { - // Drop the Minecraft namespace if applicable -// if (instrument.startsWith("minecraft:")) { -// instrument = instrument.substring("minecraft:".length()); -// } -// -// int damage = INSTRUMENTS.indexOf(instrument); -// if (damage == -1) { -// damage = 0; -// GeyserImpl.getInstance().getLogger().debug("Unknown goat horn instrument: " + instrumentTag.getValue()); -// } -// builder.damage(damage); + if (instrument != null && instrument.isId()) { + builder.damage(instrument.id()); } return builder; } diff --git a/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java index 2535a5652..629192e01 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java @@ -93,7 +93,8 @@ public final class ItemTranslator { NbtMap nbt = data.getTag(); if (nbt != null && !nbt.isEmpty()) { - DataComponents components = new DataComponents(new HashMap<>()); + // translateToJava may have added components + DataComponents components = itemStack.getComponents() == null ? new DataComponents(new HashMap<>()) : itemStack.getComponents(); javaItem.translateNbtToJava(nbt, components, bedrockItem); if (!components.getDataComponents().isEmpty()) { itemStack.setComponents(components); @@ -394,7 +395,7 @@ public final class ItemTranslator { customName = components.get(DataComponentType.ITEM_NAME); } if (customName != null) { - // Get the translated name and prefix it with a reset char TODO test + // Get the translated name and prefix it with a reset char return MessageTranslator.convertMessage(customName, session.locale()); } } From 6d5ac233d6112dd65f162064c55963b20373285d Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sat, 27 Apr 2024 21:00:10 -0400 Subject: [PATCH 302/344] Dyeable items work. --- .../geyser/entity/EntityDefinitions.java | 6 +-- ...ippedArrowEntity.java => ArrowEntity.java} | 7 +-- .../geyser/inventory/item/Potion.java | 9 ---- .../inventory/item/TippedArrowPotion.java | 9 ---- .../geyser/item/DyeableLeatherItem.java | 42 ----------------- .../java/org/geysermc/geyser/item/Items.java | 46 +++++++++---------- .../geysermc/geyser/item/type/ChestItem.java | 44 ------------------ .../geyser/item/type/DyeableArmorItem.java | 12 +++-- .../item/type/DyeableHorseArmorItem.java | 45 ------------------ .../geysermc/geyser/item/type/FlowerItem.java | 33 ------------- .../translator/item/ItemTranslator.java | 16 +++---- 11 files changed, 45 insertions(+), 224 deletions(-) rename core/src/main/java/org/geysermc/geyser/entity/type/{TippedArrowEntity.java => ArrowEntity.java} (86%) delete mode 100644 core/src/main/java/org/geysermc/geyser/item/DyeableLeatherItem.java delete mode 100644 core/src/main/java/org/geysermc/geyser/item/type/ChestItem.java delete mode 100644 core/src/main/java/org/geysermc/geyser/item/type/DyeableHorseArmorItem.java delete mode 100644 core/src/main/java/org/geysermc/geyser/item/type/FlowerItem.java diff --git a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java index 317892676..4063a675c 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java +++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java @@ -56,7 +56,7 @@ public final class EntityDefinitions { public static final EntityDefinition AREA_EFFECT_CLOUD; public static final EntityDefinition ARMADILLO; public static final EntityDefinition ARMOR_STAND; - public static final EntityDefinition ARROW; + public static final EntityDefinition ARROW; public static final EntityDefinition AXOLOTL; public static final EntityDefinition BAT; public static final EntityDefinition BEE; @@ -378,10 +378,10 @@ public final class EntityDefinitions { .addTranslator(MetadataType.BYTE, AbstractArrowEntity::setArrowFlags) .addTranslator(null) // "Piercing level" .build(); - ARROW = EntityDefinition.inherited(TippedArrowEntity::new, abstractArrowBase) + ARROW = EntityDefinition.inherited(ArrowEntity::new, abstractArrowBase) .type(EntityType.ARROW) .heightAndWidth(0.25f) - .addTranslator(MetadataType.INT, TippedArrowEntity::setPotionEffectColor) + .addTranslator(MetadataType.INT, ArrowEntity::setPotionEffectColor) .build(); SPECTRAL_ARROW = EntityDefinition.inherited(abstractArrowBase.factory(), abstractArrowBase) .type(EntityType.SPECTRAL_ARROW) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/TippedArrowEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ArrowEntity.java similarity index 86% rename from core/src/main/java/org/geysermc/geyser/entity/type/TippedArrowEntity.java rename to core/src/main/java/org/geysermc/geyser/entity/type/ArrowEntity.java index be4133028..1ee706811 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/TippedArrowEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/ArrowEntity.java @@ -34,12 +34,9 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEnt import java.util.UUID; -/** - * Internally this is known as TippedArrowEntity but is used with tipped arrows and normal arrows - */ -public class TippedArrowEntity extends AbstractArrowEntity { +public class ArrowEntity extends AbstractArrowEntity { - public TippedArrowEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { + public ArrowEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); } diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/Potion.java b/core/src/main/java/org/geysermc/geyser/inventory/item/Potion.java index 79b9565fb..00a9b091e 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/item/Potion.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/item/Potion.java @@ -91,15 +91,6 @@ public enum Potion { return new PotionContents(this.ordinal(), -1, Int2ObjectMaps.emptyMap()); } - public static @Nullable Potion getByJavaIdentifier(String javaIdentifier) { - for (Potion potion : VALUES) { - if (potion.javaIdentifier.equals(javaIdentifier)) { - return potion; - } - } - return null; - } - public static @Nullable Potion getByBedrockId(int bedrockId) { for (Potion potion : VALUES) { if (potion.bedrockId == bedrockId) { diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/TippedArrowPotion.java b/core/src/main/java/org/geysermc/geyser/inventory/item/TippedArrowPotion.java index 5c33fec67..ec6b10ec8 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/item/TippedArrowPotion.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/item/TippedArrowPotion.java @@ -99,15 +99,6 @@ public enum TippedArrowPotion { return VALUES[id]; } - public static @Nullable TippedArrowPotion getByJavaIdentifier(String javaIdentifier) { - for (TippedArrowPotion potion : VALUES) { - if (potion.javaIdentifier.equals(javaIdentifier)) { - return potion; - } - } - return null; - } - public static @Nullable TippedArrowPotion getByBedrockId(int bedrockId) { for (TippedArrowPotion potion : VALUES) { if (potion.bedrockId == bedrockId) { diff --git a/core/src/main/java/org/geysermc/geyser/item/DyeableLeatherItem.java b/core/src/main/java/org/geysermc/geyser/item/DyeableLeatherItem.java deleted file mode 100644 index eabdbee87..000000000 --- a/core/src/main/java/org/geysermc/geyser/item/DyeableLeatherItem.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2019-2023 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.item; - -import org.geysermc.geyser.translator.item.BedrockItemBuilder; -import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; -import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; -import org.geysermc.mcprotocollib.protocol.data.game.item.component.DyedItemColor; - -public interface DyeableLeatherItem { - - static void translateComponentsToBedrock(DataComponents components, BedrockItemBuilder builder) { - DyedItemColor dyedItemColor = components.get(DataComponentType.DYED_COLOR); - if (dyedItemColor == null) { - return; - } - builder.putInt("customColor", dyedItemColor.getRgb()); - } -} diff --git a/core/src/main/java/org/geysermc/geyser/item/Items.java b/core/src/main/java/org/geysermc/geyser/item/Items.java index 42a087acf..f13330700 100644 --- a/core/src/main/java/org/geysermc/geyser/item/Items.java +++ b/core/src/main/java/org/geysermc/geyser/item/Items.java @@ -256,20 +256,20 @@ public final class Items { public static final Item GREEN_WOOL = register(new BlockItem("green_wool", builder())); public static final Item RED_WOOL = register(new BlockItem("red_wool", builder())); public static final Item BLACK_WOOL = register(new BlockItem("black_wool", builder())); - public static final Item DANDELION = register(new FlowerItem("dandelion", builder())); - public static final Item POPPY = register(new FlowerItem("poppy", builder())); - public static final Item BLUE_ORCHID = register(new FlowerItem("blue_orchid", builder())); - public static final Item ALLIUM = register(new FlowerItem("allium", builder())); - public static final Item AZURE_BLUET = register(new FlowerItem("azure_bluet", builder())); - public static final Item RED_TULIP = register(new FlowerItem("red_tulip", builder())); - public static final Item ORANGE_TULIP = register(new FlowerItem("orange_tulip", builder())); - public static final Item WHITE_TULIP = register(new FlowerItem("white_tulip", builder())); - public static final Item PINK_TULIP = register(new FlowerItem("pink_tulip", builder())); - public static final Item OXEYE_DAISY = register(new FlowerItem("oxeye_daisy", builder())); - public static final Item CORNFLOWER = register(new FlowerItem("cornflower", builder())); - public static final Item LILY_OF_THE_VALLEY = register(new FlowerItem("lily_of_the_valley", builder())); - public static final Item WITHER_ROSE = register(new FlowerItem("wither_rose", builder())); - public static final Item TORCHFLOWER = register(new FlowerItem("torchflower", builder())); + public static final Item DANDELION = register(new BlockItem("dandelion", builder())); + public static final Item POPPY = register(new BlockItem("poppy", builder())); + public static final Item BLUE_ORCHID = register(new BlockItem("blue_orchid", builder())); + public static final Item ALLIUM = register(new BlockItem("allium", builder())); + public static final Item AZURE_BLUET = register(new BlockItem("azure_bluet", builder())); + public static final Item RED_TULIP = register(new BlockItem("red_tulip", builder())); + public static final Item ORANGE_TULIP = register(new BlockItem("orange_tulip", builder())); + public static final Item WHITE_TULIP = register(new BlockItem("white_tulip", builder())); + public static final Item PINK_TULIP = register(new BlockItem("pink_tulip", builder())); + public static final Item OXEYE_DAISY = register(new BlockItem("oxeye_daisy", builder())); + public static final Item CORNFLOWER = register(new BlockItem("cornflower", builder())); + public static final Item LILY_OF_THE_VALLEY = register(new BlockItem("lily_of_the_valley", builder())); + public static final Item WITHER_ROSE = register(new BlockItem("wither_rose", builder())); + public static final Item TORCHFLOWER = register(new BlockItem("torchflower", builder())); public static final Item PITCHER_PLANT = register(new BlockItem("pitcher_plant", builder())); public static final Item SPORE_BLOSSOM = register(new BlockItem("spore_blossom", builder())); public static final Item BROWN_MUSHROOM = register(new BlockItem("brown_mushroom", builder())); @@ -337,7 +337,7 @@ public final class Items { public static final Item PURPUR_PILLAR = register(new BlockItem("purpur_pillar", builder())); public static final Item PURPUR_STAIRS = register(new BlockItem("purpur_stairs", builder())); public static final Item SPAWNER = register(new BlockItem("spawner", builder())); - public static final Item CHEST = register(new ChestItem("chest", builder())); + public static final Item CHEST = register(new BlockItem("chest", builder())); public static final Item CRAFTING_TABLE = register(new BlockItem("crafting_table", builder())); public static final Item FARMLAND = register(new BlockItem("farmland", builder())); public static final Item FURNACE = register(new BlockItem("furnace", builder())); @@ -419,7 +419,7 @@ public final class Items { public static final Item END_STONE_BRICKS = register(new BlockItem("end_stone_bricks", builder())); public static final Item DRAGON_EGG = register(new BlockItem("dragon_egg", builder())); public static final Item SANDSTONE_STAIRS = register(new BlockItem("sandstone_stairs", builder())); - public static final Item ENDER_CHEST = register(new ChestItem("ender_chest", builder())); + public static final Item ENDER_CHEST = register(new BlockItem("ender_chest", builder())); public static final Item EMERALD_BLOCK = register(new BlockItem("emerald_block", builder())); public static final Item OAK_STAIRS = register(new BlockItem("oak_stairs", builder())); public static final Item SPRUCE_STAIRS = register(new BlockItem("spruce_stairs", builder())); @@ -716,7 +716,7 @@ public final class Items { public static final Item SCULK_SENSOR = register(new BlockItem("sculk_sensor", builder())); public static final Item CALIBRATED_SCULK_SENSOR = register(new BlockItem("calibrated_sculk_sensor", builder())); public static final Item TRIPWIRE_HOOK = register(new BlockItem("tripwire_hook", builder())); - public static final Item TRAPPED_CHEST = register(new ChestItem("trapped_chest", builder())); + public static final Item TRAPPED_CHEST = register(new BlockItem("trapped_chest", builder())); public static final Item TNT = register(new BlockItem("tnt", builder())); public static final Item REDSTONE_LAMP = register(new BlockItem("redstone_lamp", builder())); public static final Item NOTE_BLOCK = register(new BlockItem("note_block", builder())); @@ -894,10 +894,10 @@ public final class Items { public static final Item WHEAT_SEEDS = register(new BlockItem("wheat_seeds", builder())); public static final Item WHEAT = register(new Item("wheat", builder())); public static final Item BREAD = register(new Item("bread", builder())); - public static final Item LEATHER_HELMET = register(new ArmorItem("leather_helmet", ArmorMaterial.LEATHER, builder().stackSize(1).maxDamage(55))); - public static final Item LEATHER_CHESTPLATE = register(new ArmorItem("leather_chestplate", ArmorMaterial.LEATHER, builder().stackSize(1).maxDamage(80))); - public static final Item LEATHER_LEGGINGS = register(new ArmorItem("leather_leggings", ArmorMaterial.LEATHER, builder().stackSize(1).maxDamage(75))); - public static final Item LEATHER_BOOTS = register(new ArmorItem("leather_boots", ArmorMaterial.LEATHER, builder().stackSize(1).maxDamage(65))); + public static final Item LEATHER_HELMET = register(new DyeableArmorItem("leather_helmet", ArmorMaterial.LEATHER, builder().stackSize(1).maxDamage(55))); + public static final Item LEATHER_CHESTPLATE = register(new DyeableArmorItem("leather_chestplate", ArmorMaterial.LEATHER, builder().stackSize(1).maxDamage(80))); + public static final Item LEATHER_LEGGINGS = register(new DyeableArmorItem("leather_leggings", ArmorMaterial.LEATHER, builder().stackSize(1).maxDamage(75))); + public static final Item LEATHER_BOOTS = register(new DyeableArmorItem("leather_boots", ArmorMaterial.LEATHER, builder().stackSize(1).maxDamage(65))); public static final Item CHAINMAIL_HELMET = register(new ArmorItem("chainmail_helmet", ArmorMaterial.CHAINMAIL, builder().stackSize(1).maxDamage(165))); public static final Item CHAINMAIL_CHESTPLATE = register(new ArmorItem("chainmail_chestplate", ArmorMaterial.CHAINMAIL, builder().stackSize(1).maxDamage(240))); public static final Item CHAINMAIL_LEGGINGS = register(new ArmorItem("chainmail_leggings", ArmorMaterial.CHAINMAIL, builder().stackSize(1).maxDamage(225))); @@ -1165,7 +1165,7 @@ public final class Items { public static final Item IRON_HORSE_ARMOR = register(new ArmorItem("iron_horse_armor", ArmorMaterial.IRON, builder().stackSize(1))); public static final Item GOLDEN_HORSE_ARMOR = register(new ArmorItem("golden_horse_armor", ArmorMaterial.GOLD, builder().stackSize(1))); public static final Item DIAMOND_HORSE_ARMOR = register(new ArmorItem("diamond_horse_armor", ArmorMaterial.DIAMOND, builder().stackSize(1))); - public static final Item LEATHER_HORSE_ARMOR = register(new ArmorItem("leather_horse_armor", ArmorMaterial.LEATHER, builder().stackSize(1))); + public static final Item LEATHER_HORSE_ARMOR = register(new DyeableArmorItem("leather_horse_armor", ArmorMaterial.LEATHER, builder().stackSize(1))); public static final Item LEAD = register(new Item("lead", builder())); public static final Item NAME_TAG = register(new Item("name_tag", builder())); public static final Item COMMAND_BLOCK_MINECART = register(new Item("command_block_minecart", builder().stackSize(1))); @@ -1240,7 +1240,7 @@ public final class Items { public static final Item GUSTER_BANNER_PATTERN = register(new Item("guster_banner_pattern", builder().stackSize(1))); public static final Item GOAT_HORN = register(new GoatHornItem("goat_horn", builder().stackSize(1))); public static final Item COMPOSTER = register(new BlockItem("composter", builder())); - public static final Item BARREL = register(new ChestItem("barrel", builder())); + public static final Item BARREL = register(new BlockItem("barrel", builder())); public static final Item SMOKER = register(new BlockItem("smoker", builder())); public static final Item BLAST_FURNACE = register(new BlockItem("blast_furnace", builder())); public static final Item CARTOGRAPHY_TABLE = register(new BlockItem("cartography_table", builder())); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ChestItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ChestItem.java deleted file mode 100644 index 09718ba66..000000000 --- a/core/src/main/java/org/geysermc/geyser/item/type/ChestItem.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2019-2023 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.item.type; - -import org.checkerframework.checker.nullness.qual.NonNull; -import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.translator.item.BedrockItemBuilder; -import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; - -@Deprecated -public class ChestItem extends BlockItem { - - public ChestItem(String javaIdentifier, Builder builder) { - super(javaIdentifier, builder); - } - - @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { - super.translateComponentsToBedrock(session, components, builder); - } -} diff --git a/core/src/main/java/org/geysermc/geyser/item/type/DyeableArmorItem.java b/core/src/main/java/org/geysermc/geyser/item/type/DyeableArmorItem.java index d4bf838bd..b2dbb95e5 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/DyeableArmorItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/DyeableArmorItem.java @@ -27,12 +27,13 @@ package org.geysermc.geyser.item.type; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.item.ArmorMaterial; -import org.geysermc.geyser.item.DyeableLeatherItem; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DyedItemColor; -public class DyeableArmorItem extends ArmorItem implements DyeableLeatherItem { +public class DyeableArmorItem extends ArmorItem { public DyeableArmorItem(String javaIdentifier, ArmorMaterial material, Builder builder) { super(javaIdentifier, material, builder); } @@ -41,6 +42,11 @@ public class DyeableArmorItem extends ArmorItem implements DyeableLeatherItem { public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); - DyeableLeatherItem.translateComponentsToBedrock(components, builder); + // Note that this is handled as of 1.20.5 in the ItemColors class. + // But horse leather armor and body leather armor are now both armor items. So it works! + DyedItemColor dyedItemColor = components.get(DataComponentType.DYED_COLOR); + if (dyedItemColor != null) { + builder.putInt("customColor", dyedItemColor.getRgb()); + } } } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/DyeableHorseArmorItem.java b/core/src/main/java/org/geysermc/geyser/item/type/DyeableHorseArmorItem.java deleted file mode 100644 index b50a3b847..000000000 --- a/core/src/main/java/org/geysermc/geyser/item/type/DyeableHorseArmorItem.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2019-2023 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.item.type; - -import org.checkerframework.checker.nullness.qual.NonNull; -import org.geysermc.geyser.item.DyeableLeatherItem; -import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.translator.item.BedrockItemBuilder; -import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; - -public class DyeableHorseArmorItem extends Item implements DyeableLeatherItem { - public DyeableHorseArmorItem(String javaIdentifier, Builder builder) { - super(javaIdentifier, builder); - } - - @Override - public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { - super.translateComponentsToBedrock(session, components, builder); - - DyeableLeatherItem.translateComponentsToBedrock(components, builder); - } -} diff --git a/core/src/main/java/org/geysermc/geyser/item/type/FlowerItem.java b/core/src/main/java/org/geysermc/geyser/item/type/FlowerItem.java deleted file mode 100644 index c65eec1d2..000000000 --- a/core/src/main/java/org/geysermc/geyser/item/type/FlowerItem.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2019-2023 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.item.type; - -// If blocks are implemented, then this class is not needed. -public class FlowerItem extends BlockItem { - public FlowerItem(String javaIdentifier, Builder builder) { - super(javaIdentifier, builder); - } -} diff --git a/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java index 629192e01..11e092b57 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java @@ -71,7 +71,7 @@ public final class ItemTranslator { /** * The order of these slots is their display order on Java Edition clients */ - private static final String[] ALL_SLOTS = new String[]{"mainhand", "offhand", "feet", "legs", "chest", "head"}; + private static final ItemAttributeModifiers.EquipmentSlotGroup[] ALL_SLOTS = ItemAttributeModifiers.EquipmentSlotGroup.values(); private static final DecimalFormat ATTRIBUTE_FORMAT = new DecimalFormat("0.#####"); private ItemTranslator() { @@ -128,7 +128,7 @@ public final class ItemTranslator { .build(); } - private static ItemData.@NonNull Builder translateToBedrock(GeyserSession session, Item javaItem, ItemMapping bedrockItem, int count, DataComponents components) { + private static ItemData.@NonNull Builder translateToBedrock(GeyserSession session, Item javaItem, ItemMapping bedrockItem, int count, @Nullable DataComponents components) { BedrockItemBuilder nbtBuilder = new BedrockItemBuilder(); if (components != null) { @@ -208,8 +208,8 @@ public final class ItemTranslator { ItemAttributeModifiers.EquipmentSlotGroup slotGroup = entry.getSlot(); if (slotGroup == ItemAttributeModifiers.EquipmentSlotGroup.ANY) { // modifier applies to all slots implicitly - for (String slot : ALL_SLOTS) { // TODO SOMEONE LOOK HERE PLZ - //slotsToModifiers.computeIfAbsent(slot, s -> new ArrayList<>()).add(loreEntry); + for (var slot : ALL_SLOTS) { + slotsToModifiers.computeIfAbsent(slot, s -> new ArrayList<>()).add(loreEntry); } } else { // modifier applies to only the specified slot @@ -218,7 +218,7 @@ public final class ItemTranslator { } // iterate through the small array, not the map, so that ordering matches Java Edition - for (String slot : ALL_SLOTS) { + for (var slot : ALL_SLOTS) { List modifierStrings = slotsToModifiers.get(slot); if (modifierStrings == null || modifierStrings.isEmpty()) { continue; @@ -275,10 +275,10 @@ public final class ItemTranslator { return MessageTranslator.convertMessage(attributeComponent, language); } - private static void addAdvancedTooltips(DataComponents components, BedrockItemBuilder builder, Item item, String language) { + private static void addAdvancedTooltips(@Nullable DataComponents components, BedrockItemBuilder builder, Item item, String language) { int maxDurability = item.maxDamage(); - if (maxDurability != 0) { + if (maxDurability != 0 && components != null) { Integer durabilityComponent = components.get(DataComponentType.DAMAGE); if (durabilityComponent != null) { int durability = maxDurability - durabilityComponent; @@ -300,7 +300,7 @@ public final class ItemTranslator { Component component = Component.text() .resetStyle() .color(NamedTextColor.DARK_GRAY) - .append(Component.translatable("item.nbt_tags", // TODO + .append(Component.translatable("item.components", Component.text(components.getDataComponents().size()))) .build(); builder.getOrCreateLore().add(MessageTranslator.convertMessage(component, language)); From e97bbcc483f0e2ad6787e89ff03366eef2dff2ab Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Sun, 28 Apr 2024 02:10:20 -0400 Subject: [PATCH 303/344] Potion effect colors --- .../geyser/entity/EntityDefinitions.java | 3 +- .../geyser/entity/type/LivingEntity.java | 35 +++++++++++++++++++ gradle/libs.versions.toml | 2 +- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java index 4063a675c..fd0673062 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java +++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java @@ -454,8 +454,7 @@ public final class EntityDefinitions { EntityDefinition livingEntityBase = EntityDefinition.inherited(LivingEntity::new, entityBase) .addTranslator(MetadataType.BYTE, LivingEntity::setLivingEntityFlags) .addTranslator(MetadataType.FLOAT, LivingEntity::setHealth) - .addTranslator(MetadataType.INT, - (livingEntity, entityMetadata) -> livingEntity.getDirtyMetadata().put(EntityDataTypes.EFFECT_COLOR, entityMetadata.getValue())) + .addTranslator(MetadataType.PARTICLES, LivingEntity::setParticles) .addTranslator(MetadataType.BOOLEAN, (livingEntity, entityMetadata) -> livingEntity.getDirtyMetadata().put(EntityDataTypes.EFFECT_AMBIENCE, (byte) (((BooleanEntityMetadata) entityMetadata).getPrimitiveValue() ? 1 : 0))) .addTranslator(null) // Arrow count diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java index 401135bbf..58a3bf8e7 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java @@ -55,9 +55,13 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.FloatEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ObjectEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.level.particle.EntityEffectParticleData; +import org.geysermc.mcprotocollib.protocol.data.game.level.particle.Particle; +import org.geysermc.mcprotocollib.protocol.data.game.level.particle.ParticleType; import java.util.*; @@ -152,6 +156,37 @@ public class LivingEntity extends Entity { session.sendUpstreamPacket(attributesPacket); } + // TODO: support all particle types + public void setParticles(ObjectEntityMetadata> entityMetadata) { + List particles = entityMetadata.getValue(); + float r = 0f; + float g = 0f; + float b = 0f; + + int count = 0; + for (Particle particle : particles) { + if (particle.getType() != ParticleType.ENTITY_EFFECT) { + continue; + } + + int color = ((EntityEffectParticleData) particle.getData()).getColor(); + r += ((color >> 16) & 0xFF) / 255f; + g += ((color >> 8) & 0xFF) / 255f; + b += ((color) & 0xFF) / 255f; + count++; + } + + int result = 0; + if (count > 0) { + r = r / count * 255f; + g = g / count * 255f; + b = b / count * 255f; + result = (int) r << 16 | (int) g << 8 | (int) b; + } + + dirtyMetadata.put(EntityDataTypes.EFFECT_COLOR, result); + } + public @Nullable Vector3i setBedPosition(EntityMetadata, ?> entityMetadata) { Optional optionalPos = entityMetadata.getValue(); if (optionalPos.isPresent()) { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f8f979539..7c16b883b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ protocol-connection = "3.0.0.Beta1-20240411.165033-128" raknet = "1.0.0.CR3-20240416.144209-1" blockstateupdater="1.20.80-20240411.142413-1" mcauthlib = "d9d773e" -mcprotocollib = "98410a1" # Revert from jitpack after release +mcprotocollib = "400f1b4" # Revert from jitpack after release adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" From 9cb9a1450e6740df5abef30ff4261a0f75b8c32d Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Sun, 28 Apr 2024 07:43:33 -0700 Subject: [PATCH 304/344] Don't use tee to write metadata.json to downloads API (#4612) --- .github/workflows/build.yml | 7 ++++--- .github/workflows/preview.yml | 6 ++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 284fa265a..7ec013dc2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -136,14 +136,15 @@ jobs: run: | cat metadata.json echo + mv metadata.json metadata.json.tmp version=$(cat gradle.properties | grep -o "version=[0-9\\.]*" | cut -d"=" -f2) - cat metadata.json | jq --arg project "${PROJECT}" --arg version "${version}" ' + jq --arg project "${PROJECT}" --arg version "${version}" ' . | .changes |= map({"commit", "summary", "message"}) | .downloads |= map_values({"name", "sha256"}) | {$project, "repo", $version, "number": .build, "changes", "downloads"} - ' | tee metadata.json - echo + ' metadata.json.tmp > metadata.json + cat metadata.json - name: Publish to Downloads API if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} shell: bash diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index 13712d5ef..1268f0674 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -69,11 +69,13 @@ jobs: run: | cat metadata.json echo - cat metadata.json | jq --arg project "${PROJECT}" --arg version "${VERSION}" --arg number "${BUILD}" ' + mv metadata.json metadata.json.tmp + jq --arg project "${PROJECT}" --arg version "${VERSION}" --arg number "${BUILD}" ' . | .downloads |= map_values({"name", "sha256"}) | {$project, "repo", $version, "number": $number | tonumber, "changes": [], "downloads"} - ' | tee metadata.json + ' metadata.json.tmp > metadata.json + cat metadata.json - name: Publish to Downloads API if: success() shell: bash From 420f67752cae958be277bd0d9374b6c019d97ae2 Mon Sep 17 00:00:00 2001 From: basaigh <53559772+basaigh@users.noreply.github.com> Date: Sun, 28 Apr 2024 18:54:34 +0100 Subject: [PATCH 305/344] Fix suspicious stew NPEs --- .../java/org/geysermc/geyser/registry/type/ItemMappings.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 f3cfa3f0f..94c863660 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 @@ -148,9 +148,10 @@ public class ItemMappings implements DefinitionRegistry { } } else { if (!(mapping.getBedrockData() == data.getDamage() || - // Make exceptions for potions, tipped arrows, firework stars, and goat horns, whose damage values can vary + // Make exceptions for potions, tipped arrows, firework stars, goat horns, and suspicious stews, whose damage values can vary (mapping.getJavaItem() instanceof PotionItem || mapping.getJavaItem() == Items.ARROW - || mapping.getJavaItem() == Items.FIREWORK_STAR || mapping.getJavaItem() == Items.GOAT_HORN))) { + || mapping.getJavaItem() == Items.FIREWORK_STAR || mapping.getJavaItem() == Items.GOAT_HORN + || mapping.getJavaItem() == Items.SUSPICIOUS_STEW))) { continue; } } From 9b1e45007aeca1c64000d26da8dbf316d2e887ab Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Sun, 28 Apr 2024 23:41:13 +0200 Subject: [PATCH 306/344] Fix injectors, should work with Spigot/Paper 1.20.5 now --- .../org/geysermc/geyser/platform/mod/GeyserModInjector.java | 5 ++++- .../geyser/platform/spigot/GeyserSpigotInjector.java | 5 ++++- .../java/entity/player/JavaCookieRequestTranslator.java | 1 + .../java/entity/player/JavaStoreCookieTranslator.java | 1 + .../java/entity/player/JavaTransferPacketTranslator.java | 1 + 5 files changed, 11 insertions(+), 2 deletions(-) diff --git a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModInjector.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModInjector.java index 06496293f..624eccb3f 100644 --- a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModInjector.java +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModInjector.java @@ -93,8 +93,11 @@ public class GeyserModInjector extends GeyserInjector { protected void initChannel(@NonNull Channel ch) throws Exception { initChannel.invoke(childHandler, ch); + int index = ch.pipeline().names().indexOf("encoder"); + String baseName = index != -1 ? "encoder" : "outbound_config"; + if (bootstrap.getGeyserConfig().isDisableCompression()) { - ch.pipeline().addAfter("encoder", "geyser-compression-disabler", new GeyserModCompressionDisabler()); + ch.pipeline().addAfter(baseName, "geyser-compression-disabler", new GeyserModCompressionDisabler()); } } }) diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java index 6aa5d563f..6d22a77ae 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java @@ -119,8 +119,11 @@ public class GeyserSpigotInjector extends GeyserInjector { protected void initChannel(@NonNull Channel ch) throws Exception { initChannel.invoke(childHandler, ch); + int index = ch.pipeline().names().indexOf("encoder"); + String baseName = index != -1 ? "encoder" : "outbound_config"; + if (bootstrap.getGeyserConfig().isDisableCompression() && GeyserSpigotCompressionDisabler.ENABLED) { - ch.pipeline().addAfter("encoder", "geyser-compression-disabler", new GeyserSpigotCompressionDisabler()); + ch.pipeline().addAfter(baseName, "geyser-compression-disabler", new GeyserSpigotCompressionDisabler()); } } }) diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaCookieRequestTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaCookieRequestTranslator.java index 5266ebabd..33bfa7be8 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaCookieRequestTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaCookieRequestTranslator.java @@ -33,6 +33,7 @@ import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.Serverbound @Translator(packet = ClientboundCookieRequestPacket.class) public class JavaCookieRequestTranslator extends PacketTranslator { + @Override public void translate(GeyserSession session, ClientboundCookieRequestPacket packet) { ServerboundCookieResponsePacket responsePacket = new ServerboundCookieResponsePacket( diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaStoreCookieTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaStoreCookieTranslator.java index 19237b646..342618ff8 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaStoreCookieTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaStoreCookieTranslator.java @@ -32,6 +32,7 @@ import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.Clientbound @Translator(packet = ClientboundStoreCookiePacket.class) public class JavaStoreCookieTranslator extends PacketTranslator { + @Override public void translate(GeyserSession session, ClientboundStoreCookiePacket packet) { session.getCookies().put(packet.getKey(), packet.getPayload()); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaTransferPacketTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaTransferPacketTranslator.java index 86fd70677..ad793f934 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaTransferPacketTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaTransferPacketTranslator.java @@ -35,6 +35,7 @@ import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.Clientbound @Translator(packet = ClientboundTransferPacket.class) public class JavaTransferPacketTranslator extends PacketTranslator { + @Override public void translate(GeyserSession session, ClientboundTransferPacket packet) { ServerTransferEvent event = new ServerTransferEvent( From 82123aecf121b4fe688d6b166500821ecd036876 Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Sun, 28 Apr 2024 23:52:23 +0200 Subject: [PATCH 307/344] Fix: Modded platform injector not being used --- .../geysermc/geyser/platform/mod/GeyserModBootstrap.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModBootstrap.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModBootstrap.java index db966ec1a..9622736de 100644 --- a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModBootstrap.java +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModBootstrap.java @@ -58,6 +58,7 @@ import org.geysermc.geyser.util.FileUtils; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.net.SocketAddress; import java.nio.file.Path; import java.util.Map; import java.util.UUID; @@ -240,6 +241,11 @@ public abstract class GeyserModBootstrap implements GeyserBootstrap { return ip != null ? ip : ""; // See issue #3812 } + @Override + public SocketAddress getSocketAddress() { + return this.geyserInjector.getServerSocketAddress(); + } + @Override public int getServerPort() { return ((GeyserServerPortGetter) server).geyser$getServerPort(); From e8c1c2218f99c6abbaa981d71fd360cba7b9f2c7 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Mon, 29 Apr 2024 00:35:44 -0400 Subject: [PATCH 308/344] Fix banners on shields --- .../geysermc/geyser/item/type/BannerItem.java | 45 +++++++++++-------- .../geysermc/geyser/item/type/ShieldItem.java | 29 ++++++------ 2 files changed, 39 insertions(+), 35 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java index 232f340ea..9f5138323 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java @@ -113,6 +113,31 @@ public class BannerItem extends BlockItem { return new NbtList<>(NbtType.COMPOUND, tagsList); } + /** + * Converts a Java item component for banners into Bedrock item NBT. + */ + static void convertBannerPattern(GeyserSession session, List patterns, BedrockItemBuilder builder) { + if (isOminous(session, patterns)) { + // Remove the current patterns and set the ominous banner type + builder.putInt("Type", 1); + } else { + List patternList = new ArrayList<>(patterns.size()); + for (BannerPatternLayer patternLayer : patterns) { + patternLayer.getPattern().ifId(holder -> { + BannerPattern bannerPattern = session.getRegistryCache().bannerPatterns().get(holder.id()); + if (bannerPattern != null) { + NbtMap tag = NbtMap.builder() + .putString("Pattern", bannerPattern.getBedrockIdentifier()) + .putInt("Color", 15 - patternLayer.getColorId()) + .build(); + patternList.add(tag); + } + }); + } + builder.putList("Patterns", NbtType.COMPOUND, patternList); + } + } + /** * Convert the Java edition banner pattern nbt to Bedrock edition, null if the pattern doesn't exist * @@ -166,25 +191,7 @@ public class BannerItem extends BlockItem { List patterns = components.get(DataComponentType.BANNER_PATTERNS); if (patterns != null) { - if (isOminous(session, patterns)) { - // Remove the current patterns and set the ominous banner type - builder.putInt("Type", 1); - } else { - List patternList = new ArrayList<>(patterns.size()); - for (BannerPatternLayer patternLayer : patterns) { - patternLayer.getPattern().ifId(holder -> { - BannerPattern bannerPattern = session.getRegistryCache().bannerPatterns().get(holder.id()); - if (bannerPattern != null) { - NbtMap tag = NbtMap.builder() - .putString("Pattern", bannerPattern.getBedrockIdentifier()) - .putInt("Color", 15 - patternLayer.getColorId()) - .build(); - patternList.add(tag); - } - }); - } - builder.putList("Patterns", NbtType.COMPOUND, patternList); - } + convertBannerPattern(session, patterns, builder); } } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ShieldItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ShieldItem.java index 001fa74b6..14d41a073 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ShieldItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ShieldItem.java @@ -29,8 +29,12 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.item.components.ToolTier; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.BannerPatternLayer; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; +import java.util.List; + public class ShieldItem extends Item { public ShieldItem(String javaIdentifier, Builder builder) { super(javaIdentifier, builder); @@ -40,22 +44,15 @@ public class ShieldItem extends Item { public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { super.translateComponentsToBedrock(session, components, builder); - // TODO figure out patterns first. -// if (tag.remove("BlockEntityTag") instanceof CompoundTag blockEntityTag) { -// if (blockEntityTag.get("Patterns") instanceof ListTag patterns) { -// for (Tag pattern : patterns) { -// if (((CompoundTag) pattern).get("Color") instanceof IntTag color) { -// color.setValue(15 - color.getValue()); -// } -// } -// // Bedrock looks for patterns at the root -// tag.put(patterns); -// } -// if (blockEntityTag.get("Base") instanceof IntTag base) { -// base.setValue(15 - base.getValue()); -// tag.put(base); -// } -// } + List patterns = components.get(DataComponentType.BANNER_PATTERNS); + if (patterns != null) { + BannerItem.convertBannerPattern(session, patterns, builder); + } + // Shield pattern backing color + Integer baseColor = components.get(DataComponentType.BASE_COLOR); + if (baseColor != null) { + builder.putInt("Base", 15 - baseColor); + } } @Override From 88ae447fc6ee9667494bfefb5cd258c00d4535fc Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Mon, 29 Apr 2024 00:47:52 -0400 Subject: [PATCH 309/344] Fix banner block entity base colors with no patterns --- .../level/block/entity/BlockEntityTranslator.java | 9 +++++++-- .../block/entity/SpawnerBlockEntityTranslator.java | 5 ++++- .../entity/StructureBlockBlockEntityTranslator.java | 6 +++++- .../java/level/JavaLevelChunkWithLightTranslator.java | 11 ++++------- 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BlockEntityTranslator.java index 45981377c..6df7781be 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BlockEntityTranslator.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.translator.level.block.entity; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.session.GeyserSession; @@ -40,9 +41,13 @@ public abstract class BlockEntityTranslator { public abstract void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState); - public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, NbtMap javaNbt, int blockState) { + public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, @Nullable NbtMap javaNbt, int blockState) { NbtMapBuilder tagBuilder = getConstantBedrockTag(type, x, y, z); - translateTag(session, tagBuilder, javaNbt, blockState); + if (javaNbt != null || this instanceof RequiresBlockState) { + // Always process tags if the block state is part of the tag. + // See: banner base colors. + translateTag(session, tagBuilder, javaNbt, blockState); + } return tagBuilder.build(); } diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SpawnerBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SpawnerBlockEntityTranslator.java index 05b763e6b..edf71d384 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SpawnerBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SpawnerBlockEntityTranslator.java @@ -40,7 +40,10 @@ import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType public class SpawnerBlockEntityTranslator extends BlockEntityTranslator { @Override - public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, NbtMap javaNbt, int blockState) { + public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, @Nullable NbtMap javaNbt, int blockState) { + if (javaNbt == null) { + return super.getBlockEntityTag(session, type, x, y, z, javaNbt, blockState); + } // Sending an empty EntityIdentifier to empty the spawner is ignored by the client, so we send a whole new spawner! // Fixes https://github.com/GeyserMC/Geyser/issues/4214 NbtMap spawnData = javaNbt.getCompound("SpawnData"); diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/StructureBlockBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/StructureBlockBlockEntityTranslator.java index aefd97dd5..4bb9c5676 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/StructureBlockBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/StructureBlockBlockEntityTranslator.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.translator.level.block.entity; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; @@ -39,7 +40,10 @@ import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType public class StructureBlockBlockEntityTranslator extends BlockEntityTranslator { @Override - public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, NbtMap javaNbt, int blockState) { + public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, @Nullable NbtMap javaNbt, int blockState) { + if (javaNbt == null) { + return super.getBlockEntityTag(session, type, x, y, z, javaNbt, blockState); + } // Sending a structure with size 0 doesn't clear the outline. Hence, we have to force it by replacing the block :/ int xStructureSize = javaNbt.getInt("sizeX"); int yStructureSize = javaNbt.getInt("sizeY"); 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 c3a399863..29db95e3f 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 @@ -412,13 +412,10 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator Date: Mon, 29 Apr 2024 01:03:18 -0400 Subject: [PATCH 310/344] Firework shapes --- .../org/geysermc/geyser/item/type/FireworkRocketItem.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java b/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java index 1265956da..bba13e753 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java @@ -92,10 +92,7 @@ public class FireworkRocketItem extends Item { static NbtMap translateExplosionToBedrock(Fireworks.FireworkExplosion explosion) { NbtMapBuilder newExplosionData = NbtMap.builder(); -// if (explosion.get("Type") != null) { -// newExplosionData.put(new ByteTag("FireworkType", MathUtils.getNbtByte(explosion.get("Type").getValue()))); -// } - //newExplosionData.putByte("FireworkType", explosion.get) //TODO??? + newExplosionData.putByte("FireworkType", (byte) explosion.getShapeId()); int[] oldColors = explosion.getColors(); byte[] colors = new byte[oldColors.length]; From 4ff746e48ab4562978fab9981df2ea1f7cc8a039 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Mon, 29 Apr 2024 04:20:24 -0400 Subject: [PATCH 311/344] Fix translateTag NPE --- .../level/block/entity/BannerBlockEntityTranslator.java | 3 ++- .../level/block/entity/BrushableBlockEntityTranslator.java | 7 ++++++- .../block/entity/JigsawBlockBlockEntityTranslator.java | 7 ++++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BannerBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BannerBlockEntityTranslator.java index c87d1a217..81f58214c 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BannerBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BannerBlockEntityTranslator.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.translator.level.block.entity; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; @@ -38,7 +39,7 @@ import java.util.List; @BlockEntity(type = BlockEntityType.BANNER) public class BannerBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState { @Override - public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) { + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, @Nullable NbtMap javaNbt, int blockState) { int bannerColor = BlockStateValues.getBannerColor(blockState); if (bannerColor != -1) { bedrockNbt.putInt("Base", 15 - bannerColor); diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BrushableBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BrushableBlockEntityTranslator.java index 4f9dfec46..b4012236b 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BrushableBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BrushableBlockEntityTranslator.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.translator.level.block.entity; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.item.Items; @@ -37,7 +38,11 @@ import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType public class BrushableBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState { @Override - public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) { + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, @Nullable NbtMap javaNbt, int blockState) { + if (javaNbt == null) { + return; + } + NbtMap itemTag = javaNbt.getCompound("item"); if (itemTag.isEmpty()) { return; diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/JigsawBlockBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/JigsawBlockBlockEntityTranslator.java index bd83e3d54..53f32682c 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/JigsawBlockBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/JigsawBlockBlockEntityTranslator.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.translator.level.block.entity; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.level.block.BlockStateValues; @@ -34,7 +35,11 @@ import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType @BlockEntity(type = BlockEntityType.JIGSAW) public class JigsawBlockBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState { @Override - public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) { + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, @Nullable NbtMap javaNbt, int blockState) { + if (javaNbt == null) { + return; + } + String joint = javaNbt.getString("joint", null); if (joint != null) { bedrockNbt.putString("joint", joint); From 8b7b8cdffdb7aba97ef817037859d1151f4b2665 Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Mon, 29 Apr 2024 16:08:14 +0200 Subject: [PATCH 312/344] Properly shutdown LocalSession's, ensure transferring works properly regardless if we're injected or not --- bootstrap/mod/fabric/build.gradle.kts | 2 -- .../platform/spigot/GeyserSpigotInjector.java | 2 +- .../geysermc/geyser/network/netty/LocalSession.java | 13 +++++++------ .../org/geysermc/geyser/session/GeyserSession.java | 4 ++-- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/bootstrap/mod/fabric/build.gradle.kts b/bootstrap/mod/fabric/build.gradle.kts index 53e4dfe53..cd513c1e4 100644 --- a/bootstrap/mod/fabric/build.gradle.kts +++ b/bootstrap/mod/fabric/build.gradle.kts @@ -49,9 +49,7 @@ application { relocate("org.cloudburstmc.netty") relocate("org.cloudburstmc.protocol") -relocate("com.github.steveice10.mc.protocol") relocate("com.github.steveice10.mc.auth") -relocate("com.github.steveice10.packetlib") tasks { remapJar { diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java index 6d22a77ae..5dcfbd0f8 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java @@ -178,7 +178,7 @@ public class GeyserSpigotInjector extends GeyserInjector { MinecraftProtocol protocol = new MinecraftProtocol(); LocalSession session = new LocalSession(bootstrap.getGeyserConfig().getRemote().address(), bootstrap.getGeyserConfig().getRemote().port(), this.serverSocketAddress, - InetAddress.getLoopbackAddress().getHostAddress(), protocol, protocol.createHelper(), false); + InetAddress.getLoopbackAddress().getHostAddress(), protocol, protocol.createHelper()); session.connect(); session.disconnect(""); } diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java b/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java index b5598d063..958e88288 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java @@ -30,6 +30,7 @@ import io.netty.buffer.ByteBufAllocator; import io.netty.channel.*; import io.netty.channel.unix.PreferredDirectByteBufAllocator; import io.netty.handler.codec.haproxy.*; +import io.netty.util.concurrent.DefaultThreadFactory; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.mcprotocollib.network.BuiltinFlags; import org.geysermc.mcprotocollib.network.codec.PacketCodecHelper; @@ -42,6 +43,7 @@ import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper; import java.net.Inet4Address; import java.net.InetSocketAddress; import java.net.SocketAddress; +import java.util.concurrent.TimeUnit; /** * Manages a Minecraft Java session over our LocalChannel implementations. @@ -54,24 +56,23 @@ public final class LocalSession extends TcpSession { private final String clientIp; private final PacketCodecHelper codecHelper; - private final boolean transferring; - - public LocalSession(String host, int port, SocketAddress targetAddress, String clientIp, PacketProtocol protocol, MinecraftCodecHelper codecHelper, boolean transferring) { + public LocalSession(String host, int port, SocketAddress targetAddress, String clientIp, PacketProtocol protocol, MinecraftCodecHelper codecHelper) { super(host, port, protocol); this.targetAddress = targetAddress; this.clientIp = clientIp; this.codecHelper = codecHelper; - this.transferring = transferring; } @Override - public void connect(boolean wait) { + public void connect(boolean wait, boolean transferring) { if (this.disconnected) { throw new IllegalStateException("Connection has already been disconnected."); } if (DEFAULT_EVENT_LOOP_GROUP == null) { - DEFAULT_EVENT_LOOP_GROUP = new DefaultEventLoopGroup(); + DEFAULT_EVENT_LOOP_GROUP = new DefaultEventLoopGroup(new DefaultThreadFactory(this.getClass(), true)); + Runtime.getRuntime().addShutdownHook(new Thread( + () -> DEFAULT_EVENT_LOOP_GROUP.shutdownGracefully(100, 500, TimeUnit.MILLISECONDS))); } try { diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 869999357..d10a20b3d 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -880,7 +880,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { // We're going to connect through the JVM and not through TCP downstream = new LocalSession(this.remoteServer.address(), this.remoteServer.port(), geyser.getBootstrap().getSocketAddress(), upstream.getAddress().getAddress().getHostAddress(), - this.protocol, this.protocol.createHelper(), loginEvent.transferring()); + this.protocol, this.protocol.createHelper()); this.downstream = new DownstreamSession(downstream); } else { downstream = new TcpClientSession(this.remoteServer.address(), this.remoteServer.port(), this.protocol); @@ -1070,7 +1070,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { setDaylightCycle(true); } - downstream.connect(false); + downstream.connect(false, loginEvent.transferring()); } public void disconnect(String reason) { From 5d3630cf236aa47eb4e494272764ea58a02857d6 Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Mon, 29 Apr 2024 23:19:18 +0200 Subject: [PATCH 313/344] ominous banners - this really isn't ideal --- .../platform/spigot/GeyserSpigotPlugin.java | 4 +-- .../geyser/inventory/item/BannerPattern.java | 16 +++++----- .../geysermc/geyser/item/type/BannerItem.java | 32 ++++++++++++++----- .../geyser/session/GeyserSession.java | 1 + .../geyser/session/cache/RegistryCache.java | 19 +++++++++-- 5 files changed, 52 insertions(+), 20 deletions(-) diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java index 1f14a2f65..1170ce678 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java @@ -244,8 +244,8 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { if (Boolean.parseBoolean(System.getProperty("Geyser.UseDirectAdapters", "true"))) { try { - String name = Bukkit.getServer().getClass().getPackage().getName(); - String nmsVersion = name.substring(name.lastIndexOf('.') + 1); + String version = Bukkit.getBukkitVersion().split("-")[0]; + String nmsVersion = "v" + version.replace(".", "_"); SpigotAdapters.registerWorldAdapter(nmsVersion); if (isViaVersion && isViaVersionNeeded()) { this.geyserWorldManager = new GeyserSpigotLegacyNativeWorldManager(this); diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/BannerPattern.java b/core/src/main/java/org/geysermc/geyser/inventory/item/BannerPattern.java index 442690d7d..ae225073a 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/item/BannerPattern.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/item/BannerPattern.java @@ -45,7 +45,7 @@ public enum BannerPattern { STRIPE_MIDDLE("ms"), STRIPE_DOWNRIGHT("drs"), STRIPE_DOWNLEFT("dls"), - SMALL_STRIPES("ss"), + STRIPE_SMALL("ss"), CROSS("cr"), STRAIGHT_CROSS("sc"), TRIANGLE_BOTTOM("bt"), @@ -53,15 +53,15 @@ public enum BannerPattern { TRIANGLES_BOTTOM("bts"), TRIANGLES_TOP("tts"), DIAGONAL_LEFT("ld"), - DIAGONAL_UP_RIGHT("rd"), - DIAGONAL_UP_LEFT("lud"), - DIAGONAL_RIGHT("rud"), - CIRCLE("mc"), - RHOMBUS("mr"), + DIAGONAL_RIGHT("rd"), + DIAGONAL_LEFT_MIRROR("lud"), + DIAGONAL_RIGHT_MIRROR("rud"), + CIRCLE_MIDDLE("mc"), + RHOMBUS_MIDDLE("mr"), HALF_VERTICAL("vh"), HALF_HORIZONTAL("hh"), - HALF_VERTICAL_RIGHT("vhr"), - HALF_HORIZONTAL_BOTTOM("hhb"), + HALF_VERTICAL_MIRROR("vhr"), + HALF_HORIZONTAL_MIRROR("hhb"), BORDER("bo"), CURLY_BORDER("cbo"), GRADIENT("gra"), diff --git a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java index 9f5138323..255e320a6 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java @@ -26,18 +26,26 @@ package org.geysermc.geyser.item.type; import it.unimi.dsi.fastutil.Pair; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.Style; +import net.kyori.adventure.text.format.TextColor; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtList; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtType; +import org.cloudburstmc.protocol.common.util.Int2ObjectBiMap; import org.geysermc.geyser.inventory.item.BannerPattern; import org.geysermc.geyser.inventory.item.DyeColor; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.text.GeyserLocale; +import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.translator.item.BedrockItemBuilder; +import org.geysermc.mcprotocollib.protocol.data.game.Holder; import org.geysermc.mcprotocollib.protocol.data.game.item.component.BannerPatternLayer; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.Unit; import java.util.ArrayList; import java.util.List; @@ -56,13 +64,13 @@ public class BannerItem extends BlockItem { static { // Construct what an ominous banner is supposed to look like OMINOUS_BANNER_PATTERN = List.of( - Pair.of(BannerPattern.RHOMBUS, DyeColor.CYAN), + Pair.of(BannerPattern.RHOMBUS_MIDDLE, DyeColor.CYAN), Pair.of(BannerPattern.STRIPE_BOTTOM, DyeColor.LIGHT_GRAY), Pair.of(BannerPattern.STRIPE_CENTER, DyeColor.GRAY), Pair.of(BannerPattern.BORDER, DyeColor.LIGHT_GRAY), Pair.of(BannerPattern.STRIPE_MIDDLE, DyeColor.BLACK), Pair.of(BannerPattern.HALF_HORIZONTAL, DyeColor.LIGHT_GRAY), - Pair.of(BannerPattern.CIRCLE, DyeColor.LIGHT_GRAY), + Pair.of(BannerPattern.CIRCLE_MIDDLE, DyeColor.LIGHT_GRAY), Pair.of(BannerPattern.BORDER, DyeColor.BLACK) ); @@ -171,14 +179,13 @@ public class BannerItem extends BlockItem { * @return The Java edition format pattern layer */ public static BannerPatternLayer getJavaBannerPattern(GeyserSession session, NbtMap pattern) { - return null; // TODO - /*Int2ObjectBiMap registry = session.getRegistryCache().bannerPatterns(); + Int2ObjectBiMap registry = session.getRegistryCache().bannerPatterns(); BannerPattern bannerPattern = BannerPattern.getByBedrockIdentifier(pattern.getString("Pattern")); DyeColor dyeColor = DyeColor.getById(15 - pattern.getInt("Color")); if (bannerPattern != null && dyeColor != null && registry.containsValue(bannerPattern)) { return new BannerPatternLayer(Holder.ofId(registry.get(bannerPattern)), dyeColor.ordinal()); } - return null;*/ + return null; } public BannerItem(String javaIdentifier, Builder builder) { @@ -196,13 +203,22 @@ public class BannerItem extends BlockItem { } @Override - public void translateNbtToJava(@NonNull NbtMap bedrockTag, @NonNull DataComponents components, @NonNull ItemMapping mapping) { // TODO + public void translateNbtToJava(@NonNull NbtMap bedrockTag, @NonNull DataComponents components, @NonNull ItemMapping mapping) { super.translateNbtToJava(bedrockTag, components, mapping); if (bedrockTag.getInt("Type") == 1) { // Ominous banner pattern - // TODO more registry stuff - //components.put(DataComponentType.BANNER_PATTERNS); + List patternLayers = new ArrayList<>(); + for (Pair pair : OMINOUS_BANNER_PATTERN) { + patternLayers.add(new BannerPatternLayer(Holder.ofId(pair.left().ordinal()), pair.right().ordinal())); + } + + components.put(DataComponentType.BANNER_PATTERNS, patternLayers); + components.put(DataComponentType.HIDE_ADDITIONAL_TOOLTIP, Unit.INSTANCE); + components.put(DataComponentType.ITEM_NAME, Component.text( + MinecraftLocale.getLocaleString("block.minecraft.ominous_banner", GeyserLocale.getDefaultLocale()) + ).style(Style.style(TextColor.color(16755200))) + ); } // Bedrock's creative inventory does not support other patterns as of 1.20.5 } diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index d10a20b3d..869917b4c 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -579,6 +579,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { private final GeyserEntityData entityData; + @Getter private MinecraftProtocol protocol; public GeyserSession(GeyserImpl geyser, BedrockServerSession bedrockServerSession, EventLoop eventLoop) { diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java index 7ad2afec7..22fc72cf4 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java @@ -34,6 +34,7 @@ import lombok.Getter; import lombok.experimental.Accessors; import org.cloudburstmc.protocol.bedrock.data.TrimMaterial; import org.cloudburstmc.protocol.bedrock.data.TrimPattern; +import org.cloudburstmc.protocol.common.util.Int2ObjectBiMap; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.entity.type.living.animal.tameable.WolfEntity; import org.geysermc.geyser.inventory.item.BannerPattern; @@ -70,7 +71,7 @@ public final class RegistryCache { register("trim_material", cache -> cache.trimMaterials, TrimRecipe::readTrimMaterial); register("trim_pattern", cache -> cache.trimPatterns, TrimRecipe::readTrimPattern); register("worldgen/biome", (cache, array) -> cache.biomeTranslations = array, BiomeTranslator::loadServerBiome); - register("banner_pattern", cache -> cache.bannerPatterns, ($, entry) -> BannerPattern.getByJavaIdentifier(entry.getId())); + registerBannerRegistry(($, entry) -> BannerPattern.getByJavaIdentifier(entry.getId())); register("wolf_variant", cache -> cache.wolfVariants, ($, entry) -> WolfEntity.WolfVariant.getByJavaIdentifier(entry.getId())); } @@ -89,7 +90,7 @@ public final class RegistryCache { private final Int2ObjectMap trimMaterials = new Int2ObjectOpenHashMap<>(); private final Int2ObjectMap trimPatterns = new Int2ObjectOpenHashMap<>(); - private final Int2ObjectMap bannerPatterns = new Int2ObjectOpenHashMap<>(); + private Int2ObjectBiMap bannerPatterns = new Int2ObjectBiMap<>(); private final Int2ObjectMap wolfVariants = new Int2ObjectOpenHashMap<>(); public RegistryCache(GeyserSession session) { @@ -108,6 +109,20 @@ public final class RegistryCache { } } + private static void registerBannerRegistry(BiFunction reader) { + REGISTRIES.put("minecraft:banner_pattern", ((registryCache, entries) -> { + // Clear each local cache every time a new registry entry is given to us + // (e.g. proxy server switches) + registryCache.bannerPatterns = new Int2ObjectBiMap<>(); + for (int i = 0; i < entries.size(); i++) { + RegistryEntry entry = entries.get(i); + // This is what Geyser wants to keep as a value for this registry. + T cacheEntry = reader.apply(registryCache.session, entry); + registryCache.bannerPatterns.put(i, (BannerPattern) cacheEntry); + } + })); + } + /** * @param registry the Java registry resource location, without the "minecraft:" prefix. * @param localCacheFunction which local field in RegistryCache are we caching entries for this registry? From 28d5db622bbe60f583d7727de147949173b3d093 Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Mon, 29 Apr 2024 23:41:14 +0200 Subject: [PATCH 314/344] revert bad change --- .../geyser/inventory/item/BannerPattern.java | 16 ++++++++-------- .../geysermc/geyser/item/type/BannerItem.java | 5 +++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/BannerPattern.java b/core/src/main/java/org/geysermc/geyser/inventory/item/BannerPattern.java index ae225073a..442690d7d 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/item/BannerPattern.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/item/BannerPattern.java @@ -45,7 +45,7 @@ public enum BannerPattern { STRIPE_MIDDLE("ms"), STRIPE_DOWNRIGHT("drs"), STRIPE_DOWNLEFT("dls"), - STRIPE_SMALL("ss"), + SMALL_STRIPES("ss"), CROSS("cr"), STRAIGHT_CROSS("sc"), TRIANGLE_BOTTOM("bt"), @@ -53,15 +53,15 @@ public enum BannerPattern { TRIANGLES_BOTTOM("bts"), TRIANGLES_TOP("tts"), DIAGONAL_LEFT("ld"), - DIAGONAL_RIGHT("rd"), - DIAGONAL_LEFT_MIRROR("lud"), - DIAGONAL_RIGHT_MIRROR("rud"), - CIRCLE_MIDDLE("mc"), - RHOMBUS_MIDDLE("mr"), + DIAGONAL_UP_RIGHT("rd"), + DIAGONAL_UP_LEFT("lud"), + DIAGONAL_RIGHT("rud"), + CIRCLE("mc"), + RHOMBUS("mr"), HALF_VERTICAL("vh"), HALF_HORIZONTAL("hh"), - HALF_VERTICAL_MIRROR("vhr"), - HALF_HORIZONTAL_MIRROR("hhb"), + HALF_VERTICAL_RIGHT("vhr"), + HALF_HORIZONTAL_BOTTOM("hhb"), BORDER("bo"), CURLY_BORDER("cbo"), GRADIENT("gra"), diff --git a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java index 255e320a6..2f2d09669 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java @@ -64,13 +64,13 @@ public class BannerItem extends BlockItem { static { // Construct what an ominous banner is supposed to look like OMINOUS_BANNER_PATTERN = List.of( - Pair.of(BannerPattern.RHOMBUS_MIDDLE, DyeColor.CYAN), + Pair.of(BannerPattern.RHOMBUS, DyeColor.CYAN), Pair.of(BannerPattern.STRIPE_BOTTOM, DyeColor.LIGHT_GRAY), Pair.of(BannerPattern.STRIPE_CENTER, DyeColor.GRAY), Pair.of(BannerPattern.BORDER, DyeColor.LIGHT_GRAY), Pair.of(BannerPattern.STRIPE_MIDDLE, DyeColor.BLACK), Pair.of(BannerPattern.HALF_HORIZONTAL, DyeColor.LIGHT_GRAY), - Pair.of(BannerPattern.CIRCLE_MIDDLE, DyeColor.LIGHT_GRAY), + Pair.of(BannerPattern.CIRCLE, DyeColor.LIGHT_GRAY), Pair.of(BannerPattern.BORDER, DyeColor.BLACK) ); @@ -211,6 +211,7 @@ public class BannerItem extends BlockItem { List patternLayers = new ArrayList<>(); for (Pair pair : OMINOUS_BANNER_PATTERN) { patternLayers.add(new BannerPatternLayer(Holder.ofId(pair.left().ordinal()), pair.right().ordinal())); + System.out.println("adding: " + pair.left().getJavaIdentifier() + " " + pair.right().name()); } components.put(DataComponentType.BANNER_PATTERNS, patternLayers); From c963503fef83d17fe0286e665142b474120e8ded Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Tue, 30 Apr 2024 00:33:49 -0400 Subject: [PATCH 315/344] Entity scale attribute is now applied --- .../geyser/entity/EntityDefinitions.java | 2 +- .../entity/attribute/GeyserAttributeType.java | 1 + .../geyser/entity/type/LivingEntity.java | 36 +++++++++++++++++++ .../entity/type/living/AgeableEntity.java | 5 ++- .../entity/type/living/ArmorStandEntity.java | 10 +++--- .../entity/type/living/SlimeEntity.java | 5 ++- .../type/living/monster/GiantEntity.java | 7 ++-- .../type/living/monster/PhantomEntity.java | 3 +- .../type/living/monster/PiglinEntity.java | 3 +- .../type/living/monster/ZoglinEntity.java | 3 +- .../type/living/monster/ZombieEntity.java | 3 +- .../org/geysermc/geyser/util/MathUtils.java | 11 ------ 12 files changed, 56 insertions(+), 33 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java index fd0673062..ed2cda9b9 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java +++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java @@ -673,7 +673,7 @@ public final class EntityDefinitions { SLIME = EntityDefinition.inherited(SlimeEntity::new, mobEntityBase) .type(EntityType.SLIME) .heightAndWidth(0.51f) - .addTranslator(MetadataType.INT, SlimeEntity::setScale) + .addTranslator(MetadataType.INT, SlimeEntity::setSlimeScale) .build(); MAGMA_CUBE = EntityDefinition.inherited(MagmaCubeEntity::new, SLIME) .type(EntityType.MAGMA_CUBE) diff --git a/core/src/main/java/org/geysermc/geyser/entity/attribute/GeyserAttributeType.java b/core/src/main/java/org/geysermc/geyser/entity/attribute/GeyserAttributeType.java index 88d493275..f19912a8c 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/attribute/GeyserAttributeType.java +++ b/core/src/main/java/org/geysermc/geyser/entity/attribute/GeyserAttributeType.java @@ -49,6 +49,7 @@ public enum GeyserAttributeType { ATTACK_KNOCKBACK("minecraft:generic.attack_knockback", null, 1.5f, Float.MAX_VALUE, 0f), ATTACK_SPEED("minecraft:generic.attack_speed", null, 0f, 1024f, 4f), MAX_HEALTH("minecraft:generic.max_health", null, 0f, 1024f, 20f), + SCALE("minecraft:generic.scale", null, 0.0625f, 16f, 1f), // Unused. Do we need this? // Bedrock Attributes ABSORPTION(null, "minecraft:absorption", 0f, 1024f, 0f), diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java index 58a3bf8e7..d27fa3cad 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java @@ -86,6 +86,19 @@ public class LivingEntity extends Entity { */ private boolean isMaxFrozenState = false; + /** + * The base scale entity data, without attributes applied. Used for such cases as baby variants. + */ + @Getter(AccessLevel.NONE) + @Setter(AccessLevel.NONE) + private float scale; + /** + * The scale sent through the Java attributes packet + */ + @Getter(AccessLevel.NONE) + @Setter(AccessLevel.NONE) + private float attributeScale; + public LivingEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); } @@ -122,6 +135,9 @@ public class LivingEntity extends Entity { @Override protected void initializeMetadata() { + // Initialize here so overriding classes don't have 0 values + this.scale = 1f; + this.attributeScale = 1f; super.initializeMetadata(); // Matches Bedrock behavior; is always set to this dirtyMetadata.put(EntityDataTypes.STRUCTURAL_INTEGRITY, 1); @@ -230,6 +246,21 @@ public class LivingEntity extends Entity { return freezingPercentage; } + protected void setScale(float scale) { + this.scale = scale; + applyScale(); + } + + private void setAttributeScale(float scale) { + this.attributeScale = scale; + applyScale(); + } + + private void applyScale() { + // Take any adjustments Bedrock requires, and compute it alongside the attribute's additional changes + this.dirtyMetadata.put(EntityDataTypes.SCALE, scale * attributeScale); + } + /** * @return a Bedrock health attribute constructed from the data sent from the server */ @@ -366,6 +397,11 @@ public class LivingEntity extends Entity { case GENERIC_FOLLOW_RANGE -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.FOLLOW_RANGE)); case GENERIC_KNOCKBACK_RESISTANCE -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.KNOCKBACK_RESISTANCE)); case GENERIC_JUMP_STRENGTH -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.HORSE_JUMP_STRENGTH)); + case GENERIC_SCALE -> { + // Attribute on Java, entity data on Bedrock + setAttributeScale((float) AttributeUtils.calculateValue(javaAttribute)); + updateBedrockMetadata(); + } } } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/AgeableEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/AgeableEntity.java index 5b1d682ce..8f84e051b 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/AgeableEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/AgeableEntity.java @@ -26,7 +26,6 @@ package org.geysermc.geyser.entity.type.living; import org.cloudburstmc.math.vector.Vector3f; -import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; @@ -44,12 +43,12 @@ public class AgeableEntity extends CreatureEntity { protected void initializeMetadata() { super.initializeMetadata(); // Required as of 1.19.3 Java - dirtyMetadata.put(EntityDataTypes.SCALE, getAdultSize()); + setScale(getAdultSize()); } public void setBaby(BooleanEntityMetadata entityMetadata) { boolean isBaby = entityMetadata.getPrimitiveValue(); - dirtyMetadata.put(EntityDataTypes.SCALE, isBaby ? getBabySize() : getAdultSize()); + setScale(isBaby ? getBabySize() : getAdultSize()); setFlag(EntityFlag.BABY, isBaby); setBoundingBoxHeight(definition.height() * (isBaby ? getBabySize() : getAdultSize())); diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java index fce51e741..d057f09c7 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java @@ -311,7 +311,7 @@ public class ArmorStandEntity extends LivingEntity { if (!isInvisible) { // The armor stand isn't invisible. We good. setFlag(EntityFlag.INVISIBLE, false); - dirtyMetadata.put(EntityDataTypes.SCALE, getScale()); + setScale(getScale()); updateOffsetRequirement(false); if (secondEntity != null) { @@ -327,7 +327,7 @@ public class ArmorStandEntity extends LivingEntity { if (!isNametagEmpty && (!helmet.equals(ItemData.AIR) || !chestplate.equals(ItemData.AIR) || !leggings.equals(ItemData.AIR) || !boots.equals(ItemData.AIR) || !hand.equals(ItemData.AIR) || !offhand.equals(ItemData.AIR))) { // Reset scale of the proper armor stand - this.dirtyMetadata.put(EntityDataTypes.SCALE, getScale()); + setScale(getScale()); // Set the proper armor stand to invisible to show armor setFlag(EntityFlag.INVISIBLE, true); // Update the position of the armor stand @@ -350,7 +350,7 @@ public class ArmorStandEntity extends LivingEntity { // Guarantee this copy is NOT invisible secondEntity.setFlag(EntityFlag.INVISIBLE, false); // Scale to 0 to show nametag - secondEntity.getDirtyMetadata().put(EntityDataTypes.SCALE, 0.0f); + secondEntity.setScale(0f); // No bounding box as we don't want to interact with this entity secondEntity.getDirtyMetadata().put(EntityDataTypes.WIDTH, 0.0f); secondEntity.getDirtyMetadata().put(EntityDataTypes.HEIGHT, 0.0f); @@ -360,7 +360,7 @@ public class ArmorStandEntity extends LivingEntity { } else if (isNametagEmpty) { // We can just make an invisible entity // Reset scale of the proper armor stand - dirtyMetadata.put(EntityDataTypes.SCALE, getScale()); + setScale(getScale()); // Set the proper armor stand to invisible to show armor setFlag(EntityFlag.INVISIBLE, true); // Update offset @@ -374,7 +374,7 @@ public class ArmorStandEntity extends LivingEntity { // Nametag is not empty and there is no armor // We don't need to make a new entity setFlag(EntityFlag.INVISIBLE, false); - dirtyMetadata.put(EntityDataTypes.SCALE, 0.0f); + setScale(0f); // As the above is applied, we need an offset updateOffsetRequirement(!isMarker); diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/SlimeEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/SlimeEntity.java index 50095fe3f..3be2db1db 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/SlimeEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/SlimeEntity.java @@ -26,7 +26,6 @@ package org.geysermc.geyser.entity.type.living; import org.cloudburstmc.math.vector.Vector3f; -import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; @@ -39,8 +38,8 @@ public class SlimeEntity extends MobEntity { super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); } - public void setScale(IntEntityMetadata entityMetadata) { - dirtyMetadata.put(EntityDataTypes.SCALE, 0.10f + entityMetadata.getPrimitiveValue()); + public void setSlimeScale(IntEntityMetadata entityMetadata) { + setScale(0.10f + entityMetadata.getPrimitiveValue()); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/GiantEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/GiantEntity.java index e98c8f120..6bef3ae3e 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/GiantEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/GiantEntity.java @@ -26,7 +26,6 @@ package org.geysermc.geyser.entity.type.living.monster; import org.cloudburstmc.math.vector.Vector3f; -import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; @@ -36,7 +35,11 @@ public class GiantEntity extends MonsterEntity { public GiantEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); + } - dirtyMetadata.put(EntityDataTypes.SCALE, 6f); + @Override + protected void initializeMetadata() { + super.initializeMetadata(); + setScale(6f); } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PhantomEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PhantomEntity.java index cb4b7a8cf..18b7f6ae1 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PhantomEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PhantomEntity.java @@ -26,7 +26,6 @@ package org.geysermc.geyser.entity.type.living.monster; import org.cloudburstmc.math.vector.Vector3f; -import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.type.living.FlyingEntity; import org.geysermc.geyser.session.GeyserSession; @@ -46,7 +45,7 @@ public class PhantomEntity extends FlyingEntity { setBoundingBoxWidth(boundsScale * definition.width()); setBoundingBoxHeight(boundsScale * definition.height()); - dirtyMetadata.put(EntityDataTypes.SCALE, modelScale); + setScale(modelScale); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java index 9c43ab23a..f0f01272f 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java @@ -27,7 +27,6 @@ package org.geysermc.geyser.entity.type.living.monster; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; -import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.inventory.GeyserItemStack; @@ -49,7 +48,7 @@ public class PiglinEntity extends BasePiglinEntity { public void setBaby(BooleanEntityMetadata entityMetadata) { boolean isBaby = entityMetadata.getPrimitiveValue(); - dirtyMetadata.put(EntityDataTypes.SCALE, isBaby? .55f : 1f); + setScale(isBaby? .55f : 1f); setFlag(EntityFlag.BABY, isBaby); updateMountOffset(); diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZoglinEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZoglinEntity.java index efbb7753c..7eb950e21 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZoglinEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZoglinEntity.java @@ -26,7 +26,6 @@ package org.geysermc.geyser.entity.type.living.monster; import org.cloudburstmc.math.vector.Vector3f; -import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; @@ -43,7 +42,7 @@ public class ZoglinEntity extends MonsterEntity { public void setBaby(BooleanEntityMetadata entityMetadata) { boolean isBaby = entityMetadata.getPrimitiveValue(); if (isBaby != getFlag(EntityFlag.BABY)) { - dirtyMetadata.put(EntityDataTypes.SCALE, isBaby ? .55f : 1f); + setScale(isBaby ? .55f : 1f); setFlag(EntityFlag.BABY, isBaby); updatePassengerOffsets(); diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieEntity.java index 11354fbf8..b8351089d 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieEntity.java @@ -26,7 +26,6 @@ package org.geysermc.geyser.entity.type.living.monster; import org.cloudburstmc.math.vector.Vector3f; -import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; @@ -43,7 +42,7 @@ public class ZombieEntity extends MonsterEntity { public void setZombieBaby(BooleanEntityMetadata entityMetadata) { boolean isBaby = entityMetadata.getPrimitiveValue(); - dirtyMetadata.put(EntityDataTypes.SCALE, isBaby ? .55f : 1.0f); + setScale(isBaby ? .55f : 1.0f); setFlag(EntityFlag.BABY, isBaby); updateMountOffset(); diff --git a/core/src/main/java/org/geysermc/geyser/util/MathUtils.java b/core/src/main/java/org/geysermc/geyser/util/MathUtils.java index 32f8b7ef5..08bed56f4 100644 --- a/core/src/main/java/org/geysermc/geyser/util/MathUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/MathUtils.java @@ -168,17 +168,6 @@ public class MathUtils { return value; } - /** - * Ensures the resulting object is a byte. Java Edition does not care whether a byte is encoded as an integer or not; - * it converts it into a byte anyway. - * - * @param value The value to convert - * @return The converted byte - */ - public static byte getNbtByte(Object value) { - return ((Number) value).byteValue(); - } - /** * Packs a chunk's X and Z coordinates into a single {@code long}. * From dacacc6df8ce009f74bca901196bc69c0cf7c5ca Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Tue, 30 Apr 2024 04:45:07 -0400 Subject: [PATCH 316/344] Anvil renaming --- .../org/geysermc/geyser/inventory/AnvilContainer.java | 8 ++++---- .../inventory/updater/AnvilInventoryUpdater.java | 3 +-- .../geyser/translator/text/MessageTranslator.java | 10 +++++++--- gradle/libs.versions.toml | 2 +- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/inventory/AnvilContainer.java b/core/src/main/java/org/geysermc/geyser/inventory/AnvilContainer.java index e6332bc41..88838d068 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/AnvilContainer.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/AnvilContainer.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.inventory; +import net.kyori.adventure.text.Component; import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundRenameItemPacket; import lombok.Getter; @@ -72,10 +73,9 @@ public class AnvilContainer extends Container { String correctRename; newName = rename; - // TODO 1.20.5 fix properly - this name is apparently nullable?? - String originalName = MessageTranslator.convertMessage(ItemUtils.getCustomName(getInput().getComponents())); + Component originalName = ItemUtils.getCustomName(getInput().getComponents()); - String plainOriginalName = MessageTranslator.convertToPlainTextLenient(originalName, session.locale()); + String plainOriginalName = MessageTranslator.convertToPlainText(originalName, session.locale()); String plainNewName = MessageTranslator.convertToPlainText(rename); if (!plainOriginalName.equals(plainNewName)) { // Strip out formatting since Java Edition does not allow it @@ -85,7 +85,7 @@ public class AnvilContainer extends Container { session.sendDownstreamGamePacket(renameItemPacket); } else { // Restore formatting for item since we're not renaming - correctRename = MessageTranslator.convertMessageLenient(originalName); + correctRename = MessageTranslator.convertMessage(originalName, session.locale()); // Java Edition sends the original custom name when not renaming, // if there isn't a custom name an empty string is sent ServerboundRenameItemPacket renameItemPacket = new ServerboundRenameItemPacket(plainOriginalName); diff --git a/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java b/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java index 1021a5fb9..42924435e 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java @@ -118,8 +118,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater { // Changing the item in the input slot resets the name field on Bedrock, but // does not result in a FilterTextPacket - // TODO test - String originalName = MessageTranslator.convertToPlainText(ItemUtils.getCustomName(input.getComponents())); + String originalName = MessageTranslator.convertToPlainText(ItemUtils.getCustomName(input.getComponents()), session.locale()); ServerboundRenameItemPacket renameItemPacket = new ServerboundRenameItemPacket(originalName); session.sendDownstreamGamePacket(renameItemPacket); diff --git a/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java index 3f1c902c7..884f05256 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java @@ -260,13 +260,17 @@ public class MessageTranslator { } /** - * Convert legacy format message to plain text + * Convert a Java message to plain text * * @param message Message to convert + * @param locale Locale to use for translation strings * @return The plain text of the message */ - public static String convertToPlainText(Component message) { - return PlainTextComponentSerializer.plainText().serialize(message); + public static String convertToPlainText(Component message, String locale) { + if (message == null) { + return ""; + } + return PlainTextComponentSerializer.plainText().serialize(RENDERER.render(message, locale)); } /** diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7c16b883b..ab607495a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ protocol-connection = "3.0.0.Beta1-20240411.165033-128" raknet = "1.0.0.CR3-20240416.144209-1" blockstateupdater="1.20.80-20240411.142413-1" mcauthlib = "d9d773e" -mcprotocollib = "400f1b4" # Revert from jitpack after release +mcprotocollib = "bc8526b" # Revert from jitpack after release adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" From 74d6a37261c4516eab154f5622204b619156f609 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Tue, 30 Apr 2024 05:13:00 -0400 Subject: [PATCH 317/344] Fix bug when adding enchantments in anvil --- .../geyser/inventory/updater/AnvilInventoryUpdater.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java b/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java index 42924435e..d6a0d922b 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java @@ -387,7 +387,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater { } return enchantments; } - return Object2IntMaps.emptyMap(); + return new Object2IntOpenHashMap<>(); } private boolean isEnchantedBook(GeyserItemStack itemStack) { From ff9965f5590c9c93bb1d01377de139f8ac1c490f Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Tue, 30 Apr 2024 05:49:22 -0400 Subject: [PATCH 318/344] Translate item repair cost component --- core/src/main/java/org/geysermc/geyser/item/type/Item.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/src/main/java/org/geysermc/geyser/item/type/Item.java b/core/src/main/java/org/geysermc/geyser/item/type/Item.java index 8fcb19ad5..cc49f3785 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/Item.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/Item.java @@ -146,6 +146,11 @@ public class Item { if (!enchantNbtList.isEmpty()) { builder.putList("ench", NbtType.COMPOUND, enchantNbtList); } + + Integer repairCost = components.get(DataComponentType.REPAIR_COST); + if (repairCost != null) { + builder.putInt("RepairCost", repairCost); + } } /** From dd745b901f7826a3ef85ab7a2f0ea4f6e575e9b2 Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Tue, 30 Apr 2024 20:48:10 +0200 Subject: [PATCH 319/344] move to paper-adapters --- bootstrap/spigot/build.gradle.kts | 9 +++++++ .../platform/spigot/GeyserSpigotPlugin.java | 24 ++++++++++++++----- .../GeyserSpigotLegacyNativeWorldManager.java | 4 ++-- .../GeyserSpigotNativeWorldManager.java | 14 +++++++---- gradle/libs.versions.toml | 3 ++- 5 files changed, 41 insertions(+), 13 deletions(-) diff --git a/bootstrap/spigot/build.gradle.kts b/bootstrap/spigot/build.gradle.kts index 1d135c33d..8143d96a1 100644 --- a/bootstrap/spigot/build.gradle.kts +++ b/bootstrap/spigot/build.gradle.kts @@ -7,6 +7,9 @@ dependencies { implementation(variantOf(libs.adapters.spigot) { classifier("all") // otherwise the unshaded jar is used without the shaded NMS implementations }) + implementation(variantOf(libs.adapters.paper) { + classifier("all") // otherwise the unshaded jar is used without the shaded NMS implementations + }) implementation(libs.commodore) @@ -34,6 +37,12 @@ application { } tasks.withType { + + // Prevents Paper 1.20.5+ from remapping Geyser + manifest { + attributes["paperweight-mappings-namespace"] = "mojang" + } + archiveBaseName.set("Geyser-Spigot") dependencies { diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java index 1170ce678..e33de5f9b 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java @@ -46,6 +46,7 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.Constants; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.adapters.paper.PaperAdapters; import org.geysermc.geyser.adapters.spigot.SpigotAdapters; import org.geysermc.geyser.api.command.Command; import org.geysermc.geyser.api.extension.Extension; @@ -244,16 +245,27 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { if (Boolean.parseBoolean(System.getProperty("Geyser.UseDirectAdapters", "true"))) { try { - String version = Bukkit.getBukkitVersion().split("-")[0]; - String nmsVersion = "v" + version.replace(".", "_"); - SpigotAdapters.registerWorldAdapter(nmsVersion); + boolean isPaper = false; + try { + String name = Bukkit.getServer().getClass().getPackage().getName(); + String nmsVersion = name.substring(name.lastIndexOf('.') + 1); + SpigotAdapters.registerWorldAdapter(nmsVersion); + geyserLogger.debug("Using spigot NMS adapter for nms version: " + nmsVersion); + } catch (Exception e) { // Likely running on Paper 1.20.5+ + //noinspection deprecation + int protocolVersion = Bukkit.getUnsafe().getProtocolVersion(); + PaperAdapters.registerClosestWorldAdapter(protocolVersion); + isPaper = true; + geyserLogger.debug("Using paper world adapter for protocol version: " + protocolVersion); + } + if (isViaVersion && isViaVersionNeeded()) { - this.geyserWorldManager = new GeyserSpigotLegacyNativeWorldManager(this); + this.geyserWorldManager = new GeyserSpigotLegacyNativeWorldManager(this, isPaper); } else { // No ViaVersion - this.geyserWorldManager = new GeyserSpigotNativeWorldManager(this); + this.geyserWorldManager = new GeyserSpigotNativeWorldManager(this, isPaper); } - geyserLogger.debug("Using NMS adapter: " + this.geyserWorldManager.getClass() + ", " + nmsVersion); + geyserLogger.debug("Using world manager of type: " + this.geyserWorldManager.getClass().getSimpleName()); } catch (Exception e) { if (geyserConfig.isDebugMode()) { geyserLogger.debug("Error while attempting to find NMS adapter. Most likely, this can be safely ignored. :)"); diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotLegacyNativeWorldManager.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotLegacyNativeWorldManager.java index 021db5ec1..5d226e19e 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotLegacyNativeWorldManager.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotLegacyNativeWorldManager.java @@ -46,8 +46,8 @@ public class GeyserSpigotLegacyNativeWorldManager extends GeyserSpigotNativeWorl private final Int2IntMap oldToNewBlockId; - public GeyserSpigotLegacyNativeWorldManager(GeyserSpigotPlugin plugin) { - super(plugin); + public GeyserSpigotLegacyNativeWorldManager(GeyserSpigotPlugin plugin, boolean isPaper) { + super(plugin, isPaper); IntList allBlockStates = adapter.getAllBlockStates(); oldToNewBlockId = new Int2IntOpenHashMap(allBlockStates.size()); ProtocolVersion serverVersion = plugin.getServerProtocolVersion(); diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotNativeWorldManager.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotNativeWorldManager.java index 00212663c..45e84d254 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotNativeWorldManager.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotNativeWorldManager.java @@ -26,20 +26,26 @@ package org.geysermc.geyser.platform.spigot.world.manager; import org.bukkit.Bukkit; +import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.geyser.adapters.WorldAdapter; +import org.geysermc.geyser.adapters.paper.PaperAdapters; import org.geysermc.geyser.adapters.spigot.SpigotAdapters; -import org.geysermc.geyser.adapters.spigot.SpigotWorldAdapter; import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.session.GeyserSession; public class GeyserSpigotNativeWorldManager extends GeyserSpigotWorldManager { - protected final SpigotWorldAdapter adapter; + protected final WorldAdapter adapter; - public GeyserSpigotNativeWorldManager(Plugin plugin) { + public GeyserSpigotNativeWorldManager(Plugin plugin, boolean isPaper) { super(plugin); - adapter = SpigotAdapters.getWorldAdapter(); + if (isPaper) { + adapter = PaperAdapters.getWorldAdapter(); + } else { + adapter = SpigotAdapters.getWorldAdapter(); + } } @Override diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7c16b883b..6a88f0b0f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -25,7 +25,7 @@ jline = "3.21.0" terminalconsoleappender = "1.2.0" folia = "1.19.4-R0.1-SNAPSHOT" viaversion = "4.9.2" -adapters = "1.11-SNAPSHOT" +adapters = "1.12-SNAPSHOT" commodore = "2.2" bungeecord = "a7c6ede" velocity = "3.1.1" @@ -100,6 +100,7 @@ fabric-permissions = { group = "me.lucko", name = "fabric-permissions-api", vers neoforge-minecraft = { group = "net.neoforged", name = "neoforge", version.ref = "neoforge-minecraft" } adapters-spigot = { group = "org.geysermc.geyser.adapters", name = "spigot-all", version.ref = "adapters" } +adapters-paper = { group = "org.geysermc.geyser.adapters", name = "paper-all", version.ref = "adapters" } bungeecord-proxy = { group = "com.github.SpigotMC.BungeeCord", name = "bungeecord-proxy", version.ref = "bungeecord" } checker-qual = { group = "org.checkerframework", name = "checker-qual", version.ref = "checkerframework" } commodore = { group = "me.lucko", name = "commodore", version.ref = "commodore" } From d99f49890100c5aa891d694a3c7619dc92520401 Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Tue, 30 Apr 2024 21:35:21 +0200 Subject: [PATCH 320/344] translate ominous banners --- .../geysermc/geyser/item/type/BannerItem.java | 16 ++++++++-------- .../geyser/session/cache/RegistryCache.java | 9 +++++++-- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java index 2f2d09669..2f5d96b5a 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java @@ -38,8 +38,6 @@ import org.geysermc.geyser.inventory.item.BannerPattern; import org.geysermc.geyser.inventory.item.DyeColor; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.text.GeyserLocale; -import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.mcprotocollib.protocol.data.game.Holder; import org.geysermc.mcprotocollib.protocol.data.game.item.component.BannerPatternLayer; @@ -61,6 +59,9 @@ public class BannerItem extends BlockItem { private static final List> OMINOUS_BANNER_PATTERN; private static final List OMINOUS_BANNER_PATTERN_BLOCK; + // TODO fix - we somehow need to be able to get the sessions banner pattern registry, which we don't have where we need this :/ + private static final int[] ominousBannerPattern = new int[] { 21, 29, 30, 1, 34, 15, 3, 1 }; + static { // Construct what an ominous banner is supposed to look like OMINOUS_BANNER_PATTERN = List.of( @@ -209,16 +210,15 @@ public class BannerItem extends BlockItem { if (bedrockTag.getInt("Type") == 1) { // Ominous banner pattern List patternLayers = new ArrayList<>(); - for (Pair pair : OMINOUS_BANNER_PATTERN) { - patternLayers.add(new BannerPatternLayer(Holder.ofId(pair.left().ordinal()), pair.right().ordinal())); - System.out.println("adding: " + pair.left().getJavaIdentifier() + " " + pair.right().name()); + for (int i = 0; i < ominousBannerPattern.length; i++) { + patternLayers.add(new BannerPatternLayer(Holder.ofId(ominousBannerPattern[i]), OMINOUS_BANNER_PATTERN.get(i).right().ordinal())); } components.put(DataComponentType.BANNER_PATTERNS, patternLayers); components.put(DataComponentType.HIDE_ADDITIONAL_TOOLTIP, Unit.INSTANCE); - components.put(DataComponentType.ITEM_NAME, Component.text( - MinecraftLocale.getLocaleString("block.minecraft.ominous_banner", GeyserLocale.getDefaultLocale()) - ).style(Style.style(TextColor.color(16755200))) + components.put(DataComponentType.ITEM_NAME, Component + .translatable("block.minecraft.ominous_banner") // thank god this works + .style(Style.style(TextColor.color(16755200))) ); } // Bedrock's creative inventory does not support other patterns as of 1.20.5 diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java index 22fc72cf4..4dfc603ee 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java @@ -113,12 +113,17 @@ public final class RegistryCache { REGISTRIES.put("minecraft:banner_pattern", ((registryCache, entries) -> { // Clear each local cache every time a new registry entry is given to us // (e.g. proxy server switches) - registryCache.bannerPatterns = new Int2ObjectBiMap<>(); + registryCache.bannerPatterns = new Int2ObjectBiMap<>(); // Cannot clear it, must re-create :( for (int i = 0; i < entries.size(); i++) { RegistryEntry entry = entries.get(i); // This is what Geyser wants to keep as a value for this registry. T cacheEntry = reader.apply(registryCache.session, entry); - registryCache.bannerPatterns.put(i, (BannerPattern) cacheEntry); + if (cacheEntry != null) { + registryCache.bannerPatterns.put(i, (BannerPattern) cacheEntry); + } else { + // TODO - seems to be possible with viaversion :/ + GeyserImpl.getInstance().getLogger().warning("Was not able to translate entry: "); + } } })); } From 4a0a694eb9c6789c19ee724d55a132c8668993d7 Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Tue, 30 Apr 2024 21:38:25 +0200 Subject: [PATCH 321/344] revert bad diff --- .../src/main/java/org/geysermc/geyser/session/GeyserSession.java | 1 - 1 file changed, 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 869917b4c..d10a20b3d 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -579,7 +579,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { private final GeyserEntityData entityData; - @Getter private MinecraftProtocol protocol; public GeyserSession(GeyserImpl geyser, BedrockServerSession bedrockServerSession, EventLoop eventLoop) { From 255835438d7392f466b84841d7aedb6cfc3146be Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Tue, 30 Apr 2024 21:59:38 +0200 Subject: [PATCH 322/344] viaversion 4.10.0 compat, indicate 1.20.6 support on modrinth --- .../world/manager/GeyserSpigotLegacyNativeWorldManager.java | 2 +- .../src/main/kotlin/geyser.modded-conventions.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotLegacyNativeWorldManager.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotLegacyNativeWorldManager.java index 5d226e19e..fe2dda053 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotLegacyNativeWorldManager.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotLegacyNativeWorldManager.java @@ -58,7 +58,7 @@ public class GeyserSpigotLegacyNativeWorldManager extends GeyserSpigotNativeWorl int newBlockId = oldBlockId; // protocolList should *not* be null; we checked for that before initializing this class for (int i = protocolList.size() - 1; i >= 0; i--) { - MappingData mappingData = protocolList.get(i).getProtocol().getMappingData(); + MappingData mappingData = protocolList.get(i).protocol().getMappingData(); if (mappingData != null) { newBlockId = mappingData.getNewBlockStateId(newBlockId); } diff --git a/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts b/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts index afea247a7..b75e9c5be 100644 --- a/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts @@ -134,6 +134,6 @@ modrinth { syncBodyFrom.set(rootProject.file("README.md").readText()) uploadFile.set(tasks.getByPath("remapModrinthJar")) - gameVersions.addAll("1.20.5") + gameVersions.addAll("1.20.5", "1.20.6") failSilently.set(true) } \ No newline at end of file From aff7d2cf35d5e8799b59fca67d781b31e8e19a96 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Tue, 30 Apr 2024 18:05:46 -0400 Subject: [PATCH 323/344] Fix potential NPE --- .../main/java/org/geysermc/geyser/inventory/AnvilContainer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/inventory/AnvilContainer.java b/core/src/main/java/org/geysermc/geyser/inventory/AnvilContainer.java index 88838d068..45a062468 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/AnvilContainer.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/AnvilContainer.java @@ -85,7 +85,7 @@ public class AnvilContainer extends Container { session.sendDownstreamGamePacket(renameItemPacket); } else { // Restore formatting for item since we're not renaming - correctRename = MessageTranslator.convertMessage(originalName, session.locale()); + correctRename = originalName != null ? MessageTranslator.convertMessage(originalName, session.locale()) : ""; // Java Edition sends the original custom name when not renaming, // if there isn't a custom name an empty string is sent ServerboundRenameItemPacket renameItemPacket = new ServerboundRenameItemPacket(plainOriginalName); From 59a2c0dc02abacd00fe3a72788cc9317c891557e Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Tue, 30 Apr 2024 18:35:52 -0400 Subject: [PATCH 324/344] Use item tags for all animal loved food --- .../geyser/entity/EntityDefinitions.java | 2 +- .../entity/type/living/TadpoleEntity.java | 4 +-- .../type/living/animal/AnimalEntity.java | 21 ++++++++-------- .../type/living/animal/ArmadilloEntity.java | 8 ++++++ .../type/living/animal/AxolotlEntity.java | 7 +++--- .../entity/type/living/animal/BeeEntity.java | 7 +++--- .../type/living/animal/ChickenEntity.java | 11 ++++---- .../entity/type/living/animal/CowEntity.java | 8 ++++++ .../entity/type/living/animal/FoxEntity.java | 7 +++--- .../entity/type/living/animal/FrogEntity.java | 9 ++++--- .../entity/type/living/animal/GoatEntity.java | 8 ++++++ .../type/living/animal/HoglinEntity.java | 9 ++++--- .../type/living/animal/MooshroomEntity.java | 2 +- .../type/living/animal/OcelotEntity.java | 9 ++++--- .../type/living/animal/PandaEntity.java | 8 +++--- .../entity/type/living/animal/PigEntity.java | 9 ++++--- .../type/living/animal/PolarBearEntity.java | 8 +++--- .../type/living/animal/RabbitEntity.java | 9 ++++--- .../type/living/animal/SheepEntity.java | 8 ++++++ .../type/living/animal/SnifferEntity.java | 7 +++--- .../type/living/animal/StriderEntity.java | 9 ++++--- .../type/living/animal/TurtleEntity.java | 9 ++++--- .../animal/horse/AbstractHorseEntity.java | 15 ++++------- .../type/living/animal/horse/CamelEntity.java | 8 +++--- .../type/living/animal/horse/LlamaEntity.java | 8 +++--- .../living/animal/tameable/CatEntity.java | 8 +++--- .../living/animal/tameable/ParrotEntity.java | 11 +++++--- .../animal/tameable/TameableEntity.java | 2 +- .../living/animal/tameable/WolfEntity.java | 7 +++--- .../geyser/item/type/FireworkRocketItem.java | 2 +- .../geyser/session/cache/tags/ItemTag.java | 25 +++++++++++++++++-- .../translator/item/ItemTranslator.java | 20 +++++++-------- 32 files changed, 174 insertions(+), 111 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java index ed2cda9b9..6cd5f3fc2 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java +++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java @@ -964,7 +964,7 @@ public final class EntityDefinitions { .build(); } - EntityDefinition tameableEntityBase = EntityDefinition.inherited(TameableEntity::new, ageableEntityBase) + EntityDefinition tameableEntityBase = EntityDefinition.inherited(null, ageableEntityBase) // No factory, is abstract .addTranslator(MetadataType.BYTE, TameableEntity::setTameableFlags) .addTranslator(MetadataType.OPTIONAL_UUID, TameableEntity::setOwner) .build(); diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/TadpoleEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/TadpoleEntity.java index 4fdaa1059..68cf763c3 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/TadpoleEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/TadpoleEntity.java @@ -29,8 +29,8 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.inventory.GeyserItemStack; -import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; @@ -62,6 +62,6 @@ public class TadpoleEntity extends AbstractFishEntity { } private boolean isFood(GeyserItemStack itemStack) { - return itemStack.asItem() == Items.SLIME_BALL; + return session.getTagCache().is(ItemTag.FROG_FOOD, itemStack); } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AnimalEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AnimalEntity.java index bf23a5418..2e627b461 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AnimalEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AnimalEntity.java @@ -26,38 +26,39 @@ package org.geysermc.geyser.entity.type.living.animal; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.type.living.AgeableEntity; import org.geysermc.geyser.inventory.GeyserItemStack; -import org.geysermc.geyser.item.Items; -import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; -public class AnimalEntity extends AgeableEntity { +public abstract class AnimalEntity extends AgeableEntity { public AnimalEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); } - public final boolean canEat(GeyserItemStack itemStack) { - return canEat(itemStack.asItem()); + protected final boolean canEat(GeyserItemStack itemStack) { + ItemTag tag = getFoodTag(); + if (tag == null) { + return false; + } + return session.getTagCache().is(tag, itemStack); } /** - * @return true if this is a valid item to breed with for this animal. + * @return the tag associated with this animal for eating food. Null for nothing or different behavior. */ - public boolean canEat(Item item) { - // This is what it defaults to. OK. - return item == Items.WHEAT; - } + protected abstract @Nullable ItemTag getFoodTag(); @NonNull @Override diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ArmadilloEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ArmadilloEntity.java index 51fe09383..968520bb6 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ArmadilloEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ArmadilloEntity.java @@ -25,9 +25,11 @@ package org.geysermc.geyser.entity.type.living.animal; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.ArmadilloState; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ObjectEntityMetadata; @@ -70,4 +72,10 @@ public class ArmadilloEntity extends AnimalEntity { }, 250, TimeUnit.MILLISECONDS); } } + + @Override + @Nullable + protected ItemTag getFoodTag() { + return ItemTag.ARMADILLO_FOOD; + } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java index 37cd5f1e6..a87b1dd5e 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java @@ -26,12 +26,12 @@ package org.geysermc.geyser.entity.type.living.animal; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.inventory.GeyserItemStack; -import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.util.EntityUtils; @@ -61,8 +61,9 @@ public class AxolotlEntity extends AnimalEntity { } @Override - public boolean canEat(Item item) { - return session.getTagCache().is(ItemTag.AXOLOTL_FOOD, item); + @Nullable + protected ItemTag getFoodTag() { + return ItemTag.AXOLOTL_FOOD; } @Override diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/BeeEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/BeeEntity.java index 28ebad473..4fcf0e178 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/BeeEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/BeeEntity.java @@ -25,13 +25,13 @@ package org.geysermc.geyser.entity.type.living.animal; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket; import org.geysermc.geyser.entity.EntityDefinition; -import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; @@ -68,7 +68,8 @@ public class BeeEntity extends AnimalEntity { } @Override - public boolean canEat(Item item) { - return session.getTagCache().is(ItemTag.FLOWERS, item); + @Nullable + protected ItemTag getFoodTag() { + return ItemTag.BEE_FOOD; } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ChickenEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ChickenEntity.java index 164fb1b6c..075a49923 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ChickenEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ChickenEntity.java @@ -25,24 +25,23 @@ package org.geysermc.geyser.entity.type.living.animal; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.geysermc.geyser.entity.EntityDefinition; -import org.geysermc.geyser.item.Items; -import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.ItemTag; -import java.util.Set; import java.util.UUID; public class ChickenEntity extends AnimalEntity { - private static final Set VALID_FOOD = Set.of(Items.WHEAT_SEEDS, Items.MELON_SEEDS, Items.PUMPKIN_SEEDS, Items.BEETROOT_SEEDS); public ChickenEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); } @Override - public boolean canEat(Item item) { - return VALID_FOOD.contains(item); + @Nullable + protected ItemTag getFoodTag() { + return ItemTag.CHICKEN_FOOD; } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/CowEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/CowEntity.java index d542cb46f..64e7de193 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/CowEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/CowEntity.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.entity.type.living.animal; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; @@ -33,6 +34,7 @@ import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; @@ -64,4 +66,10 @@ public class CowEntity extends AnimalEntity { session.playSoundEvent(SoundEvent.MILK, position); return InteractionResult.SUCCESS; } + + @Override + @Nullable + protected ItemTag getFoodTag() { + return ItemTag.COW_FOOD; + } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FoxEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FoxEntity.java index 18e346b98..e20031baa 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FoxEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FoxEntity.java @@ -25,11 +25,11 @@ package org.geysermc.geyser.entity.type.living.animal; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; -import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; @@ -56,7 +56,8 @@ public class FoxEntity extends AnimalEntity { } @Override - public boolean canEat(Item item) { - return session.getTagCache().is(ItemTag.FOX_FOOD, item); + @Nullable + protected ItemTag getFoodTag() { + return ItemTag.FOX_FOOD; } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FrogEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FrogEntity.java index ed21a9609..120bfcdd4 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FrogEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FrogEntity.java @@ -25,14 +25,14 @@ package org.geysermc.geyser.entity.type.living.animal; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.type.Entity; -import org.geysermc.geyser.item.Items; -import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ObjectEntityMetadata; @@ -76,7 +76,8 @@ public class FrogEntity extends AnimalEntity { } @Override - public boolean canEat(Item item) { - return item == Items.SLIME_BALL; + @Nullable + protected ItemTag getFoodTag() { + return ItemTag.FROG_FOOD; } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/GoatEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/GoatEntity.java index 7cbbd4433..4e919b81c 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/GoatEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/GoatEntity.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.entity.type.living.animal; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; @@ -34,6 +35,7 @@ import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; @@ -94,4 +96,10 @@ public class GoatEntity extends AnimalEntity { private void setHornCount() { dirtyMetadata.put(EntityDataTypes.GOAT_HORN_COUNT, (hasLeftHorn ? 1 : 0) + (hasRightHorn ? 1 : 0)); } + + @Override + @Nullable + protected ItemTag getFoodTag() { + return ItemTag.GOAT_FOOD; + } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/HoglinEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/HoglinEntity.java index 29d1839c7..46cafad02 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/HoglinEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/HoglinEntity.java @@ -25,12 +25,12 @@ package org.geysermc.geyser.entity.type.living.animal; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; -import org.geysermc.geyser.item.Items; -import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import java.util.UUID; @@ -54,8 +54,9 @@ public class HoglinEntity extends AnimalEntity { } @Override - public boolean canEat(Item item) { - return item == Items.CRIMSON_FUNGUS; + @Nullable + protected ItemTag getFoodTag() { + return ItemTag.HOGLIN_FOOD; } @Override diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/MooshroomEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/MooshroomEntity.java index 55c3c406f..2c9040b53 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/MooshroomEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/MooshroomEntity.java @@ -40,7 +40,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; -public class MooshroomEntity extends AnimalEntity { +public class MooshroomEntity extends CowEntity { private boolean isBrown = false; public MooshroomEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/OcelotEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/OcelotEntity.java index 8a3dd6c72..9d6d33227 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/OcelotEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/OcelotEntity.java @@ -26,13 +26,13 @@ package org.geysermc.geyser.entity.type.living.animal; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.inventory.GeyserItemStack; -import org.geysermc.geyser.item.Items; -import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; @@ -46,8 +46,9 @@ public class OcelotEntity extends AnimalEntity { } @Override - public boolean canEat(Item item) { - return item == Items.COD || item == Items.SALMON; + @Nullable + protected ItemTag getFoodTag() { + return ItemTag.OCELOT_FOOD; } @NonNull diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PandaEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PandaEntity.java index df72fdc63..595e79e32 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PandaEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PandaEntity.java @@ -34,9 +34,8 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.inventory.GeyserItemStack; -import org.geysermc.geyser.item.Items; -import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; @@ -89,8 +88,9 @@ public class PandaEntity extends AnimalEntity { } @Override - public boolean canEat(Item item) { - return item == Items.BAMBOO; + @Nullable + protected ItemTag getFoodTag() { + return ItemTag.PANDA_FOOD; } @NonNull diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PigEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PigEntity.java index 4dbf3064a..446e3e109 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PigEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PigEntity.java @@ -26,13 +26,13 @@ package org.geysermc.geyser.entity.type.living.animal; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.inventory.GeyserItemStack; -import org.geysermc.geyser.item.Items; -import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.util.EntityUtils; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; @@ -47,8 +47,9 @@ public class PigEntity extends AnimalEntity { } @Override - public boolean canEat(Item item) { - return item == Items.CARROT || item == Items.POTATO || item == Items.BEETROOT; + @Nullable + protected ItemTag getFoodTag() { + return ItemTag.PIG_FOOD; } @NonNull diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PolarBearEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PolarBearEntity.java index 1d7777cdb..0e83615f7 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PolarBearEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PolarBearEntity.java @@ -25,10 +25,11 @@ package org.geysermc.geyser.entity.type.living.animal; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.geysermc.geyser.entity.EntityDefinition; -import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.ItemTag; import java.util.UUID; @@ -39,7 +40,8 @@ public class PolarBearEntity extends AnimalEntity { } @Override - public boolean canEat(Item item) { - return false; + @Nullable + protected ItemTag getFoodTag() { + return null; } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/RabbitEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/RabbitEntity.java index 09db7257b..0a108be73 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/RabbitEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/RabbitEntity.java @@ -25,13 +25,13 @@ package org.geysermc.geyser.entity.type.living.animal; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; -import org.geysermc.geyser.item.Items; -import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; import java.util.UUID; @@ -67,7 +67,8 @@ public class RabbitEntity extends AnimalEntity { } @Override - public boolean canEat(Item item) { - return item == Items.DANDELION || item == Items.CARROT || item == Items.GOLDEN_CARROT; + @Nullable + protected ItemTag getFoodTag() { + return ItemTag.RABBIT_FOOD; } } \ No newline at end of file diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SheepEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SheepEntity.java index e87186bf6..155ddf00c 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SheepEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SheepEntity.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.entity.type.living.animal; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; @@ -34,6 +35,7 @@ import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.DyeItem; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; @@ -55,6 +57,12 @@ public class SheepEntity extends AnimalEntity { dirtyMetadata.put(EntityDataTypes.COLOR, (byte) color); } + @Override + @Nullable + protected ItemTag getFoodTag() { + return ItemTag.SHEEP_FOOD; + } + @NonNull @Override protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SnifferEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SnifferEntity.java index 35b2b4183..11fee5bbf 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SnifferEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SnifferEntity.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.entity.type.living.animal; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.LevelEvent; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; @@ -34,7 +35,6 @@ import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEventPacket; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.type.Tickable; -import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose; @@ -72,8 +72,9 @@ public class SnifferEntity extends AnimalEntity implements Tickable { } @Override - public boolean canEat(Item item) { - return session.getTagCache().is(ItemTag.SNIFFER_FOOD, item); + @Nullable + protected ItemTag getFoodTag() { + return ItemTag.SNIFFER_FOOD; } public void setSnifferState(ObjectEntityMetadata entityMetadata) { diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/StriderEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/StriderEntity.java index dcdd40199..0291f75d9 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/StriderEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/StriderEntity.java @@ -26,14 +26,14 @@ package org.geysermc.geyser.entity.type.living.animal; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.inventory.GeyserItemStack; -import org.geysermc.geyser.item.Items; -import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.util.EntityUtils; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; @@ -94,8 +94,9 @@ public class StriderEntity extends AnimalEntity { } @Override - public boolean canEat(Item item) { - return item == Items.WARPED_FUNGUS; + @Nullable + protected ItemTag getFoodTag() { + return ItemTag.STRIDER_FOOD; } @NonNull diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/TurtleEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/TurtleEntity.java index 1d0aec75f..b3c1128e3 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/TurtleEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/TurtleEntity.java @@ -25,12 +25,12 @@ package org.geysermc.geyser.entity.type.living.animal; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; -import org.geysermc.geyser.item.Items; -import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import java.util.UUID; @@ -50,8 +50,9 @@ public class TurtleEntity extends AnimalEntity { } @Override - public boolean canEat(Item item) { - return item == Items.SEAGRASS; + @Nullable + protected ItemTag getFoodTag() { + return ItemTag.TURTLE_FOOD; } @Override diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/AbstractHorseEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/AbstractHorseEntity.java index 76416c146..ddc212053 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/AbstractHorseEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/AbstractHorseEntity.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.entity.type.living.animal.horse; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType; @@ -38,23 +39,16 @@ import org.geysermc.geyser.entity.attribute.GeyserAttributeType; import org.geysermc.geyser.entity.type.living.animal.AnimalEntity; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.Items; -import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; -import java.util.Set; import java.util.UUID; public class AbstractHorseEntity extends AnimalEntity { - /** - * A list of all foods a horse/donkey can eat on Java Edition. - * Used to display interactive tag if needed. - */ - private static final Set DONKEY_AND_HORSE_FOODS = Set.of(Items.GOLDEN_APPLE, Items.ENCHANTED_GOLDEN_APPLE, - Items.GOLDEN_CARROT, Items.SUGAR, Items.APPLE, Items.WHEAT, Items.HAY_BLOCK); public AbstractHorseEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); @@ -124,8 +118,9 @@ public class AbstractHorseEntity extends AnimalEntity { } @Override - public boolean canEat(Item item) { - return DONKEY_AND_HORSE_FOODS.contains(item); + @Nullable + protected ItemTag getFoodTag() { + return ItemTag.HORSE_FOOD; } @NonNull diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/CamelEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/CamelEntity.java index 00144617a..ee3b2be70 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/CamelEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/CamelEntity.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.entity.type.living.animal.horse; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType; @@ -32,9 +33,8 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket; import org.geysermc.geyser.entity.EntityDefinition; -import org.geysermc.geyser.item.Items; -import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; @@ -90,8 +90,8 @@ public class CamelEntity extends AbstractHorseEntity { } @Override - public boolean canEat(Item item) { - return item == Items.CACTUS; + protected @Nullable ItemTag getFoodTag() { + return ItemTag.CAMEL_FOOD; } @Override diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/LlamaEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/LlamaEntity.java index 346b6da9b..76939ceb9 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/LlamaEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/LlamaEntity.java @@ -26,12 +26,12 @@ package org.geysermc.geyser.entity.type.living.animal.horse; import lombok.Getter; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.geysermc.geyser.entity.EntityDefinition; -import org.geysermc.geyser.item.Items; -import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.util.MathUtils; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; @@ -56,7 +56,7 @@ public class LlamaEntity extends ChestedHorseEntity { } @Override - public boolean canEat(Item item) { - return item == Items.WHEAT || item == Items.HAY_BLOCK; + protected @Nullable ItemTag getFoodTag() { + return ItemTag.LLAMA_FOOD; } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/CatEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/CatEntity.java index fc5978c2b..bf1555e9d 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/CatEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/CatEntity.java @@ -26,14 +26,14 @@ package org.geysermc.geyser.entity.type.living.animal.tameable; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.inventory.GeyserItemStack; -import org.geysermc.geyser.item.Items; -import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; @@ -109,8 +109,8 @@ public class CatEntity extends TameableEntity { } @Override - public boolean canEat(Item item) { - return item == Items.COD || item == Items.SALMON; + protected @Nullable ItemTag getFoodTag() { + return ItemTag.CAT_FOOD; } @NonNull diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/ParrotEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/ParrotEntity.java index 18feec979..8baba6f00 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/ParrotEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/ParrotEntity.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.entity.type.living.animal.tameable; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; @@ -33,6 +34,7 @@ import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; @@ -49,16 +51,17 @@ public class ParrotEntity extends TameableEntity { } @Override - public boolean canEat(Item item) { - return false; + @Nullable + protected ItemTag getFoodTag() { + return null; } private boolean isTameFood(Item item) { - return TAMING_FOOD.contains(item); + return session.getTagCache().is(ItemTag.PARROT_FOOD, item); } private boolean isPoisonousFood(Item item) { - return item == Items.COOKIE; + return session.getTagCache().is(ItemTag.PARROT_POISONOUS_FOOD, item); } @NonNull diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/TameableEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/TameableEntity.java index 4a1cd70e9..e16823d37 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/TameableEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/TameableEntity.java @@ -39,7 +39,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEn import java.util.Optional; import java.util.UUID; -public class TameableEntity extends AnimalEntity { +public abstract class TameableEntity extends AnimalEntity { /** * Used in the interactive tag manager to track if the session player owns this entity */ diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java index 833d0e175..ceb29695a 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java @@ -38,6 +38,7 @@ import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.DyeItem; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; import org.geysermc.geyser.util.ItemUtils; @@ -120,9 +121,9 @@ public class WolfEntity extends TameableEntity { } @Override - public boolean canEat(Item item) { - // Cannot be a baby to eat these foods - return WOLF_FOODS.contains(item) && !isBaby(); + @Nullable + protected ItemTag getFoodTag() { + return ItemTag.WOLF_FOOD; } @Override diff --git a/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java b/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java index bba13e753..c70467b4c 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java @@ -115,7 +115,7 @@ public class FireworkRocketItem extends Item { newExplosionData.putByteArray("FireworkFade", colors); newExplosionData.putBoolean("FireworkTrail", explosion.isHasTrail()); - newExplosionData.putBoolean("FireworkFlicker", explosion.isHasTwinkle()); // TODO verify + newExplosionData.putBoolean("FireworkFlicker", explosion.isHasTwinkle()); return newExplosionData.build(); } diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/tags/ItemTag.java b/core/src/main/java/org/geysermc/geyser/session/cache/tags/ItemTag.java index df9a423ed..f064d0763 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/tags/ItemTag.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/tags/ItemTag.java @@ -31,11 +31,32 @@ public enum ItemTag { AXOLOTL_FOOD("axolotl_food"), CREEPER_IGNITERS("creeper_igniters"), FISHES("fishes"), - FLOWERS("flowers"), FOX_FOOD("fox_food"), PIGLIN_LOVED("piglin_loved"), SMALL_FLOWERS("small_flowers"), - SNIFFER_FOOD("sniffer_food"); + SNIFFER_FOOD("sniffer_food"), + PIGLIN_FOOD("piglin_food"), + COW_FOOD("cow_food"), + GOAT_FOOD("goat_food"), + SHEEP_FOOD("sheep_food"), + WOLF_FOOD("wolf_food"), + CAT_FOOD("cat_food"), + HORSE_FOOD("horse_food"), + CAMEL_FOOD("camel_food"), + ARMADILLO_FOOD("armadillo_food"), + BEE_FOOD("bee_food"), + CHICKEN_FOOD("chicken_food"), + FROG_FOOD("frog_food"), + HOGLIN_FOOD("hoglin_food"), + LLAMA_FOOD("llama_food"), + OCELOT_FOOD("ocelot_food"), + PANDA_FOOD("panda_food"), + PIG_FOOD("pig_food"), + RABBIT_FOOD("rabbit_food"), + STRIDER_FOOD("strider_food"), + TURTLE_FOOD("turtle_food"), + PARROT_FOOD("parrot_food"), + PARROT_POISONOUS_FOOD("parrot_poisonous_food"); ItemTag(String identifier) { register(identifier, this); diff --git a/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java index 11e092b57..49ee498b9 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java @@ -249,19 +249,17 @@ public final class ItemTranslator { String name = modifier.getName().replace("minecraft:", ""); // the namespace does not need to be present, but if it is, the java client ignores it as of pre-1.20.5 - String operationTotal; ModifierOperation operation = modifier.getOperation(); - if (operation == ModifierOperation.ADD) { - if (name.equals("generic.knockback_resistance")) { - amount *= 10; + String operationTotal = switch (operation) { + case ADD -> { + if (name.equals("generic.knockback_resistance")) { + amount *= 10; + } + yield ATTRIBUTE_FORMAT.format(amount); } - operationTotal = ATTRIBUTE_FORMAT.format(amount); - } else if (operation == ModifierOperation.ADD_MULTIPLIED_BASE || operation == ModifierOperation.ADD_MULTIPLIED_TOTAL) { - operationTotal = ATTRIBUTE_FORMAT.format(amount * 100) + "%"; - } else { - GeyserImpl.getInstance().getLogger().warning("Unhandled ModifierOperation while adding item attributes: " + operation); - return null; - } + case ADD_MULTIPLIED_BASE, ADD_MULTIPLIED_TOTAL -> + ATTRIBUTE_FORMAT.format(amount * 100) + "%"; + }; if (amount > 0) { operationTotal = "+" + operationTotal; } From abb1d7d9e9fb1de2c5959fc679cb5afbda7b0978 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Tue, 30 Apr 2024 18:50:41 -0400 Subject: [PATCH 325/344] Indicate Java 1.20.6 support --- README.md | 2 +- .../src/main/java/org/geysermc/geyser/network/GameProtocol.java | 2 +- gradle/libs.versions.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 314876d60..2fdc93fa1 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,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.20.40 - 1.20.80 and Minecraft Java 1.20.5 +### Currently supporting Minecraft Bedrock 1.20.40 - 1.20.80 and Minecraft Java 1.20.5/1.20.6 ## 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/GameProtocol.java b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java index cf80e8c6e..fdaecbb69 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java @@ -124,7 +124,7 @@ public final class GameProtocol { * @return the supported Minecraft: Java Edition version names */ public static List getJavaVersions() { - return List.of(DEFAULT_JAVA_CODEC.getMinecraftVersion()); + return List.of("1.20.5", DEFAULT_JAVA_CODEC.getMinecraftVersion()); } /** diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9e5a0a53f..e975ba0c8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ protocol-connection = "3.0.0.Beta1-20240411.165033-128" raknet = "1.0.0.CR3-20240416.144209-1" blockstateupdater="1.20.80-20240411.142413-1" mcauthlib = "d9d773e" -mcprotocollib = "bc8526b" # Revert from jitpack after release +mcprotocollib = "209e79f8" # Revert from jitpack after release adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" From 1e8d6b23cf5f5058f6bf11c362346e0f48871a20 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Wed, 1 May 2024 15:35:30 -0400 Subject: [PATCH 326/344] Different registry implementation; fix banner blocks with ViaVersion --- .../living/animal/tameable/WolfEntity.java | 2 +- .../geysermc/geyser/item/type/ArmorItem.java | 4 +- .../geysermc/geyser/item/type/BannerItem.java | 52 +++++++++------- .../geyser/session/cache/RegistryCache.java | 52 +++++----------- .../session/cache/registry/JavaRegistry.java | 56 ++++++++++++++++++ .../cache/registry/SimpleJavaRegistry.java | 59 +++++++++++++++++++ .../translator/text/MessageTranslator.java | 2 +- .../org/geysermc/geyser/util/ChunkUtils.java | 2 +- 8 files changed, 166 insertions(+), 63 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/session/cache/registry/JavaRegistry.java create mode 100644 core/src/main/java/org/geysermc/geyser/session/cache/registry/SimpleJavaRegistry.java diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java index ceb29695a..4573f0e7a 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java @@ -113,7 +113,7 @@ public class WolfEntity extends TameableEntity { // 1.20.5+ public void setWolfVariant(IntEntityMetadata entityMetadata) { - WolfVariant wolfVariant = session.getRegistryCache().wolfVariants().get(entityMetadata.getPrimitiveValue()); + WolfVariant wolfVariant = session.getRegistryCache().wolfVariants().byId(entityMetadata.getPrimitiveValue()); if (wolfVariant == null) { wolfVariant = WolfVariant.PALE; } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java index 76f951c66..fc0dd3ba4 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java @@ -56,8 +56,8 @@ public class ArmorItem extends Item { return; } - TrimMaterial material = session.getRegistryCache().trimMaterials().get(trim.material().id()); - TrimPattern pattern = session.getRegistryCache().trimPatterns().get(trim.pattern().id()); + TrimMaterial material = session.getRegistryCache().trimMaterials().byId(trim.material().id()); + TrimPattern pattern = session.getRegistryCache().trimPatterns().byId(trim.pattern().id()); NbtMapBuilder trimBuilder = NbtMap.builder(); // bedrock has an uppercase first letter key, and the value is not namespaced diff --git a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java index 2f5d96b5a..6c2678db9 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java @@ -33,13 +33,14 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtList; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtType; -import org.cloudburstmc.protocol.common.util.Int2ObjectBiMap; import org.geysermc.geyser.inventory.item.BannerPattern; import org.geysermc.geyser.inventory.item.DyeColor; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.registry.JavaRegistry; import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.mcprotocollib.protocol.data.game.Holder; +import org.geysermc.mcprotocollib.protocol.data.game.Identifier; import org.geysermc.mcprotocollib.protocol.data.game.item.component.BannerPatternLayer; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; @@ -57,7 +58,6 @@ public class BannerItem extends BlockItem { * the correct ominous banner pattern if Bedrock pulls the item from creative. */ private static final List> OMINOUS_BANNER_PATTERN; - private static final List OMINOUS_BANNER_PATTERN_BLOCK; // TODO fix - we somehow need to be able to get the sessions banner pattern registry, which we don't have where we need this :/ private static final int[] ominousBannerPattern = new int[] { 21, 29, 30, 1, 34, 15, 3, 1 }; @@ -74,11 +74,6 @@ public class BannerItem extends BlockItem { Pair.of(BannerPattern.CIRCLE, DyeColor.LIGHT_GRAY), Pair.of(BannerPattern.BORDER, DyeColor.BLACK) ); - - OMINOUS_BANNER_PATTERN_BLOCK = new ArrayList<>(); - for (Pair pair : OMINOUS_BANNER_PATTERN) { - OMINOUS_BANNER_PATTERN_BLOCK.add(getJavaBannerPatternTag(pair.left(), pair.right())); - } } public static boolean isOminous(GeyserSession session, List patternLayers) { @@ -92,7 +87,7 @@ public class BannerItem extends BlockItem { !patternLayer.getPattern().isId()) { return false; } - BannerPattern bannerPattern = session.getRegistryCache().bannerPatterns().get(patternLayer.getPattern().id()); + BannerPattern bannerPattern = session.getRegistryCache().bannerPatterns().byId(patternLayer.getPattern().id()); if (bannerPattern != pair.left()) { return false; } @@ -101,7 +96,25 @@ public class BannerItem extends BlockItem { } public static boolean isOminous(List blockEntityPatterns) { - return OMINOUS_BANNER_PATTERN_BLOCK.equals(blockEntityPatterns); + // Cannot do a simple NBT equals check here because the IDs may not be full resource locations + // ViaVersion's fault, 1.20.4 -> 1.20.5, but it works on Java so we need to support it. + if (OMINOUS_BANNER_PATTERN.size() != blockEntityPatterns.size()) { + return false; + } + for (int i = 0; i < OMINOUS_BANNER_PATTERN.size(); i++) { + NbtMap patternLayer = blockEntityPatterns.get(i); + Pair pair = OMINOUS_BANNER_PATTERN.get(i); + DyeColor color = DyeColor.getByJavaIdentifier(patternLayer.getString("color")); + if (color != pair.right()) { + return false; + } + String id = Identifier.formalize(patternLayer.getString("pattern")); // Ouch + BannerPattern bannerPattern = BannerPattern.getByJavaIdentifier(id); + if (bannerPattern != pair.left()) { + return false; + } + } + return true; } /** @@ -133,7 +146,7 @@ public class BannerItem extends BlockItem { List patternList = new ArrayList<>(patterns.size()); for (BannerPatternLayer patternLayer : patterns) { patternLayer.getPattern().ifId(holder -> { - BannerPattern bannerPattern = session.getRegistryCache().bannerPatterns().get(holder.id()); + BannerPattern bannerPattern = session.getRegistryCache().bannerPatterns().byId(holder.id()); if (bannerPattern != null) { NbtMap tag = NbtMap.builder() .putString("Pattern", bannerPattern.getBedrockIdentifier()) @@ -154,7 +167,8 @@ public class BannerItem extends BlockItem { * @return The Bedrock edition format pattern nbt */ private static NbtMap getBedrockBannerPattern(NbtMap pattern) { - BannerPattern bannerPattern = BannerPattern.getByJavaIdentifier(pattern.getString("pattern")); + // ViaVersion 1.20.4 -> 1.20.5 can send without the namespace + BannerPattern bannerPattern = BannerPattern.getByJavaIdentifier(Identifier.formalize(pattern.getString("pattern"))); DyeColor dyeColor = DyeColor.getByJavaIdentifier(pattern.getString("color")); if (bannerPattern == null || dyeColor == null) { return null; @@ -166,13 +180,6 @@ public class BannerItem extends BlockItem { .build(); } - public static NbtMap getJavaBannerPatternTag(BannerPattern bannerPattern, DyeColor dyeColor) { - return NbtMap.builder() - .putString("pattern", bannerPattern.getJavaIdentifier()) - .putString("color", dyeColor.getJavaIdentifier()) - .build(); - } - /** * Convert the Bedrock edition banner pattern nbt to Java edition * @@ -180,11 +187,14 @@ public class BannerItem extends BlockItem { * @return The Java edition format pattern layer */ public static BannerPatternLayer getJavaBannerPattern(GeyserSession session, NbtMap pattern) { - Int2ObjectBiMap registry = session.getRegistryCache().bannerPatterns(); + JavaRegistry registry = session.getRegistryCache().bannerPatterns(); BannerPattern bannerPattern = BannerPattern.getByBedrockIdentifier(pattern.getString("Pattern")); DyeColor dyeColor = DyeColor.getById(15 - pattern.getInt("Color")); - if (bannerPattern != null && dyeColor != null && registry.containsValue(bannerPattern)) { - return new BannerPatternLayer(Holder.ofId(registry.get(bannerPattern)), dyeColor.ordinal()); + if (bannerPattern != null && dyeColor != null) { + int id = registry.byValue(bannerPattern); + if (id != -1) { + return new BannerPatternLayer(Holder.ofId(id), dyeColor.ordinal()); + } } return null; } diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java index 4dfc603ee..9581df253 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java @@ -27,25 +27,25 @@ package org.geysermc.geyser.session.cache; import it.unimi.dsi.fastutil.ints.Int2IntMap; import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import lombok.AccessLevel; import lombok.Getter; import lombok.experimental.Accessors; import org.cloudburstmc.protocol.bedrock.data.TrimMaterial; import org.cloudburstmc.protocol.bedrock.data.TrimPattern; -import org.cloudburstmc.protocol.common.util.Int2ObjectBiMap; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.entity.type.living.animal.tameable.WolfEntity; import org.geysermc.geyser.inventory.item.BannerPattern; import org.geysermc.geyser.inventory.recipe.TrimRecipe; import org.geysermc.geyser.level.JavaDimension; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.registry.JavaRegistry; +import org.geysermc.geyser.session.cache.registry.SimpleJavaRegistry; import org.geysermc.geyser.text.TextDecoration; import org.geysermc.geyser.translator.level.BiomeTranslator; import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry; import org.geysermc.mcprotocollib.protocol.packet.configuration.clientbound.ClientboundRegistryDataPacket; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -71,7 +71,7 @@ public final class RegistryCache { register("trim_material", cache -> cache.trimMaterials, TrimRecipe::readTrimMaterial); register("trim_pattern", cache -> cache.trimPatterns, TrimRecipe::readTrimPattern); register("worldgen/biome", (cache, array) -> cache.biomeTranslations = array, BiomeTranslator::loadServerBiome); - registerBannerRegistry(($, entry) -> BannerPattern.getByJavaIdentifier(entry.getId())); + register("banner_pattern", cache -> cache.bannerPatterns, ($, entry) -> BannerPattern.getByJavaIdentifier(entry.getId())); register("wolf_variant", cache -> cache.wolfVariants, ($, entry) -> WolfEntity.WolfVariant.getByJavaIdentifier(entry.getId())); } @@ -82,16 +82,16 @@ public final class RegistryCache { * Java -> Bedrock biome network IDs. */ private int[] biomeTranslations; - private final Int2ObjectMap chatTypes = new Int2ObjectOpenHashMap<>(7); + private final JavaRegistry chatTypes = new SimpleJavaRegistry<>(); /** * All dimensions that the client could possibly connect to. */ - private final Int2ObjectMap dimensions = new Int2ObjectOpenHashMap<>(4); - private final Int2ObjectMap trimMaterials = new Int2ObjectOpenHashMap<>(); - private final Int2ObjectMap trimPatterns = new Int2ObjectOpenHashMap<>(); + private final JavaRegistry dimensions = new SimpleJavaRegistry<>(); + private final JavaRegistry trimMaterials = new SimpleJavaRegistry<>(); + private final JavaRegistry trimPatterns = new SimpleJavaRegistry<>(); - private Int2ObjectBiMap bannerPatterns = new Int2ObjectBiMap<>(); - private final Int2ObjectMap wolfVariants = new Int2ObjectOpenHashMap<>(); + private final JavaRegistry bannerPatterns = new SimpleJavaRegistry<>(); + private final JavaRegistry wolfVariants = new SimpleJavaRegistry<>(); public RegistryCache(GeyserSession session) { this.session = session; @@ -109,47 +109,25 @@ public final class RegistryCache { } } - private static void registerBannerRegistry(BiFunction reader) { - REGISTRIES.put("minecraft:banner_pattern", ((registryCache, entries) -> { - // Clear each local cache every time a new registry entry is given to us - // (e.g. proxy server switches) - registryCache.bannerPatterns = new Int2ObjectBiMap<>(); // Cannot clear it, must re-create :( - for (int i = 0; i < entries.size(); i++) { - RegistryEntry entry = entries.get(i); - // This is what Geyser wants to keep as a value for this registry. - T cacheEntry = reader.apply(registryCache.session, entry); - if (cacheEntry != null) { - registryCache.bannerPatterns.put(i, (BannerPattern) cacheEntry); - } else { - // TODO - seems to be possible with viaversion :/ - GeyserImpl.getInstance().getLogger().warning("Was not able to translate entry: "); - } - } - })); - } - /** * @param registry the Java registry resource location, without the "minecraft:" prefix. * @param localCacheFunction which local field in RegistryCache are we caching entries for this registry? * @param reader converts the RegistryEntry NBT into a class file * @param the class that represents these entries. */ - private static void register(String registry, Function> localCacheFunction, BiFunction reader) { + private static void register(String registry, Function> localCacheFunction, BiFunction reader) { REGISTRIES.put("minecraft:" + registry, (registryCache, entries) -> { - Int2ObjectMap localCache = localCacheFunction.apply(registryCache); + JavaRegistry localCache = localCacheFunction.apply(registryCache); // Clear each local cache every time a new registry entry is given to us // (e.g. proxy server switches) - localCache.clear(); + List builder = new ArrayList<>(entries.size()); for (int i = 0; i < entries.size(); i++) { RegistryEntry entry = entries.get(i); // This is what Geyser wants to keep as a value for this registry. T cacheEntry = reader.apply(registryCache.session, entry); - localCache.put(i, cacheEntry); - } - // Trim registry down to needed size - if (localCache instanceof Int2ObjectOpenHashMap hashMap) { - hashMap.trim(); + builder.add(i, cacheEntry); } + localCache.reset(builder); }); } diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/registry/JavaRegistry.java b/core/src/main/java/org/geysermc/geyser/session/cache/registry/JavaRegistry.java new file mode 100644 index 000000000..d7c7782ea --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/session/cache/registry/JavaRegistry.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2019-2024 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.session.cache.registry; + +import org.checkerframework.checker.index.qual.NonNegative; + +import java.util.List; + +/** + * A wrapper for a list, holding Java registry values. + */ +public interface JavaRegistry { + + /** + * Looks up a registry entry by its ID. The object can be null, or not present. + */ + T byId(@NonNegative int id); + + /** + * Reverse looks-up an object to return its network ID, or -1. + */ + int byValue(T value); + + /** + * Resets the objects by these IDs. + */ + void reset(List values); + + /** + * All values of this registry, as a list. + */ + List values(); +} diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/registry/SimpleJavaRegistry.java b/core/src/main/java/org/geysermc/geyser/session/cache/registry/SimpleJavaRegistry.java new file mode 100644 index 000000000..633e5fbd1 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/session/cache/registry/SimpleJavaRegistry.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2019-2024 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.session.cache.registry; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.checkerframework.checker.index.qual.NonNegative; + +import java.util.List; + +public class SimpleJavaRegistry implements JavaRegistry { + protected final ObjectArrayList values = new ObjectArrayList<>(); + + @Override + public T byId(@NonNegative int id) { + if (id < 0 || id >= this.values.size()) { + return null; + } + return this.values.get(id); + } + + @Override + public int byValue(T value) { + return this.values.indexOf(value); + } + + @Override + public void reset(List values) { + this.values.addAll(values); + this.values.trim(); + } + + @Override + public List values() { + return this.values; + } +} diff --git a/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java index 884f05256..5a0121039 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java @@ -330,7 +330,7 @@ public class MessageTranslator { textPacket.setNeedsTranslation(false); - TextDecoration decoration = session.getRegistryCache().chatTypes().get(chatType); + TextDecoration decoration = session.getRegistryCache().chatTypes().byId(chatType); if (decoration != null) { // As of 1.19 - do this to apply all the styling for signed messages // Though, Bedrock cannot care about the signed stuff. diff --git a/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java b/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java index a542f7431..379162540 100644 --- a/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java @@ -280,7 +280,7 @@ public class ChunkUtils { * This must be done after the player has switched dimensions so we know what their dimension is */ public static void loadDimension(GeyserSession session) { - JavaDimension dimension = session.getRegistryCache().dimensions().get(session.getDimension()); + JavaDimension dimension = session.getRegistryCache().dimensions().byId(session.getDimension()); session.setDimensionType(dimension); int minY = dimension.minY(); int maxY = dimension.maxY(); From cc635d4447abb15089065b3948565e0382493684 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Wed, 1 May 2024 15:41:27 -0400 Subject: [PATCH 327/344] This would probably end up being an issue... --- .../geyser/session/cache/registry/SimpleJavaRegistry.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/registry/SimpleJavaRegistry.java b/core/src/main/java/org/geysermc/geyser/session/cache/registry/SimpleJavaRegistry.java index 633e5fbd1..9839a1568 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/registry/SimpleJavaRegistry.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/registry/SimpleJavaRegistry.java @@ -48,6 +48,7 @@ public class SimpleJavaRegistry implements JavaRegistry { @Override public void reset(List values) { + this.values.clear(); this.values.addAll(values); this.values.trim(); } From 1291b89e64e0ff5e96e90ad6a354add0c0f94365 Mon Sep 17 00:00:00 2001 From: chris Date: Thu, 2 May 2024 00:29:33 +0200 Subject: [PATCH 328/344] Ensure proper Geyser starting/disabling when Geyser is used on a client (#4621) * Ensure proper Geyser starting/disabling when Geyser is used on a client * also set correct remote port * only use direct connection on server, not client, actually override remote port --- .../fabric/GeyserFabricBootstrap.java | 23 ++++++++++++++++--- .../neoforge/GeyserNeoForgeBootstrap.java | 19 +++++++++++++-- .../platform/mod/GeyserModBootstrap.java | 19 +++++++++++++-- .../mixin/client/IntegratedServerMixin.java | 6 +++-- 4 files changed, 58 insertions(+), 9 deletions(-) diff --git a/bootstrap/mod/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricBootstrap.java b/bootstrap/mod/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricBootstrap.java index 81e329c03..c363ade8f 100644 --- a/bootstrap/mod/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricBootstrap.java +++ b/bootstrap/mod/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricBootstrap.java @@ -28,14 +28,15 @@ package org.geysermc.geyser.platform.fabric; import me.lucko.fabric.api.permissions.v0.Permissions; import net.fabricmc.api.EnvType; import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.commands.CommandSourceStack; import net.minecraft.world.entity.player.Player; +import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.platform.mod.GeyserModBootstrap; import org.geysermc.geyser.platform.mod.GeyserModUpdateListener; -import org.checkerframework.checker.nullness.qual.NonNull; public class GeyserFabricBootstrap extends GeyserModBootstrap implements ModInitializer { @@ -45,21 +46,37 @@ public class GeyserFabricBootstrap extends GeyserModBootstrap implements ModInit @Override public void onInitialize() { - if (FabricLoader.getInstance().getEnvironmentType() == EnvType.SERVER) { + if (isServer()) { // Set as an event, so we can get the proper IP and port if needed ServerLifecycleEvents.SERVER_STARTED.register((server) -> { this.setServer(server); onGeyserEnable(); }); + } else { + ClientLifecycleEvents.CLIENT_STOPPING.register(($)-> { + onGeyserShutdown(); + }); } // These are only registered once - ServerLifecycleEvents.SERVER_STOPPING.register((server) -> onGeyserShutdown()); + ServerLifecycleEvents.SERVER_STOPPING.register((server) -> { + if (isServer()) { + onGeyserShutdown(); + } else { + onGeyserDisable(); + } + }); + ServerPlayConnectionEvents.JOIN.register((handler, $, $$) -> GeyserModUpdateListener.onPlayReady(handler.getPlayer())); this.onGeyserInitialize(); } + @Override + public boolean isServer() { + return FabricLoader.getInstance().getEnvironmentType().equals(EnvType.SERVER); + } + @Override public boolean hasPermission(@NonNull Player source, @NonNull String permissionNode) { return Permissions.check(source, permissionNode); diff --git a/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgeBootstrap.java b/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgeBootstrap.java index 67cad1683..1655dea91 100644 --- a/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgeBootstrap.java +++ b/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgeBootstrap.java @@ -27,10 +27,10 @@ package org.geysermc.geyser.platform.neoforge; import net.minecraft.commands.CommandSourceStack; import net.minecraft.world.entity.player.Player; -import net.neoforged.api.distmarker.Dist; import net.neoforged.fml.common.Mod; import net.neoforged.fml.loading.FMLLoader; import net.neoforged.neoforge.common.NeoForge; +import net.neoforged.neoforge.event.GameShuttingDownEvent; import net.neoforged.neoforge.event.entity.player.PlayerEvent; import net.neoforged.neoforge.event.server.ServerStartedEvent; import net.neoforged.neoforge.event.server.ServerStoppingEvent; @@ -46,9 +46,11 @@ public class GeyserNeoForgeBootstrap extends GeyserModBootstrap { public GeyserNeoForgeBootstrap() { super(new GeyserNeoForgePlatform()); - if (FMLLoader.getDist() == Dist.DEDICATED_SERVER) { + if (isServer()) { // Set as an event so we can get the proper IP and port if needed NeoForge.EVENT_BUS.addListener(this::onServerStarted); + } else { + NeoForge.EVENT_BUS.addListener(this::onClientStopping); } NeoForge.EVENT_BUS.addListener(this::onServerStopping); @@ -64,6 +66,14 @@ public class GeyserNeoForgeBootstrap extends GeyserModBootstrap { } private void onServerStopping(ServerStoppingEvent event) { + if (isServer()) { + this.onGeyserShutdown(); + } else { + this.onGeyserDisable(); + } + } + + private void onClientStopping(GameShuttingDownEvent ignored) { this.onGeyserShutdown(); } @@ -71,6 +81,11 @@ public class GeyserNeoForgeBootstrap extends GeyserModBootstrap { GeyserModUpdateListener.onPlayReady(event.getEntity()); } + @Override + public boolean isServer() { + return FMLLoader.getDist().isDedicatedServer(); + } + @Override public boolean hasPermission(@NonNull Player source, @NonNull String permissionNode) { return this.permissionHandler.hasPermission(source, permissionNode); diff --git a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModBootstrap.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModBootstrap.java index db966ec1a..d3d3a9104 100644 --- a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModBootstrap.java +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModBootstrap.java @@ -58,6 +58,7 @@ import org.geysermc.geyser.util.FileUtils; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.net.SocketAddress; import java.nio.file.Path; import java.util.Map; import java.util.UUID; @@ -127,7 +128,9 @@ public abstract class GeyserModBootstrap implements GeyserBootstrap { // We want to do this late in the server startup process to allow other mods // To do their job injecting, then connect into *that* this.geyserInjector = new GeyserModInjector(server, this.platform); - this.geyserInjector.initializeLocalChannel(this); + if (isServer()) { + this.geyserInjector.initializeLocalChannel(this); + } // Start command building // Set just "geyser" as the help command @@ -242,7 +245,19 @@ public abstract class GeyserModBootstrap implements GeyserBootstrap { @Override public int getServerPort() { - return ((GeyserServerPortGetter) server).geyser$getServerPort(); + if (isServer()) { + return ((GeyserServerPortGetter) server).geyser$getServerPort(); + } else { + // Set in the IntegratedServerMixin + return geyserConfig.getRemote().port(); + } + } + + public abstract boolean isServer(); + + @Override + public @Nullable SocketAddress getSocketAddress() { + return this.geyserInjector.getServerSocketAddress(); } @Override diff --git a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/mixin/client/IntegratedServerMixin.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/mixin/client/IntegratedServerMixin.java index 4db1165fc..ece2f730a 100644 --- a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/mixin/client/IntegratedServerMixin.java +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/mixin/client/IntegratedServerMixin.java @@ -54,8 +54,10 @@ public class IntegratedServerMixin implements GeyserServerPortGetter { private void onOpenToLan(GameType gameType, boolean cheatsAllowed, int port, CallbackInfoReturnable cir) { if (cir.getReturnValueZ()) { // If the LAN is opened, starts Geyser. - GeyserModBootstrap.getInstance().setServer((MinecraftServer) (Object) this); - GeyserModBootstrap.getInstance().onGeyserEnable(); + GeyserModBootstrap instance = GeyserModBootstrap.getInstance(); + instance.setServer((MinecraftServer) (Object) this); + instance.getGeyserConfig().getRemote().setPort(port); + instance.onGeyserEnable(); // Ensure player locale has been loaded, in case it's different from Java system language GeyserLocale.loadGeyserLocale(this.minecraft.options.languageCode); // Give indication that Geyser is loaded From fdae333351a6e4f9e6b5aa4536133dee7ea35e91 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Wed, 1 May 2024 19:00:39 -0400 Subject: [PATCH 329/344] Add data components hash code to translated NBT --- .../java/org/geysermc/geyser/item/type/Item.java | 4 ++++ .../inventory/PlayerInventoryTranslator.java | 6 ++++++ .../org/geysermc/geyser/util/InventoryUtils.java | 15 +++++++++++++++ 3 files changed, 25 insertions(+) diff --git a/core/src/main/java/org/geysermc/geyser/item/type/Item.java b/core/src/main/java/org/geysermc/geyser/item/type/Item.java index cc49f3785..bfcfb23d1 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/Item.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/Item.java @@ -151,6 +151,10 @@ public class Item { if (repairCost != null) { builder.putInt("RepairCost", repairCost); } + + // Prevents the client from trying to stack items with untranslated components + // Relies on correct hash code implementation, and some luck + builder.putInt("GeyserHash", components.hashCode()); // TODO: don't rely on this } /** diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java index 7459ccf30..36752e582 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java @@ -261,6 +261,8 @@ public class PlayerInventoryTranslator extends InventoryTranslator { GeyserItemStack sourceItem = inventory.getItem(sourceSlot); if (playerInv.getCursor().isEmpty()) { playerInv.setCursor(sourceItem.copy(0), session); + } else if (!InventoryUtils.canStack(sourceItem, playerInv.getCursor())) { + return rejectRequest(request); } playerInv.getCursor().add(transferAmount); @@ -272,6 +274,8 @@ public class PlayerInventoryTranslator extends InventoryTranslator { GeyserItemStack sourceItem = playerInv.getCursor(); if (inventory.getItem(destSlot).isEmpty()) { inventory.setItem(destSlot, sourceItem.copy(0), session); + } else if (!InventoryUtils.canStack(sourceItem, inventory.getItem(destSlot))) { + return rejectRequest(request); } inventory.getItem(destSlot).add(transferAmount); @@ -284,6 +288,8 @@ public class PlayerInventoryTranslator extends InventoryTranslator { GeyserItemStack sourceItem = inventory.getItem(sourceSlot); if (inventory.getItem(destSlot).isEmpty()) { inventory.setItem(destSlot, sourceItem.copy(0), session); + } else if (!InventoryUtils.canStack(sourceItem, inventory.getItem(destSlot))) { + return rejectRequest(request); } inventory.getItem(destSlot).add(transferAmount); diff --git a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java index 63644d5fc..64c95afdd 100644 --- a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java @@ -178,11 +178,26 @@ public class InventoryUtils { } public static boolean canStack(GeyserItemStack item1, GeyserItemStack item2) { + if (GeyserImpl.getInstance().getConfig().isDebugMode()) + canStackDebug(item1, item2); if (item1.isEmpty() || item2.isEmpty()) return false; return item1.getJavaId() == item2.getJavaId() && Objects.equals(item1.getComponents(), item2.getComponents()); } + private static void canStackDebug(GeyserItemStack item1, GeyserItemStack item2) { + DataComponents components1 = item1.getComponents(); + DataComponents components2 = item2.getComponents(); + if (components1 != null && components2 != null) { + if (components1.hashCode() == components2.hashCode() && !components1.equals(components2)) { + GeyserImpl.getInstance().getLogger().error("DEBUG: DataComponents hash collision"); + GeyserImpl.getInstance().getLogger().error("hash: " + components1.hashCode()); + GeyserImpl.getInstance().getLogger().error("components1: " + components1); + GeyserImpl.getInstance().getLogger().error("components2: " + components2); + } + } + } + /** * Checks to see if an item stack represents air or has no count. */ From d003818e73c07b6e5b31370439f46bb1fb83c46f Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Thu, 2 May 2024 03:47:30 -0400 Subject: [PATCH 330/344] Potion fixes --- .../geyser/entity/EntityDefinitions.java | 1 - .../entity/type/AreaEffectCloudEntity.java | 7 +++++- .../entity/type/ThrownPotionEntity.java | 8 +++--- .../geyser/inventory/item/Potion.java | 25 ++++++++++++------- .../geysermc/geyser/item/type/PotionItem.java | 2 +- 5 files changed, 27 insertions(+), 16 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java index 6cd5f3fc2..2c5fe7a86 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java +++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java @@ -202,7 +202,6 @@ public final class EntityDefinitions { .type(EntityType.AREA_EFFECT_CLOUD) .height(0.5f).width(1.0f) .addTranslator(MetadataType.FLOAT, AreaEffectCloudEntity::setRadius) - .addTranslator(MetadataType.INT, (entity, entityMetadata) -> entity.getDirtyMetadata().put(EntityDataTypes.EFFECT_COLOR, entityMetadata.getValue())) .addTranslator(null) // Waiting .addTranslator(MetadataType.PARTICLE, AreaEffectCloudEntity::setParticle) .build(); diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/AreaEffectCloudEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/AreaEffectCloudEntity.java index 4b8eea061..83484b732 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/AreaEffectCloudEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/AreaEffectCloudEntity.java @@ -34,6 +34,7 @@ import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.FloatEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.level.particle.EntityEffectParticleData; import org.geysermc.mcprotocollib.protocol.data.game.level.particle.Particle; import java.util.UUID; @@ -51,7 +52,7 @@ public class AreaEffectCloudEntity extends Entity { dirtyMetadata.put(EntityDataTypes.AREA_EFFECT_CLOUD_DURATION, Integer.MAX_VALUE); // This disabled client side shrink of the cloud - dirtyMetadata.put(EntityDataTypes.AREA_EFFECT_CLOUD_RADIUS, 0.0f); + dirtyMetadata.put(EntityDataTypes.AREA_EFFECT_CLOUD_RADIUS, 0.5f); dirtyMetadata.put(EntityDataTypes.AREA_EFFECT_CLOUD_CHANGE_RATE, Float.MIN_VALUE); dirtyMetadata.put(EntityDataTypes.AREA_EFFECT_CLOUD_CHANGE_ON_PICKUP, Float.MIN_VALUE); @@ -69,5 +70,9 @@ public class AreaEffectCloudEntity extends Entity { Particle particle = entityMetadata.getValue(); Registries.PARTICLES.map(particle.getType(), p -> p.levelEventType() instanceof ParticleType particleType ? particleType : null).ifPresent(type -> dirtyMetadata.put(EntityDataTypes.AREA_EFFECT_CLOUD_PARTICLE, type)); + + if (particle.getData() instanceof EntityEffectParticleData effectParticleData) { + dirtyMetadata.put(EntityDataTypes.EFFECT_COLOR, effectParticleData.getColor()); + } } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/ThrownPotionEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ThrownPotionEntity.java index bfe429f33..88cf4f8b9 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/ThrownPotionEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/ThrownPotionEntity.java @@ -54,7 +54,7 @@ public class ThrownPotionEntity extends ThrowableItemEntity { public void setItem(EntityMetadata entityMetadata) { ItemStack itemStack = entityMetadata.getValue(); if (itemStack == null) { - dirtyMetadata.put(EntityDataTypes.EFFECT_COLOR, 0); + dirtyMetadata.put(EntityDataTypes.AUX_VALUE_DATA, (short) 0); setFlag(EntityFlag.ENCHANTED, false); setFlag(EntityFlag.LINGERING, false); } else { @@ -63,12 +63,12 @@ public class ThrownPotionEntity extends ThrowableItemEntity { if (components != null) { PotionContents potionContents = components.get(DataComponentType.POTION_CONTENTS); if (potionContents != null) { - Potion potion = Potion.VALUES[potionContents.getPotionId()]; + Potion potion = Potion.getByJavaId(potionContents.getPotionId()); if (potion != null) { - dirtyMetadata.put(EntityDataTypes.EFFECT_COLOR, (int) potion.getBedrockId()); + dirtyMetadata.put(EntityDataTypes.AUX_VALUE_DATA, potion.getBedrockId()); setFlag(EntityFlag.ENCHANTED, !NON_ENCHANTED_POTIONS.contains(potion)); } else { - dirtyMetadata.put(EntityDataTypes.EFFECT_COLOR, 0); + dirtyMetadata.put(EntityDataTypes.AUX_VALUE_DATA, (short) 0); GeyserImpl.getInstance().getLogger().debug("Unknown java potion: " + potionContents.getPotionId()); } } diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/Potion.java b/core/src/main/java/org/geysermc/geyser/inventory/item/Potion.java index 00a9b091e..cf3a37afd 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/item/Potion.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/item/Potion.java @@ -43,16 +43,19 @@ public enum Potion { INVISIBILITY(7), LONG_INVISIBILITY(8), LEAPING(9), - STRONG_LEAPING(11), LONG_LEAPING(10), + STRONG_LEAPING(11), FIRE_RESISTANCE(12), LONG_FIRE_RESISTANCE(13), SWIFTNESS(14), - STRONG_SWIFTNESS(16), LONG_SWIFTNESS(15), + STRONG_SWIFTNESS(16), SLOWNESS(17), - STRONG_SLOWNESS(42), LONG_SLOWNESS(18), + STRONG_SLOWNESS(42), + TURTLE_MASTER(37), + LONG_TURTLE_MASTER(38), + STRONG_TURTLE_MASTER(39), WATER_BREATHING(19), LONG_WATER_BREATHING(20), HEALING(21), @@ -60,20 +63,17 @@ public enum Potion { HARMING(23), STRONG_HARMING(24), POISON(25), - STRONG_POISON(27), LONG_POISON(26), + STRONG_POISON(27), REGENERATION(28), - STRONG_REGENERATION(30), LONG_REGENERATION(29), + STRONG_REGENERATION(30), STRENGTH(31), - STRONG_STRENGTH(33), LONG_STRENGTH(32), + STRONG_STRENGTH(33), WEAKNESS(34), LONG_WEAKNESS(35), LUCK(2), //does not exist - TURTLE_MASTER(37), - STRONG_TURTLE_MASTER(39), - LONG_TURTLE_MASTER(38), SLOW_FALLING(40), LONG_SLOW_FALLING(41); @@ -91,6 +91,13 @@ public enum Potion { return new PotionContents(this.ordinal(), -1, Int2ObjectMaps.emptyMap()); } + public static @Nullable Potion getByJavaId(int javaId) { + if (javaId >= 0 && javaId < VALUES.length) { + return VALUES[javaId]; + } + return null; + } + public static @Nullable Potion getByBedrockId(int bedrockId) { for (Potion potion : VALUES) { if (potion.bedrockId == bedrockId) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java b/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java index b69f7d35f..e9889c882 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java @@ -50,7 +50,7 @@ public class PotionItem extends Item { if (potionContents != null) { ItemDefinition customItemDefinition = CustomItemTranslator.getCustomItem(components, mapping); if (customItemDefinition == null) { - Potion potion = Potion.VALUES[potionContents.getPotionId()]; + Potion potion = Potion.getByJavaId(potionContents.getPotionId()); if (potion != null) { return ItemData.builder() .definition(mapping.getBedrockDefinition()) From 29a613b85c59f030bcfbaf9f1b80b1fe1a8a2aba Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Thu, 2 May 2024 05:04:19 -0400 Subject: [PATCH 331/344] Use java default area effect cloud radius --- .../geysermc/geyser/entity/type/AreaEffectCloudEntity.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/AreaEffectCloudEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/AreaEffectCloudEntity.java index 83484b732..165495506 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/AreaEffectCloudEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/AreaEffectCloudEntity.java @@ -32,6 +32,7 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.util.MathUtils; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.FloatEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.level.particle.EntityEffectParticleData; @@ -52,7 +53,7 @@ public class AreaEffectCloudEntity extends Entity { dirtyMetadata.put(EntityDataTypes.AREA_EFFECT_CLOUD_DURATION, Integer.MAX_VALUE); // This disabled client side shrink of the cloud - dirtyMetadata.put(EntityDataTypes.AREA_EFFECT_CLOUD_RADIUS, 0.5f); + dirtyMetadata.put(EntityDataTypes.AREA_EFFECT_CLOUD_RADIUS, 3.0f); dirtyMetadata.put(EntityDataTypes.AREA_EFFECT_CLOUD_CHANGE_RATE, Float.MIN_VALUE); dirtyMetadata.put(EntityDataTypes.AREA_EFFECT_CLOUD_CHANGE_ON_PICKUP, Float.MIN_VALUE); @@ -61,7 +62,7 @@ public class AreaEffectCloudEntity extends Entity { public void setRadius(FloatEntityMetadata entityMetadata) { // Anything less than 0.5 will cause the cloud to despawn - float value = Math.max(entityMetadata.getPrimitiveValue(), 0.5f); + float value = MathUtils.clamp(entityMetadata.getPrimitiveValue(), 0.5f, 32.0f); dirtyMetadata.put(EntityDataTypes.AREA_EFFECT_CLOUD_RADIUS, value); dirtyMetadata.put(EntityDataTypes.WIDTH, 2.0f * value); } From 60f8532be3826cb6e7a70750d4996045d4b3f26a Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Thu, 2 May 2024 06:06:12 -0400 Subject: [PATCH 332/344] Fix attribute display text --- .../translator/item/ItemTranslator.java | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java index 49ee498b9..768c94791 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java @@ -62,6 +62,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemAttribut import java.text.DecimalFormat; import java.util.ArrayList; +import java.util.EnumMap; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -71,9 +72,21 @@ public final class ItemTranslator { /** * The order of these slots is their display order on Java Edition clients */ - private static final ItemAttributeModifiers.EquipmentSlotGroup[] ALL_SLOTS = ItemAttributeModifiers.EquipmentSlotGroup.values(); + private static final EnumMap SLOT_NAMES; private static final DecimalFormat ATTRIBUTE_FORMAT = new DecimalFormat("0.#####"); + static { + // These are the only slots that are used and have translation strings + SLOT_NAMES = new EnumMap<>(ItemAttributeModifiers.EquipmentSlotGroup.class); + SLOT_NAMES.put(ItemAttributeModifiers.EquipmentSlotGroup.MAIN_HAND, "mainhand"); + SLOT_NAMES.put(ItemAttributeModifiers.EquipmentSlotGroup.OFF_HAND, "offhand"); + SLOT_NAMES.put(ItemAttributeModifiers.EquipmentSlotGroup.FEET, "feet"); + SLOT_NAMES.put(ItemAttributeModifiers.EquipmentSlotGroup.LEGS, "legs"); + SLOT_NAMES.put(ItemAttributeModifiers.EquipmentSlotGroup.CHEST, "chest"); + SLOT_NAMES.put(ItemAttributeModifiers.EquipmentSlotGroup.HEAD, "head"); + SLOT_NAMES.put(ItemAttributeModifiers.EquipmentSlotGroup.BODY, "body"); + } + private ItemTranslator() { } @@ -208,7 +221,7 @@ public final class ItemTranslator { ItemAttributeModifiers.EquipmentSlotGroup slotGroup = entry.getSlot(); if (slotGroup == ItemAttributeModifiers.EquipmentSlotGroup.ANY) { // modifier applies to all slots implicitly - for (var slot : ALL_SLOTS) { + for (var slot : SLOT_NAMES.keySet()) { slotsToModifiers.computeIfAbsent(slot, s -> new ArrayList<>()).add(loreEntry); } } else { @@ -218,7 +231,7 @@ public final class ItemTranslator { } // iterate through the small array, not the map, so that ordering matches Java Edition - for (var slot : ALL_SLOTS) { + for (var slot : SLOT_NAMES.keySet()) { List modifierStrings = slotsToModifiers.get(slot); if (modifierStrings == null || modifierStrings.isEmpty()) { continue; @@ -228,7 +241,7 @@ public final class ItemTranslator { Component slotComponent = Component.text() .resetStyle() .color(NamedTextColor.GRAY) - .append(Component.newline(), Component.translatable("item.modifiers." + slot)) + .append(Component.newline(), Component.translatable("item.modifiers." + SLOT_NAMES.get(slot))) .build(); builder.getOrCreateLore().add(MessageTranslator.convertMessage(slotComponent, language)); From f7c65f38d1b4bb606797bda161efb1ab276e6672 Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Thu, 2 May 2024 12:51:14 +0200 Subject: [PATCH 333/344] properly annotate methods in the ServerTransferEvent --- .../geyser/api/event/java/ServerTransferEvent.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/api/src/main/java/org/geysermc/geyser/api/event/java/ServerTransferEvent.java b/api/src/main/java/org/geysermc/geyser/api/event/java/ServerTransferEvent.java index b3b580ec3..594e28ef0 100644 --- a/api/src/main/java/org/geysermc/geyser/api/event/java/ServerTransferEvent.java +++ b/api/src/main/java/org/geysermc/geyser/api/event/java/ServerTransferEvent.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.api.event.java; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.common.value.qual.IntRange; import org.geysermc.geyser.api.connection.GeyserConnection; import org.geysermc.geyser.api.event.connection.ConnectionEvent; @@ -44,7 +45,8 @@ public class ServerTransferEvent extends ConnectionEvent { private int bedrockPort; private final Map cookies; - public ServerTransferEvent(@NonNull GeyserConnection connection, String host, int port, Map cookies) { + public ServerTransferEvent(@NonNull GeyserConnection connection, + @NonNull String host, int port, @NonNull Map cookies) { super(connection); this.host = host; this.port = port; @@ -58,7 +60,7 @@ public class ServerTransferEvent extends ConnectionEvent { * * @return the host */ - public String host() { + public @NonNull String host() { return this.host; } @@ -77,7 +79,7 @@ public class ServerTransferEvent extends ConnectionEvent { * * @return the host where the Bedrock client will be transferred to, or null if not set. */ - public String bedrockHost() { + public @Nullable String bedrockHost() { return this.bedrockHost; } From 6a214f235c21fb2c36e30a5ecbdbd15aa21706ff Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Thu, 2 May 2024 13:07:18 -0400 Subject: [PATCH 334/344] Remove duplicate method --- .../org/geysermc/geyser/platform/mod/GeyserModBootstrap.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModBootstrap.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModBootstrap.java index 98024ae45..786faac93 100644 --- a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModBootstrap.java +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModBootstrap.java @@ -260,11 +260,6 @@ public abstract class GeyserModBootstrap implements GeyserBootstrap { public abstract boolean isServer(); - @Override - public @Nullable SocketAddress getSocketAddress() { - return this.geyserInjector.getServerSocketAddress(); - } - @Override public boolean testFloodgatePluginPresent() { return this.platform.testFloodgatePluginPresent(this); From cab1a20034c05302ac5e61b6c9c401f6a396cc2a Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Thu, 2 May 2024 13:08:09 -0400 Subject: [PATCH 335/344] Set mappings commit to master --- core/src/main/resources/mappings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/resources/mappings b/core/src/main/resources/mappings index cb2cbe9f2..7c01501ed 160000 --- a/core/src/main/resources/mappings +++ b/core/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit cb2cbe9f262d14640f7c46885f1c8c9d23f2beaa +Subproject commit 7c01501ed6a0ee8848a66d729000539f2661f785 From b39ed5de53fd9b820023a3ac9c603a9936fa3e63 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Thu, 2 May 2024 20:33:28 -0400 Subject: [PATCH 336/344] Panda eating particles are not necessarily bamboo --- .../geysermc/geyser/entity/type/living/animal/PandaEntity.java | 3 ++- .../org/geysermc/geyser/inventory/item/StoredItemMappings.java | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PandaEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PandaEntity.java index 595e79e32..79401f63f 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PandaEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PandaEntity.java @@ -61,7 +61,8 @@ public class PandaEntity extends AnimalEntity { EntityEventPacket packet = new EntityEventPacket(); packet.setRuntimeEntityId(geyserId); packet.setType(EntityEventType.EATING_ITEM); - packet.setData(session.getItemMappings().getStoredItems().bamboo().getBedrockDefinition().getRuntimeId() << 16); + // As of 1.20.5 - pandas can eat cake + packet.setData(this.hand.getDefinition().getRuntimeId() << 16); session.sendUpstreamPacket(packet); } } diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java b/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java index c15a5d3b4..0305df685 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java @@ -40,7 +40,6 @@ import java.util.Map; @Getter @Accessors(fluent = true) public class StoredItemMappings { - private final ItemMapping bamboo; private final ItemMapping banner; private final ItemMapping barrier; private final ItemMapping compass; @@ -56,7 +55,6 @@ public class StoredItemMappings { private final ItemMapping writtenBook; public StoredItemMappings(Map itemMappings) { - this.bamboo = load(itemMappings, Items.BAMBOO); this.banner = load(itemMappings, Items.WHITE_BANNER); // As of 1.17.10, all banners have the same Bedrock ID this.barrier = load(itemMappings, Items.BARRIER); this.compass = load(itemMappings, Items.COMPASS); From a39cd65537cbcdbf8e958f0378e25588387df35e Mon Sep 17 00:00:00 2001 From: basaigh <53559772+basaigh@users.noreply.github.com> Date: Fri, 3 May 2024 12:53:47 +0100 Subject: [PATCH 337/344] Fix velocity ping passthrough (#4626) --- .../platform/velocity/GeyserVelocityPingPassthrough.java | 6 ++++++ gradle/libs.versions.toml | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPingPassthrough.java b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPingPassthrough.java index 8944ea134..b2258d3a3 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPingPassthrough.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPingPassthrough.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.platform.velocity; import com.velocitypowered.api.event.proxy.ProxyPingEvent; +import com.velocitypowered.api.network.ProtocolState; import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.api.proxy.InboundConnection; import com.velocitypowered.api.proxy.ProxyServer; @@ -88,6 +89,11 @@ public class GeyserVelocityPingPassthrough implements IGeyserPingPassthrough { public ProtocolVersion getProtocolVersion() { return ProtocolVersion.MAXIMUM_VERSION; } + + @Override + public ProtocolState getProtocolState() { + return ProtocolState.STATUS; + } } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 24d0d5050..2cca857f3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -28,7 +28,7 @@ viaversion = "4.9.2" adapters = "1.12-SNAPSHOT" commodore = "2.2" bungeecord = "a7c6ede" -velocity = "3.1.1" +velocity = "3.3.0-SNAPSHOT" viaproxy = "3.2.1" fabric-minecraft = "1.20.5" fabric-loader = "0.15.10" From 9d299ee83bf7e4b3bf7fd82048c85d8642248bab Mon Sep 17 00:00:00 2001 From: basaigh <53559772+basaigh@users.noreply.github.com> Date: Fri, 3 May 2024 15:29:15 +0100 Subject: [PATCH 338/344] Fix particle reading issues (#4631) --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2cca857f3..3756faa0e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ protocol-connection = "3.0.0.Beta1-20240411.165033-128" raknet = "1.0.0.CR3-20240416.144209-1" blockstateupdater="1.20.80-20240411.142413-1" mcauthlib = "d9d773e" -mcprotocollib = "209e79f8" # Revert from jitpack after release +mcprotocollib = "9b96ebda" # Revert from jitpack after release adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" From b8fe71a8bc9762443e0a2814a151a57f14c305cd Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Sat, 4 May 2024 01:06:59 -0400 Subject: [PATCH 339/344] Bump MCPL to fix ClientboundExplodePacket (#4635) --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3756faa0e..b00db373f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ protocol-connection = "3.0.0.Beta1-20240411.165033-128" raknet = "1.0.0.CR3-20240416.144209-1" blockstateupdater="1.20.80-20240411.142413-1" mcauthlib = "d9d773e" -mcprotocollib = "9b96ebda" # Revert from jitpack after release +mcprotocollib = "c1786e2" # Revert from jitpack after release adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" From 5770c96f48c4713be5786394963b73dc06806232 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sun, 5 May 2024 01:29:37 -0400 Subject: [PATCH 340/344] Indicate support for 1.20.81 --- README.md | 2 +- .../main/java/org/geysermc/geyser/network/GameProtocol.java | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2fdc93fa1..9257af9ac 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,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.20.40 - 1.20.80 and Minecraft Java 1.20.5/1.20.6 +### Currently supporting Minecraft Bedrock 1.20.40 - 1.20.80/81 and Minecraft Java 1.20.5/1.20.6 ## 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/GameProtocol.java b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java index fdaecbb69..f9292671f 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java @@ -50,7 +50,9 @@ public final class GameProtocol { * Default Bedrock codec that should act as a fallback. Should represent the latest available * release of the game that Geyser supports. */ - public static final BedrockCodec DEFAULT_BEDROCK_CODEC = CodecProcessor.processCodec(Bedrock_v671.CODEC); + public static final BedrockCodec DEFAULT_BEDROCK_CODEC = CodecProcessor.processCodec(Bedrock_v671.CODEC.toBuilder() + .minecraftVersion("1.20.81") + .build()); /** * A list of all supported Bedrock versions that can join Geyser @@ -77,7 +79,7 @@ public final class GameProtocol { .minecraftVersion("1.20.70/1.20.73") .build())); SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(DEFAULT_BEDROCK_CODEC.toBuilder() - .minecraftVersion("1.20.80") + .minecraftVersion("1.20.80/1.20.81") .build())); } From 8addcadb71993236730764963e3d776ac007b7a7 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Sun, 5 May 2024 02:24:28 -0400 Subject: [PATCH 341/344] Bump MCPL to increase NBT max depth (#4639) --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b00db373f..b1eb616b3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ protocol-connection = "3.0.0.Beta1-20240411.165033-128" raknet = "1.0.0.CR3-20240416.144209-1" blockstateupdater="1.20.80-20240411.142413-1" mcauthlib = "d9d773e" -mcprotocollib = "c1786e2" # Revert from jitpack after release +mcprotocollib = "1234962" # Revert from jitpack after release adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" From 0a261f1d9d2a6b1aae8880af8811064e7ccbacec Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Mon, 6 May 2024 21:40:32 -0400 Subject: [PATCH 342/344] Update MCPL and MCAuthLib (#4645) * Update MCPL and MCAuthLib * Bump MCPL --- .../java/org/geysermc/geyser/inventory/item/Potion.java | 4 ++-- .../geysermc/geyser/inventory/item/TippedArrowPotion.java | 7 +++++-- .../main/java/org/geysermc/geyser/item/type/ArrowItem.java | 5 +++-- gradle/libs.versions.toml | 4 ++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/Potion.java b/core/src/main/java/org/geysermc/geyser/inventory/item/Potion.java index cf3a37afd..86c19de80 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/item/Potion.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/item/Potion.java @@ -25,11 +25,11 @@ package org.geysermc.geyser.inventory.item; -import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; import lombok.Getter; import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.mcprotocollib.protocol.data.game.item.component.PotionContents; +import java.util.Collections; import java.util.Locale; @Getter @@ -88,7 +88,7 @@ public enum Potion { } public PotionContents toComponent() { - return new PotionContents(this.ordinal(), -1, Int2ObjectMaps.emptyMap()); + return new PotionContents(this.ordinal(), -1, Collections.emptyList()); } public static @Nullable Potion getByJavaId(int javaId) { diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/TippedArrowPotion.java b/core/src/main/java/org/geysermc/geyser/inventory/item/TippedArrowPotion.java index ec6b10ec8..b849e07e2 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/item/TippedArrowPotion.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/item/TippedArrowPotion.java @@ -95,8 +95,11 @@ public enum TippedArrowPotion { this.javaColor = arrowParticleColor.getColor(); } - public static TippedArrowPotion of(int id) { - return VALUES[id]; + public static @Nullable TippedArrowPotion of(int id) { + if (id >= 0 && id < VALUES.length) { + return VALUES[id]; + } + return null; } public static @Nullable TippedArrowPotion getByBedrockId(int bedrockId) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java index f2548e170..84c3b1a39 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.item.type; -import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.inventory.GeyserItemStack; @@ -36,6 +35,8 @@ import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import org.geysermc.mcprotocollib.protocol.data.game.item.component.PotionContents; +import java.util.Collections; + public class ArrowItem extends Item { public ArrowItem(String javaIdentifier, Builder builder) { super(javaIdentifier, builder); @@ -47,7 +48,7 @@ public class ArrowItem extends Item { GeyserItemStack itemStack = super.translateToJava(itemData, mapping, mappings); if (tippedArrowPotion != null) { itemStack = Items.TIPPED_ARROW.newItemStack(itemStack.getAmount(), itemStack.getComponents()); - PotionContents contents = new PotionContents(tippedArrowPotion.ordinal(), -1, Int2ObjectMaps.emptyMap()); + PotionContents contents = new PotionContents(tippedArrowPotion.ordinal(), -1, Collections.emptyList()); itemStack.getOrCreateComponents().put(DataComponentType.POTION_CONTENTS, contents); } return itemStack; diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b1eb616b3..65a5e3a52 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,8 +14,8 @@ protocol = "3.0.0.Beta1-20240411.165033-129" protocol-connection = "3.0.0.Beta1-20240411.165033-128" raknet = "1.0.0.CR3-20240416.144209-1" blockstateupdater="1.20.80-20240411.142413-1" -mcauthlib = "d9d773e" -mcprotocollib = "1234962" # Revert from jitpack after release +mcauthlib = "e5b0bcc" +mcprotocollib = "42ea4a4" # Revert from jitpack after release adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" From cda7a19a08f5b9d62ce492f6fdd87af3bc461e8b Mon Sep 17 00:00:00 2001 From: Eclipse <116838833+eclipseisoffline@users.noreply.github.com> Date: Tue, 7 May 2024 07:16:21 +0100 Subject: [PATCH 343/344] Fix discarding of custom trim patterns/materials (#4642) * Fix discarding of custom trim patterns/materials * Rename `stripNamespace` method to reflect its behaviour --- .../geyser/inventory/recipe/TrimRecipe.java | 12 +++++++---- .../geysermc/geyser/item/type/ArmorItem.java | 20 ++++++++++++++----- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/inventory/recipe/TrimRecipe.java b/core/src/main/java/org/geysermc/geyser/inventory/recipe/TrimRecipe.java index 37eb905a4..9d9dbe0db 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/recipe/TrimRecipe.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/recipe/TrimRecipe.java @@ -47,7 +47,7 @@ public final class TrimRecipe { public static final ItemDescriptorWithCount TEMPLATE = tagDescriptor("minecraft:trim_templates"); public static TrimMaterial readTrimMaterial(GeyserSession session, RegistryEntry entry) { - String key = stripNamespace(entry.getId()); + String key = stripMinecraftNamespace(entry.getId()); // Color is used when hovering over the item // Find the nearest legacy color from the RGB Java gives us to work with @@ -67,7 +67,7 @@ public final class TrimRecipe { } public static TrimPattern readTrimPattern(GeyserSession session, RegistryEntry entry) { - String key = stripNamespace(entry.getId()); + String key = stripMinecraftNamespace(entry.getId()); String itemIdentifier = entry.getData().getString("template_item"); ItemMapping itemMapping = session.getItemMappings().getMapping(itemIdentifier); @@ -79,10 +79,14 @@ public final class TrimRecipe { } // TODO find a good place for a stripNamespace util method - private static String stripNamespace(String identifier) { + private static String stripMinecraftNamespace(String identifier) { int i = identifier.indexOf(':'); if (i >= 0) { - return identifier.substring(i + 1); + String namespace = identifier.substring(0, i); + // Only strip minecraft namespace + if (namespace.equals("minecraft")) { + return identifier.substring(i + 1); + } } return identifier; } diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java index fc0dd3ba4..0a25a8d4f 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java @@ -51,14 +51,15 @@ public class ArmorItem extends Item { ArmorTrim trim = components.get(DataComponentType.TRIM); if (trim != null) { - // discard custom trim patterns/materials to prevent visual glitches on bedrock - if (trim.material().isCustom() || trim.pattern().isCustom()) { - return; - } - TrimMaterial material = session.getRegistryCache().trimMaterials().byId(trim.material().id()); TrimPattern pattern = session.getRegistryCache().trimPatterns().byId(trim.pattern().id()); + // discard custom trim patterns/materials to prevent visual glitches on bedrock + if (!getNamespace(material.getMaterialId()).equals("minecraft") + || !getNamespace(pattern.getPatternId()).equals("minecraft")) { + return; + } + NbtMapBuilder trimBuilder = NbtMap.builder(); // bedrock has an uppercase first letter key, and the value is not namespaced trimBuilder.put("Material", material.getMaterialId()); @@ -71,4 +72,13 @@ public class ArmorItem extends Item { public boolean isValidRepairItem(Item other) { return material.getRepairIngredient() == other; } + + // TODO maybe some kind of namespace util? + private static String getNamespace(String identifier) { + int i = identifier.indexOf(':'); + if (i >= 0) { + return identifier.substring(0, i); + } + return "minecraft"; + } } From 627c2babe9380c64692728581339c0c60869eb6c Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Tue, 7 May 2024 19:26:31 -0400 Subject: [PATCH 344/344] Fix various mob attack animations (#4627) * Fix various mob attack animations * Fix error * Don't set piglin target unless attacking * Fix piglin and hoglin shaking effect * Fix piglin attack animation when switching weapons --- .../geyser/entity/EntityDefinitions.java | 7 ++- .../geyser/entity/type/LivingEntity.java | 9 +++ .../type/living/animal/HoglinEntity.java | 8 +++ .../monster/AbstractSkeletonEntity.java | 14 +++++ .../type/living/monster/BasePiglinEntity.java | 18 ++++++ .../type/living/monster/PiglinEntity.java | 56 ++++++++++++++++++- .../type/living/monster/ZoglinEntity.java | 7 +++ .../type/living/monster/ZombieEntity.java | 5 ++ .../living/monster/raid/PillagerEntity.java | 40 ++++++++++--- .../living/monster/raid/RavagerEntity.java | 54 ++++++++++++++++++ .../living/monster/raid/VindicatorEntity.java | 7 +++ .../inventory/item/StoredItemMappings.java | 2 + .../java/entity/JavaAnimateTranslator.java | 11 ++++ 13 files changed, 226 insertions(+), 12 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/RavagerEntity.java diff --git a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java index 2c5fe7a86..991b95571 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java +++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.entity; +import org.geysermc.geyser.entity.type.living.monster.raid.RavagerEntity; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.MetadataType; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.FloatEntityMetadata; @@ -132,7 +133,7 @@ public final class EntityDefinitions { public static final EntityDefinition POTION; public static final EntityDefinition PUFFERFISH; public static final EntityDefinition RABBIT; - public static final EntityDefinition RAVAGER; + public static final EntityDefinition RAVAGER; public static final EntityDefinition SALMON; public static final EntityDefinition SHEEP; public static final EntityDefinition SHULKER; @@ -745,9 +746,9 @@ public final class EntityDefinitions { .type(EntityType.PILLAGER) .height(1.8f).width(0.6f) .offset(1.62f) - .addTranslator(null) // Charging; doesn't have an equivalent on Bedrock //TODO check + .addTranslator(MetadataType.BOOLEAN, PillagerEntity::setChargingCrossbow) .build(); - RAVAGER = EntityDefinition.inherited(raidParticipantEntityBase.factory(), raidParticipantEntityBase) + RAVAGER = EntityDefinition.inherited(RavagerEntity::new, raidParticipantEntityBase) .type(EntityType.RAVAGER) .height(1.9f).width(1.2f) .build(); diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java index d27fa3cad..499084555 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java @@ -352,6 +352,15 @@ public class LivingEntity extends Entity { session.sendUpstreamPacket(offHandPacket); } + /** + * Called when a SWING_ARM animation packet is received + * + * @return true if an ATTACK_START event should be used instead + */ + public boolean useArmSwingAttack() { + return false; + } + /** * Attributes are properties of an entity that are generally more runtime-based instead of permanent properties. * Movement speed, current attack damage with a weapon, current knockback resistance. diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/HoglinEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/HoglinEntity.java index 46cafad02..74c937417 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/HoglinEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/HoglinEntity.java @@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type.living.animal; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; +import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; @@ -40,6 +41,8 @@ public class HoglinEntity extends AnimalEntity { public HoglinEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); + dirtyMetadata.put(EntityDataTypes.TARGET_EID, session.getPlayerEntity().getGeyserId()); + setFlag(EntityFlag.SHAKING, isShaking()); } public void setImmuneToZombification(BooleanEntityMetadata entityMetadata) { @@ -68,4 +71,9 @@ public class HoglinEntity extends AnimalEntity { protected boolean isEnemy() { return true; } + + @Override + public boolean useArmSwingAttack() { + return true; + } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/AbstractSkeletonEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/AbstractSkeletonEntity.java index 3fbdda245..d08fff06a 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/AbstractSkeletonEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/AbstractSkeletonEntity.java @@ -26,7 +26,9 @@ package org.geysermc.geyser.entity.type.living.monster; import org.cloudburstmc.math.vector.Vector3f; +import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; +import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; @@ -45,5 +47,17 @@ public class AbstractSkeletonEntity extends MonsterEntity { byte xd = entityMetadata.getPrimitiveValue(); // A bit of a loophole so the hands get raised - set the target ID to its own ID dirtyMetadata.put(EntityDataTypes.TARGET_EID, ((xd & 4) == 4) ? geyserId : 0); + + if ((xd & 4) == 4) { + ItemDefinition bow = session.getItemMappings().getStoredItems().bow().getBedrockDefinition(); + setFlag(EntityFlag.FACING_TARGET_TO_RANGE_ATTACK, this.hand.getDefinition() == bow || this.offhand.getDefinition() == bow); + } else { + setFlag(EntityFlag.FACING_TARGET_TO_RANGE_ATTACK, false); + } + } + + @Override + public boolean useArmSwingAttack() { + return true; } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BasePiglinEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BasePiglinEntity.java index 09bd28cd0..9258cd3b8 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BasePiglinEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BasePiglinEntity.java @@ -26,10 +26,13 @@ package org.geysermc.geyser.entity.type.living.monster; import org.cloudburstmc.math.vector.Vector3f; +import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType; import java.util.UUID; @@ -38,6 +41,16 @@ public class BasePiglinEntity extends MonsterEntity { public BasePiglinEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); + // Both TARGET_EID and BLOCK are needed for melee attack animation + dirtyMetadata.put(EntityDataTypes.BLOCK, session.getBlockMappings().getDefinition(1)); + setFlag(EntityFlag.SHAKING, isShaking()); + } + + @Override + public void setMobFlags(ByteEntityMetadata entityMetadata) { + super.setMobFlags(entityMetadata); + byte xd = entityMetadata.getPrimitiveValue(); + dirtyMetadata.put(EntityDataTypes.TARGET_EID, (xd & 4) == 4 ? session.getPlayerEntity().getGeyserId() : 0); } public void setImmuneToZombification(BooleanEntityMetadata entityMetadata) { @@ -50,4 +63,9 @@ public class BasePiglinEntity extends MonsterEntity { protected boolean isShaking() { return (!isImmuneToZombification && !session.getDimensionType().piglinSafe()) || super.isShaking(); } + + @Override + public boolean useArmSwingAttack() { + return true; + } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java index f0f01272f..19b6d8e69 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java @@ -27,16 +27,22 @@ package org.geysermc.geyser.entity.type.living.monster; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3f; +import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; +import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId; +import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; +import org.cloudburstmc.protocol.bedrock.packet.MobEquipmentPacket; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.Items; +import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import java.util.UUID; @@ -55,13 +61,61 @@ public class PiglinEntity extends BasePiglinEntity { } public void setChargingCrossbow(BooleanEntityMetadata entityMetadata) { - setFlag(EntityFlag.CHARGING, entityMetadata.getPrimitiveValue()); + boolean charging = entityMetadata.getPrimitiveValue(); + setFlag(EntityFlag.CHARGING, charging); + dirtyMetadata.put(EntityDataTypes.CHARGE_AMOUNT, charging ? (byte) 64 : (byte) 0); // TODO: gradually increase } public void setDancing(BooleanEntityMetadata entityMetadata) { setFlag(EntityFlag.DANCING, entityMetadata.getPrimitiveValue()); } + @Override + public void setHand(ItemStack stack) { + ItemMapping crossbow = session.getItemMappings().getStoredItems().crossbow(); + boolean toCrossbow = stack != null && stack.getId() == crossbow.getJavaItem().javaId(); + + if (toCrossbow ^ this.hand.getDefinition() == crossbow.getBedrockDefinition()) { // If switching to/from crossbow + dirtyMetadata.put(EntityDataTypes.BLOCK, session.getBlockMappings().getDefinition(toCrossbow ? 0 : 1)); + dirtyMetadata.put(EntityDataTypes.CHARGE_AMOUNT, (byte) 0); + setFlag(EntityFlag.CHARGED, false); + setFlag(EntityFlag.USING_ITEM, false); + updateBedrockMetadata(); + + if (this.hand.isValid()) { + MobEquipmentPacket mobEquipmentPacket = new MobEquipmentPacket(); + mobEquipmentPacket.setRuntimeEntityId(geyserId); + mobEquipmentPacket.setContainerId(ContainerId.INVENTORY); + mobEquipmentPacket.setInventorySlot(0); + mobEquipmentPacket.setHotbarSlot(-1); + mobEquipmentPacket.setItem(ItemData.AIR); + session.sendUpstreamPacket(mobEquipmentPacket); + } + } + + super.setHand(stack); + } + + @Override + public void updateMainHand(GeyserSession session) { + super.updateMainHand(session); + + if (this.hand.getDefinition() == session.getItemMappings().getStoredItems().crossbow().getBedrockDefinition()) { + if (this.hand.getTag() != null && this.hand.getTag().containsKey("chargedItem")) { + dirtyMetadata.put(EntityDataTypes.CHARGE_AMOUNT, Byte.MAX_VALUE); + setFlag(EntityFlag.CHARGING, false); + setFlag(EntityFlag.CHARGED, true); + setFlag(EntityFlag.USING_ITEM, true); + } else if (getFlag(EntityFlag.CHARGED)) { + dirtyMetadata.put(EntityDataTypes.CHARGE_AMOUNT, (byte) 0); + setFlag(EntityFlag.CHARGED, false); + setFlag(EntityFlag.USING_ITEM, false); + } + } + + updateBedrockMetadata(); + } + @Override public void updateOffHand(GeyserSession session) { // Check if the Piglin is holding Gold and set the ADMIRING flag accordingly so its pose updates diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZoglinEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZoglinEntity.java index 7eb950e21..206746fb9 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZoglinEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZoglinEntity.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.entity.type.living.monster; import org.cloudburstmc.math.vector.Vector3f; +import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; @@ -37,6 +38,7 @@ public class ZoglinEntity extends MonsterEntity { public ZoglinEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); + dirtyMetadata.put(EntityDataTypes.TARGET_EID, session.getPlayerEntity().getGeyserId()); } public void setBaby(BooleanEntityMetadata entityMetadata) { @@ -64,4 +66,9 @@ public class ZoglinEntity extends MonsterEntity { protected boolean isEnemy() { return true; } + + @Override + public boolean useArmSwingAttack() { + return true; + } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieEntity.java index b8351089d..b07afd742 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieEntity.java @@ -57,4 +57,9 @@ public class ZombieEntity extends MonsterEntity { protected boolean isShaking() { return convertingToDrowned || super.isShaking(); } + + @Override + public boolean useArmSwingAttack() { + return true; + } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/PillagerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/PillagerEntity.java index 1d2d9115b..fd7448e29 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/PillagerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/PillagerEntity.java @@ -26,10 +26,13 @@ package org.geysermc.geyser.entity.type.living.monster.raid; import org.cloudburstmc.math.vector.Vector3f; +import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; +import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import java.util.UUID; @@ -39,16 +42,22 @@ public class PillagerEntity extends AbstractIllagerEntity { super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); } + public void setChargingCrossbow(BooleanEntityMetadata entityMetadata) { + boolean charging = entityMetadata.getPrimitiveValue(); + setFlag(EntityFlag.CHARGING, charging); + dirtyMetadata.put(EntityDataTypes.CHARGE_AMOUNT, charging ? (byte) 64 : (byte) 0); // TODO: gradually increase + } + @Override - public void updateMainHand(GeyserSession session) { //TODO - checkForCrossbow(); + public void updateMainHand(GeyserSession session) { + updateCrossbow(); super.updateMainHand(session); } @Override public void updateOffHand(GeyserSession session) { - checkForCrossbow(); + updateCrossbow(); super.updateOffHand(session); } @@ -56,12 +65,27 @@ public class PillagerEntity extends AbstractIllagerEntity { /** * Check for a crossbow in either the mainhand or offhand. If one exists, indicate that the pillager should be posing */ - protected void checkForCrossbow() { + protected void updateCrossbow() { ItemMapping crossbow = session.getItemMappings().getStoredItems().crossbow(); - boolean hasCrossbow = this.hand.getDefinition() == crossbow.getBedrockDefinition() - || this.offhand.getDefinition() == crossbow.getBedrockDefinition(); - setFlag(EntityFlag.USING_ITEM, hasCrossbow); - setFlag(EntityFlag.CHARGED, hasCrossbow); + ItemData activeCrossbow = null; + if (this.hand.getDefinition() == crossbow.getBedrockDefinition()) { + activeCrossbow = this.hand; + } else if (this.offhand.getDefinition() == crossbow.getBedrockDefinition()) { + activeCrossbow = this.offhand; + } + + if (activeCrossbow != null) { + if (activeCrossbow.getTag() != null && activeCrossbow.getTag().containsKey("chargedItem")) { + dirtyMetadata.put(EntityDataTypes.CHARGE_AMOUNT, Byte.MAX_VALUE); + setFlag(EntityFlag.CHARGING, false); + setFlag(EntityFlag.CHARGED, true); + setFlag(EntityFlag.USING_ITEM, true); + } else if (getFlag(EntityFlag.CHARGED)) { + dirtyMetadata.put(EntityDataTypes.CHARGE_AMOUNT, (byte) 0); + setFlag(EntityFlag.CHARGED, false); + setFlag(EntityFlag.USING_ITEM, false); + } + } updateBedrockMetadata(); } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/RavagerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/RavagerEntity.java new file mode 100644 index 000000000..6190bae10 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/RavagerEntity.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2019-2024 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.entity.type.living.monster.raid; + +import org.cloudburstmc.math.vector.Vector3f; +import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; +import org.geysermc.geyser.entity.EntityDefinition; +import org.geysermc.geyser.session.GeyserSession; + +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +public class RavagerEntity extends RaidParticipantEntity { + + public RavagerEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { + super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); + } + + @Override + public boolean useArmSwingAttack() { + setFlag(EntityFlag.DELAYED_ATTACK, false); + updateBedrockMetadata(); + + session.scheduleInEventLoop(() -> { + setFlag(EntityFlag.DELAYED_ATTACK, true); + updateBedrockMetadata(); + }, 75, TimeUnit.MILLISECONDS); + + return true; + } +} diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/VindicatorEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/VindicatorEntity.java index 04a58addd..a2557e75a 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/VindicatorEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/VindicatorEntity.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.entity.type.living.monster.raid; import org.cloudburstmc.math.vector.Vector3f; +import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; @@ -37,6 +38,7 @@ public class VindicatorEntity extends AbstractIllagerEntity { public VindicatorEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); + dirtyMetadata.put(EntityDataTypes.TARGET_EID, session.getPlayerEntity().getGeyserId()); } @Override @@ -46,4 +48,9 @@ public class VindicatorEntity extends AbstractIllagerEntity { byte xd = entityMetadata.getPrimitiveValue(); setFlag(EntityFlag.ANGRY, (xd & 4) == 4); } + + @Override + public boolean useArmSwingAttack() { + return true; + } } diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java b/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java index 0305df685..05f6ba6cc 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java @@ -42,6 +42,7 @@ import java.util.Map; public class StoredItemMappings { private final ItemMapping banner; private final ItemMapping barrier; + private final ItemMapping bow; private final ItemMapping compass; private final ItemMapping crossbow; private final ItemMapping egg; @@ -57,6 +58,7 @@ public class StoredItemMappings { public StoredItemMappings(Map itemMappings) { this.banner = load(itemMappings, Items.WHITE_BANNER); // As of 1.17.10, all banners have the same Bedrock ID this.barrier = load(itemMappings, Items.BARRIER); + this.bow = load(itemMappings, Items.BOW); this.compass = load(itemMappings, Items.COMPASS); this.crossbow = load(itemMappings, Items.CROSSBOW); this.egg = load(itemMappings, Items.EGG); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaAnimateTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaAnimateTranslator.java index 8bd4bad10..bf6dfe684 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaAnimateTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaAnimateTranslator.java @@ -26,10 +26,13 @@ package org.geysermc.geyser.translator.protocol.java.entity; import org.cloudburstmc.math.vector.Vector3f; +import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType; import org.cloudburstmc.protocol.bedrock.packet.AnimateEntityPacket; import org.cloudburstmc.protocol.bedrock.packet.AnimatePacket; +import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket; import org.cloudburstmc.protocol.bedrock.packet.SpawnParticleEffectPacket; import org.geysermc.geyser.entity.type.Entity; +import org.geysermc.geyser.entity.type.LivingEntity; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; @@ -57,6 +60,14 @@ public class JavaAnimateTranslator extends PacketTranslator { + if (entity instanceof LivingEntity livingEntity && livingEntity.useArmSwingAttack()) { + EntityEventPacket entityEventPacket = new EntityEventPacket(); + entityEventPacket.setRuntimeEntityId(entity.getGeyserId()); + entityEventPacket.setType(EntityEventType.ATTACK_START); + session.sendUpstreamPacket(entityEventPacket); + return; + } + animatePacket.setAction(AnimatePacket.Action.SWING_ARM); if (entity.getEntityId() == session.getPlayerEntity().getEntityId()) { session.activateArmAnimationTicking();

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%0D8NL_yw6CPSm^x#@W)*%Q+? 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 bpUvdU1E#~Pzl`yiv-g&@bjG3vY-s-jSX!9v literal 0 HcmV?d00001 diff --git a/core/src/main/resources/bedrock/creative_items.1_20_40.json b/core/src/main/resources/bedrock/creative_items.1_20_40.json new file mode 100644 index 000000000..b2c0bfe04 --- /dev/null +++ b/core/src/main/resources/bedrock/creative_items.1_20_40.json @@ -0,0 +1,5787 @@ +{ + "items": [ + { + "id": "minecraft:planks", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBsYW5rcwQJAG5hbWVfaGFzaA+7EGxL5oikAwoAbmV0d29ya19pZE/NqzcKBgBzdGF0ZXMICQB3b29kX3R5cGUDAG9hawADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:planks", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBsYW5rcwQJAG5hbWVfaGFzaA+7EGxL5oikAwoAbmV0d29ya19pZHl/r2YKBgBzdGF0ZXMICQB3b29kX3R5cGUGAHNwcnVjZQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:planks", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBsYW5rcwQJAG5hbWVfaGFzaA+7EGxL5oikAwoAbmV0d29ya19pZL6SoXYKBgBzdGF0ZXMICQB3b29kX3R5cGUFAGJpcmNoAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:planks", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBsYW5rcwQJAG5hbWVfaGFzaA+7EGxL5oikAwoAbmV0d29ya19pZKYD6L0KBgBzdGF0ZXMICQB3b29kX3R5cGUGAGp1bmdsZQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:planks", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBsYW5rcwQJAG5hbWVfaGFzaA+7EGxL5oikAwoAbmV0d29ya19pZJ0zTHYKBgBzdGF0ZXMICQB3b29kX3R5cGUGAGFjYWNpYQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:planks", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBsYW5rcwQJAG5hbWVfaGFzaA+7EGxL5oikAwoAbmV0d29ya19pZOf6hVkKBgBzdGF0ZXMICQB3b29kX3R5cGUIAGRhcmtfb2FrAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:mangrove_planks", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX3BsYW5rcwQJAG5hbWVfaGFzaPvLtcEA0F8xAwoAbmV0d29ya19pZEvnlCYKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:cherry_planks", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9wbGFua3MECQBuYW1lX2hhc2hNIvVh/lVW7gMKAG5ldHdvcmtfaWQTXpRoCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:bamboo_planks", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19wbGFua3MECQBuYW1lX2hhc2gYnjNz7SCCjgMKAG5ldHdvcmtfaWTi8ySSCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:bamboo_mosaic", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19tb3NhaWMECQBuYW1lX2hhc2izSEgiMKOp/AMKAG5ldHdvcmtfaWQZ/p8xCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:crimson_planks", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fcGxhbmtzBAkAbmFtZV9oYXNoJc5IKqNXJnwDCgBuZXR3b3JrX2lkwtJDdQoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:warped_planks", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9wbGFua3MECQBuYW1lX2hhc2g3yGXEWhe6LgMKAG5ldHdvcmtfaWStTABvCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWSE4JosCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCwBjb2JibGVzdG9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWTUvV6XCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEQBtb3NzeV9jb2JibGVzdG9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWT4opb2CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBwBncmFuaXRlCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQAMQTVCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBwBkaW9yaXRlCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQIbDOcCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCABhbmRlc2l0ZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWSZKhusCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCQBzYW5kc3RvbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWSp4zgCCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlDQByZWRfc2FuZHN0b25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRbqVHTCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCwBzdG9uZV9icmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRr0ZT/CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEQBtb3NzeV9zdG9uZV9icmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRnLis3CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBQBicmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQNLzfSCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlDABuZXRoZXJfYnJpY2sIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQ5h0xwCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEAByZWRfbmV0aGVyX2JyaWNrCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWS9J0B2CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCQBlbmRfYnJpY2sIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRPbkJeCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCgBwcmlzbWFyaW5lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:blackstone_wall", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmJsYWNrc3RvbmVfd2FsbAQJAG5hbWVfaGFzaMP8XppUSU1RAwoAbmV0d29ya19pZMbeBBsKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:polished_blackstone_wall", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfd2FsbAQJAG5hbWVfaGFzaP6SwV08YwzAAwoAbmV0d29ya19pZAJLsz8KBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:polished_blackstone_brick_wall", + "block_state_b64": "CgAACAQAbmFtZSgAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfd2FsbAQJAG5hbWVfaGFzaBBIDZbHxiEzAwoAbmV0d29ya19pZEbLV8cKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:cobbled_deepslate_wall", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3dhbGwECQBuYW1lX2hhc2iECY5oKxeT+gMKAG5ldHdvcmtfaWRCnPrFCgYAc3RhdGVzCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:deepslate_tile_wall", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3dhbGwECQBuYW1lX2hhc2jz7N+PeuEXgQMKAG5ldHdvcmtfaWTqw4s4CgYAc3RhdGVzCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:polished_deepslate_wall", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV93YWxsBAkAbmFtZV9oYXNoHxjTdj9pevMDCgBuZXR3b3JrX2lkIvBYYwoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:deepslate_brick_wall", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja193YWxsBAkAbmFtZV9oYXNoEs3EQrjroyEDCgBuZXR3b3JrX2lkwlrCGwoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:mud_brick_wall", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0Om11ZF9icmlja193YWxsBAkAbmFtZV9oYXNov9b98ATpUSwDCgBuZXR3b3JrX2lkH/1WZQoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:oak_fence", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0Om9ha19mZW5jZQQJAG5hbWVfaGFzaGEmid7AaCWRAwoAbmV0d29ya19pZDvPEXcKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:spruce_fence", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnNwcnVjZV9mZW5jZQQJAG5hbWVfaGFzaPQCm+aX1ZQeAwoAbmV0d29ya19pZD1QUEoKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:birch_fence", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmJpcmNoX2ZlbmNlBAkAbmFtZV9oYXNo6CJ2ATpANfgDCgBuZXR3b3JrX2lkmCUV2QoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:jungle_fence", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0Omp1bmdsZV9mZW5jZQQJAG5hbWVfaGFzaOX4cD9uAmsdAwoAbmV0d29ya19pZHz1VxkKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:acacia_fence", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmFjYWNpYV9mZW5jZQQJAG5hbWVfaGFzaGjn+RlKVDH6AwoAbmV0d29ya19pZNVGubwKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:dark_oak_fence", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmRhcmtfb2FrX2ZlbmNlBAkAbmFtZV9oYXNoGPj0gCgM0c0DCgBuZXR3b3JrX2lk2w+gEwoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:mangrove_fence", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hbmdyb3ZlX2ZlbmNlBAkAbmFtZV9oYXNowwAd7tPu9bsDCgBuZXR3b3JrX2lkKEcd0goGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:cherry_fence", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmNoZXJyeV9mZW5jZQQJAG5hbWVfaGFzaFmtUfHfTxcxAwoAbmV0d29ya19pZPCBxAIKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:bamboo_fence", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJhbWJvb19mZW5jZQQJAG5hbWVfaGFzaCKRbxfXsfkiAwoAbmV0d29ya19pZJNXKFcKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:nether_brick_fence", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0Om5ldGhlcl9icmlja19mZW5jZQQJAG5hbWVfaGFzaA6030ngawxcAwoAbmV0d29ya19pZLnjLF4KBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:crimson_fence", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNyaW1zb25fZmVuY2UECQBuYW1lX2hhc2jhUhKv1HGj9AMKAG5ldHdvcmtfaWR3OH3OCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:warped_fence", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OndhcnBlZF9mZW5jZQQJAG5hbWVfaGFzaJfb3/YuKmOWAwoAbmV0d29ya19pZCpaGC8KBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:fence_gate", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmZlbmNlX2dhdGUECQBuYW1lX2hhc2hTxpjEDmRzAwMKAG5ldHdvcmtfaWR+T9kTCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:spruce_fence_gate", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnNwcnVjZV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoanTVB84HRbkDCgBuZXR3b3JrX2lkEnw5egoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:birch_fence_gate", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmJpcmNoX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2jmfPklI8azSwMKAG5ldHdvcmtfaWQL77/BCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:jungle_fence_gate", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0Omp1bmdsZV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNobYVQkfBomIcDCgBuZXR3b3JrX2lkA1zgtgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:acacia_fence_gate", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmFjYWNpYV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoZnrLUx/XSekDCgBuZXR3b3JrX2lkHg/kTgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:dark_oak_fence_gate", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmRhcmtfb2FrX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2j2PTvdJJHcVQMKAG5ldHdvcmtfaWTwjOCeCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:mangrove_fence_gate", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0Om1hbmdyb3ZlX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2i/kOhBKiI/dAMKAG5ldHdvcmtfaWSfweCSCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:cherry_fence_gate", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmNoZXJyeV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoKWLgCk0z+PsDCgBuZXR3b3JrX2lk/9bTZQoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:bamboo_fence_gate", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmJhbWJvb19mZW5jZV9nYXRlBAkAbmFtZV9oYXNopH1JrUgwdIADCgBuZXR3b3JrX2lkzIpPywoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:crimson_fence_gate", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmNyaW1zb25fZmVuY2VfZ2F0ZQQJAG5hbWVfaGFzaHE3Gfd0Z2d2AwoAbmV0d29ya19pZDQzVbEKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQsAaW5fd2FsbF9iaXQAAQgAb3Blbl9iaXQAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:warped_fence_gate", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OndhcnBlZF9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoy0oIBjDIG4kDCgBuZXR3b3JrX2lkkf+/3QoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:normal_stone_stairs", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0Om5vcm1hbF9zdG9uZV9zdGFpcnMECQBuYW1lX2hhc2hAEktZZOkGIwMKAG5ldHdvcmtfaWQeH1ALCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:stone_stairs", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnN0b25lX3N0YWlycwQJAG5hbWVfaGFzaNRjqVC5GRVDAwoAbmV0d29ya19pZDcCv+MKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:mossy_cobblestone_stairs", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0Om1vc3N5X2NvYmJsZXN0b25lX3N0YWlycwQJAG5hbWVfaGFzaMVSTq5z9n1RAwoAbmV0d29ya19pZFIfrhkKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:oak_stairs", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Om9ha19zdGFpcnMECQBuYW1lX2hhc2jk/HFzdXy0FQMKAG5ldHdvcmtfaWQJjyzBCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:spruce_stairs", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9zdGFpcnMECQBuYW1lX2hhc2iznygw7uBPBQMKAG5ldHdvcmtfaWTv+is3CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:birch_stairs", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX3N0YWlycwQJAG5hbWVfaGFzaPfhbL619a3GAwoAbmV0d29ya19pZFyPlHAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:jungle_stairs", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9zdGFpcnMECQBuYW1lX2hhc2jodJsHUbOVxQMKAG5ldHdvcmtfaWR0z5d4CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:acacia_stairs", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9zdGFpcnMECQBuYW1lX2hhc2h3x1NmD43IqQMKAG5ldHdvcmtfaWS7Jwz6CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:dark_oak_stairs", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX3N0YWlycwQJAG5hbWVfaGFzaMfwkbYPbNmAAwoAbmV0d29ya19pZCmBYKAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:mangrove_stairs", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX3N0YWlycwQJAG5hbWVfaGFzaNpUDY+uGMpyAwoAbmV0d29ya19pZChzUAsKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:cherry_stairs", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9zdGFpcnMECQBuYW1lX2hhc2jMtr0v9JY4zwMKAG5ldHdvcmtfaWRQwq31CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:bamboo_stairs", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19zdGFpcnMECQBuYW1lX2hhc2jFOzWL8PalKwMKAG5ldHdvcmtfaWTVPh42CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:bamboo_mosaic_stairs", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmJhbWJvb19tb3NhaWNfc3RhaXJzBAkAbmFtZV9oYXNoNLPiveSHPaoDCgBuZXR3b3JrX2lk44PHjgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:stone_brick_stairs", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnN0b25lX2JyaWNrX3N0YWlycwQJAG5hbWVfaGFzaN6tQViRo5cwAwoAbmV0d29ya19pZDMyMgIKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:mossy_stone_brick_stairs", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0Om1vc3N5X3N0b25lX2JyaWNrX3N0YWlycwQJAG5hbWVfaGFzaIB/Zv5YBPuYAwoAbmV0d29ya19pZANTOsMKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:sandstone_stairs", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnNhbmRzdG9uZV9zdGFpcnMECQBuYW1lX2hhc2hOyA0BoYUOPQMKAG5ldHdvcmtfaWSV/834CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:smooth_sandstone_stairs", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnNtb290aF9zYW5kc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNoB+CuCd8Ruz8DCgBuZXR3b3JrX2lksR+m8QoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:red_sandstone_stairs", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNoPs0LpHPL24YDCgBuZXR3b3JrX2lkLYVt3woGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:smooth_red_sandstone_stairs", + "block_state_b64": "CgAACAQAbmFtZSUAbWluZWNyYWZ0OnNtb290aF9yZWRfc2FuZHN0b25lX3N0YWlycwQJAG5hbWVfaGFzaBvjtQv5pf+MAwoAbmV0d29ya19pZMHNND8KBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:granite_stairs", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmdyYW5pdGVfc3RhaXJzBAkAbmFtZV9oYXNoGzpvtoqKQjgDCgBuZXR3b3JrX2lkPkcB1goGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:polished_granite_stairs", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2dyYW5pdGVfc3RhaXJzBAkAbmFtZV9oYXNo3PvbSfEQklIDCgBuZXR3b3JrX2lkMmEm3AoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:diorite_stairs", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmRpb3JpdGVfc3RhaXJzBAkAbmFtZV9oYXNoi73T8VQuZmcDCgBuZXR3b3JrX2lk6i6nBQoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:polished_diorite_stairs", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2Rpb3JpdGVfc3RhaXJzBAkAbmFtZV9oYXNoFKRJd5Wk5L0DCgBuZXR3b3JrX2lkbt2ioAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:andesite_stairs", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmFuZGVzaXRlX3N0YWlycwQJAG5hbWVfaGFzaO5w2FKBw76EAwoAbmV0d29ya19pZKhXEgUKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:polished_andesite_stairs", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2FuZGVzaXRlX3N0YWlycwQJAG5hbWVfaGFzaNcZZ/zmLInIAwoAbmV0d29ya19pZJTHrlEKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:brick_stairs", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJyaWNrX3N0YWlycwQJAG5hbWVfaGFzaMyt+cRDk5O2AwoAbmV0d29ya19pZNeMh58KBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:nether_brick_stairs", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0Om5ldGhlcl9icmlja19zdGFpcnMECQBuYW1lX2hhc2jRqIoOXgifBAMKAG5ldHdvcmtfaWQDiw5yCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:red_nether_brick_stairs", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnJlZF9uZXRoZXJfYnJpY2tfc3RhaXJzBAkAbmFtZV9oYXNogQvosSbcj7kDCgBuZXR3b3JrX2lkx2IMtAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:end_brick_stairs", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmVuZF9icmlja19zdGFpcnMECQBuYW1lX2hhc2hmlAk+QhsUsQMKAG5ldHdvcmtfaWTN7KFaCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:quartz_stairs", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnF1YXJ0el9zdGFpcnMECQBuYW1lX2hhc2hmvpvOqGi6egMKAG5ldHdvcmtfaWRmUTh7CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:smooth_quartz_stairs", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnNtb290aF9xdWFydHpfc3RhaXJzBAkAbmFtZV9oYXNoNZZ9rX0qZOsDCgBuZXR3b3JrX2lkzsgQyQoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:purpur_stairs", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnB1cl9zdGFpcnMECQBuYW1lX2hhc2ifwDxeezXD7gMKAG5ldHdvcmtfaWTT+rxiCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:prismarine_stairs", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnByaXNtYXJpbmVfc3RhaXJzBAkAbmFtZV9oYXNooTHSZ+IrYtcDCgBuZXR3b3JrX2lkxTJfeAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:dark_prismarine_stairs", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmRhcmtfcHJpc21hcmluZV9zdGFpcnMECQBuYW1lX2hhc2hIciLmam4o4AMKAG5ldHdvcmtfaWTVu7TCCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:prismarine_bricks_stairs", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnByaXNtYXJpbmVfYnJpY2tzX3N0YWlycwQJAG5hbWVfaGFzaNIjq1oBlZMMAwoAbmV0d29ya19pZGEFwLYKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:crimson_stairs", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fc3RhaXJzBAkAbmFtZV9oYXNoZJqIzCBpCq4DCgBuZXR3b3JrX2lktXE00AoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:warped_stairs", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9zdGFpcnMECQBuYW1lX2hhc2hOkY27jLD4RQMKAG5ldHdvcmtfaWQ+E5VrCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:blackstone_stairs", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmJsYWNrc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNokdoUb76p9McDCgBuZXR3b3JrX2lk5fWI5goGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:polished_blackstone_stairs", + "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNolCFtFIE8MmADCgBuZXR3b3JrX2lkGTf7sgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:polished_blackstone_brick_stairs", + "block_state_b64": "CgAACAQAbmFtZSoAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfc3RhaXJzBAkAbmFtZV9oYXNonks6UlfpOmkDCgBuZXR3b3JrX2lkgYeOdAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:cut_copper_stairs", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmN1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoHfoAXYq5G3MDCgBuZXR3b3JrX2lkeetf7woGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:exposed_cut_copper_stairs", + "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcl9zdGFpcnMECQBuYW1lX2hhc2howneQGtZ9cgMKAG5ldHdvcmtfaWSg73zdCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:weathered_cut_copper_stairs", + "block_state_b64": "CgAACAQAbmFtZSUAbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyX3N0YWlycwQJAG5hbWVfaGFzaP+R5loXxrVgAwoAbmV0d29ya19pZOnbRf4KBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:oxidized_cut_copper_stairs", + "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNo6Jeoq5rsPxsDCgBuZXR3b3JrX2lkmRjDnQoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:waxed_cut_copper_stairs", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoh07CQj0/SR8DCgBuZXR3b3JrX2lkmYqoqAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:waxed_exposed_cut_copper_stairs", + "block_state_b64": "CgAACAQAbmFtZSkAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcl9zdGFpcnMECQBuYW1lX2hhc2guVct1ilmxTwMKAG5ldHdvcmtfaWQgCPROCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:waxed_weathered_cut_copper_stairs", + "block_state_b64": "CgAACAQAbmFtZSsAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyX3N0YWlycwQJAG5hbWVfaGFzaPXC8Sz/phCpAwoAbmV0d29ya19pZHlwHVsKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:waxed_oxidized_cut_copper_stairs", + "block_state_b64": "CgAACAQAbmFtZSoAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoaqGdkuhxVZUDCgBuZXR3b3JrX2lkYQXzzgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:cobbled_deepslate_stairs", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3N0YWlycwQJAG5hbWVfaGFzaPIfa+TpyJcIAwoAbmV0d29ya19pZJUvOYIKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:deepslate_tile_stairs", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3N0YWlycwQJAG5hbWVfaGFzaGFRFzB72mN2AwoAbmV0d29ya19pZJEOgIsKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:polished_deepslate_stairs", + "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV9zdGFpcnMECQBuYW1lX2hhc2iNCYxVik9sGAMKAG5ldHdvcmtfaWSRVPnYCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:deepslate_brick_stairs", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja19zdGFpcnMECQBuYW1lX2hhc2hIasOahEf83wMKAG5ldHdvcmtfaWQ1qEDCCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:mud_brick_stairs", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0Om11ZF9icmlja19zdGFpcnMECQBuYW1lX2hhc2gt3qxK1NWajAMKAG5ldHdvcmtfaWSm9N3MCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:wooden_door" + }, + { + "id": "minecraft:spruce_door" + }, + { + "id": "minecraft:birch_door" + }, + { + "id": "minecraft:jungle_door" + }, + { + "id": "minecraft:acacia_door" + }, + { + "id": "minecraft:dark_oak_door" + }, + { + "id": "minecraft:mangrove_door" + }, + { + "id": "minecraft:cherry_door" + }, + { + "id": "minecraft:bamboo_door" + }, + { + "id": "minecraft:iron_door" + }, + { + "id": "minecraft:crimson_door" + }, + { + "id": "minecraft:warped_door" + }, + { + "id": "minecraft:trapdoor", + "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OnRyYXBkb29yBAkAbmFtZV9oYXNotYiAJGtN0xADCgBuZXR3b3JrX2lkyTAWkAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:spruce_trapdoor", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnNwcnVjZV90cmFwZG9vcgQJAG5hbWVfaGFzaOwlfbgBkUW4AwoAbmV0d29ya19pZPHy1K0KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:birch_trapdoor", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmJpcmNoX3RyYXBkb29yBAkAbmFtZV9oYXNoSLtLweOLJ7wDCgBuZXR3b3JrX2lkeJWDfgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:jungle_trapdoor", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Omp1bmdsZV90cmFwZG9vcgQJAG5hbWVfaGFzaDP/TnM9wyCIAwoAbmV0d29ya19pZEy2fJoKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:acacia_trapdoor", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmFjYWNpYV90cmFwZG9vcgQJAG5hbWVfaGFzaMj8xi3vmEKOAwoAbmV0d29ya19pZOHj8E8KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:dark_oak_trapdoor", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmRhcmtfb2FrX3RyYXBkb29yBAkAbmFtZV9oYXNomB2GGJQ2aOMDCgBuZXR3b3JrX2lko5ZHTwoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:mangrove_trapdoor", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0Om1hbmdyb3ZlX3RyYXBkb29yBAkAbmFtZV9oYXNooV3kQsQUUmkDCgBuZXR3b3JrX2lkkF/mxAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:cherry_trapdoor", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmNoZXJyeV90cmFwZG9vcgQJAG5hbWVfaGFzaH/PefpfdHgtAwoAbmV0d29ya19pZOA7eNgKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:bamboo_trapdoor", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmJhbWJvb190cmFwZG9vcgQJAG5hbWVfaGFzaJrEOpsTwtKCAwoAbmV0d29ya19pZLvbPz8KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:iron_trapdoor", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Omlyb25fdHJhcGRvb3IECQBuYW1lX2hhc2gwA+IumsEiGQMKAG5ldHdvcmtfaWTvSVl/CgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAEPAHVwc2lkZV9kb3duX2JpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:crimson_trapdoor", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNyaW1zb25fdHJhcGRvb3IECQBuYW1lX2hhc2jHXufTnwUkYgMKAG5ldHdvcmtfaWQLjMYVCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAEPAHVwc2lkZV9kb3duX2JpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:warped_trapdoor", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OndhcnBlZF90cmFwZG9vcgQJAG5hbWVfaGFzaA20wG/+vkd6AwoAbmV0d29ya19pZHKR/hYKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:iron_bars", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0Omlyb25fYmFycwQJAG5hbWVfaGFzaPuefWSNAe56AwoAbmV0d29ya19pZN2LB5IKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:glass", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmdsYXNzBAkAbmFtZV9oYXNowGJByfWff6gDCgBuZXR3b3JrX2lk0hdLNwoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:white_stained_glass", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OndoaXRlX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2iHubqoMbu9fAMKAG5ldHdvcmtfaWRndBrUCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:light_gray_stained_glass", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaKKa+LrRsHQhAwoAbmV0d29ya19pZEv2giYKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:gray_stained_glass", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmdyYXlfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaIETy7Y/HZREAwoAbmV0d29ya19pZDomVrUKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:black_stained_glass", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmJsYWNrX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2iV6BCwpfDMmwMKAG5ldHdvcmtfaWSV7doJCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:brown_stained_glass", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmJyb3duX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2igsEiq5np8JgMKAG5ldHdvcmtfaWRMzE/lCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:red_stained_glass", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnJlZF9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNoCa2J12/lQoIDCgBuZXR3b3JrX2lk283lWAoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:orange_stained_glass", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0Om9yYW5nZV9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNozgjAuvzhxGsDCgBuZXR3b3JrX2lkW5CkhQoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:yellow_stained_glass", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnllbGxvd19zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNo7EbHMd5WVugDCgBuZXR3b3JrX2lkkdDyXQoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:lime_stained_glass", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmxpbWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaBtZA1nZtwcFAwoAbmV0d29ya19pZDxX85UKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:green_stained_glass", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmdyZWVuX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2h91ptDgbehWwMKAG5ldHdvcmtfaWTlDhnECgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:cyan_stained_glass", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmN5YW5fc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaBkIYQ8nQLqbAwoAbmV0d29ya19pZOL1lHsKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:light_blue_stained_glass", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaLt05n1G0fiSAwoAbmV0d29ya19pZNbwulIKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:blue_stained_glass", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmJsdWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaPhLocSfzduRAwoAbmV0d29ya19pZENsjFwKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:purple_stained_glass", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnB1cnBsZV9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNoJk0DhRO0szUDCgBuZXR3b3JrX2lkD98ZxgoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:magenta_stained_glass", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0Om1hZ2VudGFfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaFEDeFiJj3zSAwoAbmV0d29ya19pZG+iFRoKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:pink_stained_glass", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnBpbmtfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaDijTX87ywxhAwoAbmV0d29ya19pZKdEricKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:tinted_glass", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnRpbnRlZF9nbGFzcwQJAG5hbWVfaGFzaAFZWSamk6KdAwoAbmV0d29ya19pZGSvWX8KBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:glass_pane", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmdsYXNzX3BhbmUECQBuYW1lX2hhc2gRSBHwNMQ4gQMKAG5ldHdvcmtfaWRGwixuCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:white_stained_glass_pane", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OndoaXRlX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaHgxQmgJVtRrAwoAbmV0d29ya19pZBEr/DYKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:light_gray_stained_glass_pane", + "block_state_b64": "CgAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNon0aQw9lNkSEDCgBuZXR3b3JrX2lk9dp5VgoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:gray_stained_glass_pane", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmdyYXlfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNors74IIw+2MMDCgBuZXR3b3JrX2lkmrGO5woGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:black_stained_glass_pane", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OmJsYWNrX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaOK/5ZRRd+M1AwoAbmV0d29ya19pZDv++oQKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:brown_stained_glass_pane", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OmJyb3duX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaLHeGJyRFTIWAwoAbmV0d29ya19pZMz9L0wKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:red_stained_glass_pane", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OnJlZF9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2gGr4x6JheAywMKAG5ldHdvcmtfaWQBjCTmCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:orange_stained_glass_pane", + "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0Om9yYW5nZV9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2hbHxPD2gEbEAMKAG5ldHdvcmtfaWSt/7a5CgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:yellow_stained_glass_pane", + "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0OnllbGxvd19zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2g9tl4aOCyZBwMKAG5ldHdvcmtfaWTXRAS7CgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:lime_stained_glass_pane", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmxpbWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNo3CtUyLwoGegDCgBuZXR3b3JrX2lkYJDnggoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:green_stained_glass_pane", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OmdyZWVuX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaJo6YP7IMy9SAwoAbmV0d29ya19pZHOnixoKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:cyan_stained_glass_pane", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmN5YW5fc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoti97c6QrbLQDCgBuZXR3b3JrX2lkUqFUeQoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:light_blue_stained_glass_pane", + "block_state_b64": "CgAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNovDg/gQle104DCgBuZXR3b3JrX2lkFuy4MQoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:blue_stained_glass_pane", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmJsdWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoGc57tiexbQMDCgBuZXR3b3JrX2lk1eBLUAoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:purple_stained_glass_pane", + "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0OnB1cnBsZV9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2hDJHYdd0FdfQMKAG5ldHdvcmtfaWSNsdK5CgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:magenta_stained_glass_pane", + "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0Om1hZ2VudGFfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNo3pcOw5bs5XoDCgBuZXR3b3JrX2lkVbOR7AoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:pink_stained_glass_pane", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnBpbmtfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoWRhSACMWgswDCgBuZXR3b3JrX2lkIR92xwoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:ladder", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmxhZGRlcgQJAG5hbWVfaGFzaKBhqheJVOz+AwoAbmV0d29ya19pZCgvzlsKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:scaffolding", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnNjYWZmb2xkaW5nBAkAbmFtZV9oYXNoYrkevrqcljwDCgBuZXR3b3JrX2lkD13mlAoGAHN0YXRlcwMJAHN0YWJpbGl0eQAAAAABDwBzdGFiaWxpdHlfY2hlY2sAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWTkNl0JCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQwAc21vb3RoX3N0b25lAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:stone_block_slab4", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkQJoxlgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNAUAc3RvbmUAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWRHh04KCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQsAY29iYmxlc3RvbmUAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkVRZB+woGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhEAbW9zc3lfY29iYmxlc3RvbmUAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:wooden_slab", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lkBaobgAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20ICQB3b29kX3R5cGUDAG9hawADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:wooden_slab", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lkhz9TeQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20ICQB3b29kX3R5cGUGAHNwcnVjZQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:wooden_slab", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lk3HkwowoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20ICQB3b29kX3R5cGUFAGJpcmNoAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:wooden_slab", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lkDIBqVQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20ICQB3b29kX3R5cGUGAGp1bmdsZQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:wooden_slab", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lkL5hFYAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20ICQB3b29kX3R5cGUGAGFjYWNpYQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:wooden_slab", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lkKRUHSQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20ICQB3b29kX3R5cGUIAGRhcmtfb2FrAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:mangrove_slab", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Om1hbmdyb3ZlX3NsYWIECQBuYW1lX2hhc2jYCcmhJPeNMwMKAG5ldHdvcmtfaWQx6U1yCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:cherry_slab", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNoZXJyeV9zbGFiBAkAbmFtZV9oYXNoTt0MmVn/mqoDCgBuZXR3b3JrX2lk2VVsZQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:bamboo_slab", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmJhbWJvb19zbGFiBAkAbmFtZV9oYXNoo1xuFqINeLYDCgBuZXR3b3JrX2lkVC+0twoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:bamboo_mosaic_slab", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmJhbWJvb19tb3NhaWNfc2xhYgQJAG5hbWVfaGFzaNbVRBZ/ChI3AwoAbmV0d29ya19pZOLZHFMKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWQSiInOCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQsAc3RvbmVfYnJpY2sAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:stone_block_slab4", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkoF89tgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNBEAbW9zc3lfc3RvbmVfYnJpY2sAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWSkoAE4CgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQkAc2FuZHN0b25lAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:stone_block_slab4", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkWfF7pgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNA0AY3V0X3NhbmRzdG9uZQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkbKRChAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAc21vb3RoX3NhbmRzdG9uZQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkBlrvqAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMg0AcmVkX3NhbmRzdG9uZQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:stone_block_slab4", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkRWFXuwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNBEAY3V0X3JlZF9zYW5kc3RvbmUAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkom8neQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxQAc21vb3RoX3JlZF9zYW5kc3RvbmUAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkd1ZaWgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMwcAZ3Jhbml0ZQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkISH4iwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxAAcG9saXNoZWRfZ3Jhbml0ZQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkqxEDMwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMwcAZGlvcml0ZQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkSYs86QoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxAAcG9saXNoZWRfZGlvcml0ZQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkq6BU6goGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMwgAYW5kZXNpdGUAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkTSXY8AoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxEAcG9saXNoZWRfYW5kZXNpdGUAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWQiYHKTCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQUAYnJpY2sAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWTk/0LfCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQwAbmV0aGVyX2JyaWNrAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lk/hXQ7AoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAcmVkX25ldGhlcl9icmljawADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:stone_block_slab3", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkYJNxrwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMw8AZW5kX3N0b25lX2JyaWNrAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:stone_block_slab", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWRlj0/sCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQYAcXVhcnR6AAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:stone_block_slab4", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkMae+2goGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNA0Ac21vb3RoX3F1YXJ0egADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lk+kMHGAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMgYAcHVycHVyAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkKOSOMAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAcHJpc21hcmluZV9yb3VnaAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lk8igLCQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMg8AcHJpc21hcmluZV9kYXJrAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:stone_block_slab2", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkSFbyEwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAcHJpc21hcmluZV9icmljawADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:crimson_slab", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmNyaW1zb25fc2xhYgQJAG5hbWVfaGFzaKZ+EfP0ZYOZAwoAbmV0d29ya19pZAxRUWAKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:warped_slab", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OndhcnBlZF9zbGFiBAkAbmFtZV9oYXNo/AT0e/Z9W7UDCgBuZXR3b3JrX2lk1yq11AoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:blackstone_slab", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmJsYWNrc3RvbmVfc2xhYgQJAG5hbWVfaGFzaF/DD4ZUlNgtAwoAbmV0d29ya19pZGy1DjwKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:polished_blackstone_slab", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfc2xhYgQJAG5hbWVfaGFzaDYnuUs86EWfAwoAbmV0d29ya19pZJj2bXIKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:polished_blackstone_brick_slab", + "block_state_b64": "CgAACAQAbmFtZSgAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfc2xhYgQJAG5hbWVfaGFzaKySLqvHc4xXAwoAbmV0d29ya19pZOyWX94KBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:cut_copper_slab", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmN1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaDsNpb2qs4iBAwoAbmV0d29ya19pZOTm2nsKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:exposed_cut_copper_slab", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcl9zbGFiBAkAbmFtZV9oYXNoahQ5OwIQb7kDCgBuZXR3b3JrX2lkrUlZLwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:weathered_cut_copper_slab", + "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyX3NsYWIECQBuYW1lX2hhc2hBIuGIOVVXogMKAG5ldHdvcmtfaWQgnaDiCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:oxidized_cut_copper_slab", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaOptj9ycfpaDAwoAbmV0d29ya19pZMzFSRgKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:waxed_cut_copper_slab", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaAlx6DZOCTHzAwoAbmV0d29ya19pZFRBvDAKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:waxed_exposed_cut_copper_slab", + "block_state_b64": "CgAACAQAbmFtZScAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcl9zbGFiBAkAbmFtZV9oYXNo3KqS5OnhtRIDCgBuZXR3b3JrX2lkHTGcTgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:waxed_weathered_cut_copper_slab", + "block_state_b64": "CgAACAQAbmFtZSkAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyX3NsYWIECQBuYW1lX2hhc2gzZ1oX0HCFtwMKAG5ldHdvcmtfaWSgJR+XCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:waxed_oxidized_cut_copper_slab", + "block_state_b64": "CgAACAQAbmFtZSgAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaMjjTnLu1KcqAwoAbmV0d29ya19pZIxsnFYKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:cobbled_deepslate_slab", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3NsYWIECQBuYW1lX2hhc2gwJIVWK1TM2QMKAG5ldHdvcmtfaWTYAoX5CgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:polished_deepslate_slab", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV9zbGFiBAkAbmFtZV9oYXNoC/Adiz8k6RYDCgBuZXR3b3JrX2lkuFYMAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:deepslate_tile_slab", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3NsYWIECQBuYW1lX2hhc2hPydV6emzIXAMKAG5ldHdvcmtfaWQwlbFCCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:deepslate_brick_slab", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja19zbGFiBAkAbmFtZV9oYXNoSv62V7iw10UDCgBuZXR3b3JrX2lkWMoragoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:mud_brick_slab", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0Om11ZF9icmlja19zbGFiBAkAbmFtZV9oYXNoq/tGBQWkv08DCgBuZXR3b3JrX2lkl4nnMwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:brick_block", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmJyaWNrX2Jsb2NrBAkAbmFtZV9oYXNo5Qc2E005S3oDCgBuZXR3b3JrX2lkqeGWRgoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:chiseled_nether_bricks", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmNoaXNlbGVkX25ldGhlcl9icmlja3MECQBuYW1lX2hhc2g31SBPTcUK1QMKAG5ldHdvcmtfaWS8TJ+TCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:cracked_nether_bricks", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmNyYWNrZWRfbmV0aGVyX2JyaWNrcwQJAG5hbWVfaGFzaAdC6eKzXT5tAwoAbmV0d29ya19pZIUSejwKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:quartz_bricks", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnF1YXJ0el9icmlja3MECQBuYW1lX2hhc2jSZO590dd8sAMKAG5ldHdvcmtfaWSc5xCLCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:stonebrick", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWQ5kni1CgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQcAZGVmYXVsdAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:stonebrick", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWTDw813CgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQUAbW9zc3kAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:stonebrick", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWSTvQGECgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQcAY3JhY2tlZAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:stonebrick", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWQIM0OwCgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQgAY2hpc2VsZWQAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:end_bricks", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmVuZF9icmlja3MECQBuYW1lX2hhc2hIUFfxNLZaFgMKAG5ldHdvcmtfaWQ/vDihCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:prismarine", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnByaXNtYXJpbmUECQBuYW1lX2hhc2jcnQCHi9CspQMKAG5ldHdvcmtfaWSH021WCgYAc3RhdGVzCBUAcHJpc21hcmluZV9ibG9ja190eXBlBgBicmlja3MAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:polished_blackstone_bricks", + "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tzBAkAbmFtZV9oYXNoIHgsgIdzKXcDCgBuZXR3b3JrX2lkUw9b3woGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:cracked_polished_blackstone_bricks", + "block_state_b64": "CgAACAQAbmFtZSwAbWluZWNyYWZ0OmNyYWNrZWRfcG9saXNoZWRfYmxhY2tzdG9uZV9icmlja3MECQBuYW1lX2hhc2jQIO1GQDk80AMKAG5ldHdvcmtfaWQ3UlRYCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:gilded_blackstone", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmdpbGRlZF9ibGFja3N0b25lBAkAbmFtZV9oYXNoNoWt1ocG0HEDCgBuZXR3b3JrX2lktL8gUwoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:chiseled_polished_blackstone", + "block_state_b64": "CgAACAQAbmFtZSYAbWluZWNyYWZ0OmNoaXNlbGVkX3BvbGlzaGVkX2JsYWNrc3RvbmUECQBuYW1lX2hhc2gzFa+kEjCJgAMKAG5ldHdvcmtfaWR2NJX2CgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:deepslate_tiles", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlcwQJAG5hbWVfaGFzaGcLLx3NXAFvAwoAbmV0d29ya19pZI/G/xYKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:cracked_deepslate_tiles", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmNyYWNrZWRfZGVlcHNsYXRlX3RpbGVzBAkAbmFtZV9oYXNo9zWgkFuMM1QDCgBuZXR3b3JrX2lkGwY6OgoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:deepslate_bricks", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja3MECQBuYW1lX2hhc2gucvFmPdZxigMKAG5ldHdvcmtfaWSH4HDPCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:cracked_deepslate_bricks", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OmNyYWNrZWRfZGVlcHNsYXRlX2JyaWNrcwQJAG5hbWVfaGFzaN40aqhh9WqHAwoAbmV0d29ya19pZO9GPBQKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:chiseled_deepslate", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmNoaXNlbGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaEU7/uRG8HSBAwoAbmV0d29ya19pZEqmI0EKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:cobblestone", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvYmJsZXN0b25lBAkAbmFtZV9oYXNoPoK7mGlSUz4DCgBuZXR3b3JrX2lkLm7RZwoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:mossy_cobblestone", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0Om1vc3N5X2NvYmJsZXN0b25lBAkAbmFtZV9oYXNoGJ67FCbkChMDCgBuZXR3b3JrX2lk/pYs1AoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:cobbled_deepslate", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlBAkAbmFtZV9oYXNoLUz9Y/ywmLwDCgBuZXR3b3JrX2lkNwzZ+AoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:smooth_stone", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnNtb290aF9zdG9uZQQJAG5hbWVfaGFzaMwf87/JaTNvAwoAbmV0d29ya19pZLkZICEKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:sandstone", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZB2wApMKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGUHAGRlZmF1bHQAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:sandstone", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZB7E+eQKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGULAGhlaXJvZ2x5cGhzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:sandstone", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZFQnDaEKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGUDAGN1dAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:sandstone", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZPO4A3IKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGUGAHNtb290aAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:red_sandstone", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWRhNYiFCgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlBwBkZWZhdWx0AAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:red_sandstone", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWTqXJr1CgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlCwBoZWlyb2dseXBocwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:red_sandstone", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWTQRGkFCgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlAwBjdXQAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:red_sandstone", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWTvAHWDCgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlBgBzbW9vdGgAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:coal_block", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmNvYWxfYmxvY2sECQBuYW1lX2hhc2jH8QQP3t5PiAMKAG5ldHdvcmtfaWRo+sR+CgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:dried_kelp_block", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmRyaWVkX2tlbHBfYmxvY2sECQBuYW1lX2hhc2iRoucexkrl8wMKAG5ldHdvcmtfaWQQCCrvCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:gold_block", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmdvbGRfYmxvY2sECQBuYW1lX2hhc2iYLshvjtXzFwMKAG5ldHdvcmtfaWTDJGBcCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:iron_block", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Omlyb25fYmxvY2sECQBuYW1lX2hhc2jYINmJQbvV/gMKAG5ldHdvcmtfaWRf7AbICgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:copper_block", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmNvcHBlcl9ibG9jawQJAG5hbWVfaGFzaDVxnehsGaZ1AwoAbmV0d29ya19pZIiUodwKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:exposed_copper", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmV4cG9zZWRfY29wcGVyBAkAbmFtZV9oYXNoQH3Fukmu3CEDCgBuZXR3b3JrX2lk72jFIwoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:weathered_copper", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OndlYXRoZXJlZF9jb3BwZXIECQBuYW1lX2hhc2hJCQXbvobv+gMKAG5ldHdvcmtfaWQwM0lJCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:oxidized_copper", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om94aWRpemVkX2NvcHBlcgQJAG5hbWVfaGFzaMDtJqR0G5Y7AwoAbmV0d29ya19pZGjN8bUKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:waxed_copper", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OndheGVkX2NvcHBlcgQJAG5hbWVfaGFzaPF+FG6Eh5fsAwoAbmV0d29ya19pZIjtz/0KBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:waxed_exposed_copper", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY29wcGVyBAkAbmFtZV9oYXNoig8IOc+SCikDCgBuZXR3b3JrX2lklz8yWQoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:waxed_weathered_copper", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jb3BwZXIECQBuYW1lX2hhc2gjtPq8MOdvKgMKAG5ldHdvcmtfaWSQ9Ln9CgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:waxed_oxidized_copper", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OndheGVkX294aWRpemVkX2NvcHBlcgQJAG5hbWVfaGFzaMaORhsO+LzjAwoAbmV0d29ya19pZJhGfLEKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:cut_copper", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmN1dF9jb3BwZXIECQBuYW1lX2hhc2hAfN3NGax3eAMKAG5ldHdvcmtfaWTnFBtYCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:exposed_cut_copper", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcgQJAG5hbWVfaGFzaA85G3yv/w6pAwoAbmV0d29ya19pZMQhr0QKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:weathered_cut_copper", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyBAkAbmFtZV9oYXNoVgRV0fBaz88DCgBuZXR3b3JrX2lk/0cYugoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:oxidized_cut_copper", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2iP8WmFWOkriwMKAG5ldHdvcmtfaWQPdce7CgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:waxed_cut_copper", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2jumiwOZIqv2AMKAG5ldHdvcmtfaWQvuxx9CgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:waxed_exposed_cut_copper", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcgQJAG5hbWVfaGFzaPE/OfK6IoVMAwoAbmV0d29ya19pZHy5HkcKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:waxed_weathered_cut_copper", + "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyBAkAbmFtZV9oYXNoCA1xDp11bnwDCgBuZXR3b3JrX2lkDyEDVQoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:waxed_oxidized_cut_copper", + "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2i1pZAsZYHLDAMKAG5ldHdvcmtfaWQ/wSkCCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:emerald_block", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmVtZXJhbGRfYmxvY2sECQBuYW1lX2hhc2hK6QunqJznNAMKAG5ldHdvcmtfaWRk5+otCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:diamond_block", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmRpYW1vbmRfYmxvY2sECQBuYW1lX2hhc2iGKrxuvkytFQMKAG5ldHdvcmtfaWQQeQZXCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:lapis_block", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmxhcGlzX2Jsb2NrBAkAbmFtZV9oYXNoDZ44xdb2zVoDCgBuZXR3b3JrX2lktVy0BAoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:raw_iron_block", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnJhd19pcm9uX2Jsb2NrBAkAbmFtZV9oYXNo9XyzNIQXxvwDCgBuZXR3b3JrX2lknms1QAoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:raw_copper_block", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnJhd19jb3BwZXJfYmxvY2sECQBuYW1lX2hhc2hw1KG0TNUGgwMKAG5ldHdvcmtfaWS1vGo/CgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:raw_gold_block", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnJhd19nb2xkX2Jsb2NrBAkAbmFtZV9oYXNo6YuwuLwfOBwDCgBuZXR3b3JrX2lkLiQ5gQoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:quartz_block", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZEupC1AKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQcAZGVmYXVsdAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:quartz_block", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZM97+l0KBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQUAbGluZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:quartz_block", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZCbTfssKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQgAY2hpc2VsZWQICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:quartz_block", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZJss8V0KBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQYAc21vb3RoCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:prismarine", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnByaXNtYXJpbmUECQBuYW1lX2hhc2jcnQCHi9CspQMKAG5ldHdvcmtfaWRFIsoGCgYAc3RhdGVzCBUAcHJpc21hcmluZV9ibG9ja190eXBlBwBkZWZhdWx0AAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:prismarine", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnByaXNtYXJpbmUECQBuYW1lX2hhc2jcnQCHi9CspQMKAG5ldHdvcmtfaWTDNWOvCgYAc3RhdGVzCBUAcHJpc21hcmluZV9ibG9ja190eXBlBABkYXJrAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:slime", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnNsaW1lBAkAbmFtZV9oYXNoHJiEEJx+JlkDCgBuZXR3b3JrX2lkfgfVzAoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:honey_block", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmhvbmV5X2Jsb2NrBAkAbmFtZV9oYXNo9zLYSUlelywDCgBuZXR3b3JrX2lko+dyWgoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:honeycomb_block", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmhvbmV5Y29tYl9ibG9jawQJAG5hbWVfaGFzaASIPuOCYd1oAwoAbmV0d29ya19pZKys4n4KBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:hay_block", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmhheV9ibG9jawQJAG5hbWVfaGFzaIB2VxKxX8EpAwoAbmV0d29ya19pZKuQSloKBgBzdGF0ZXMDCgBkZXByZWNhdGVkAAAAAAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:bone_block", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmJvbmVfYmxvY2sECQBuYW1lX2hhc2i4ZX576W9AWgMKAG5ldHdvcmtfaWTWGacQCgYAc3RhdGVzAwoAZGVwcmVjYXRlZAAAAAAICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:nether_brick", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0Om5ldGhlcl9icmljawQJAG5hbWVfaGFzaMxcRiheU+nXAwoAbmV0d29ya19pZMkmzloKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:red_nether_brick", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnJlZF9uZXRoZXJfYnJpY2sECQBuYW1lX2hhc2j8pRO4LfoECAMKAG5ldHdvcmtfaWRpdF0YCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:netherite_block", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om5ldGhlcml0ZV9ibG9jawQJAG5hbWVfaGFzaMghh6Zib/ZKAwoAbmV0d29ya19pZIz0mq0KBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:lodestone", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmxvZGVzdG9uZQQJAG5hbWVfaGFzaJ2gmHOTlXv8AwoAbmV0d29ya19pZEfgB4wKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:white_wool", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OndoaXRlX3dvb2wECQBuYW1lX2hhc2jRWB7vaIEDiQMKAG5ldHdvcmtfaWSO8paQCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:light_gray_wool", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfd29vbAQJAG5hbWVfaGFzaOpdQ1a2v4b3AwoAbmV0d29ya19pZIqZCYEKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:gray_wool", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmdyYXlfd29vbAQJAG5hbWVfaGFzaLsc1Lp1xdIOAwoAbmV0d29ya19pZFUs+HgKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:black_wool", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmJsYWNrX3dvb2wECQBuYW1lX2hhc2hP2HC6o0X4HAMKAG5ldHdvcmtfaWRUbORcCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:brown_wool", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmJyb3duX3dvb2wECQBuYW1lX2hhc2ig5IW89PrREwMKAG5ldHdvcmtfaWRjT9j8CgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:red_wool", + "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OnJlZF93b29sBAkAbmFtZV9oYXNoY4TBDq+mFgUDCgBuZXR3b3JrX2lktn9lcAoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:orange_wool", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om9yYW5nZV93b29sBAkAbmFtZV9oYXNoFstfrTZfSCgDCgBuZXR3b3JrX2lk+rqywwoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:yellow_wool", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnllbGxvd193b29sBAkAbmFtZV9oYXNoTFyus2RHegcDCgBuZXR3b3JrX2lkkKBhXAoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:lime_wool", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmxpbWVfd29vbAQJAG5hbWVfaGFzaNVnnzKiMxmeAwoAbmV0d29ya19pZG9b32kKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:green_wool", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmdyZWVuX3dvb2wECQBuYW1lX2hhc2i3mElRYHIcSQMKAG5ldHdvcmtfaWSssprwCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:cyan_wool", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmN5YW5fd29vbAQJAG5hbWVfaGFzaBNDfvHn8dqFAwoAbmV0d29ya19pZK0hAbgKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:light_blue_wool", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfd29vbAQJAG5hbWVfaGFzaLWFAUfyxFPNAwoAbmV0d29ya19pZL2oEugKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:blue_wool", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmJsdWVfd29vbAQJAG5hbWVfaGFzaLjHyxxbTWCLAwoAbmV0d29ya19pZPaLdFQKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:purple_wool", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnB1cnBsZV93b29sBAkAbmFtZV9oYXNojvFtqzjAf/4DCgBuZXR3b3JrX2lklqASNQoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:magenta_wool", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0Om1hZ2VudGFfd29vbAQJAG5hbWVfaGFzaGuOHvf+Pd4yAwoAbmV0d29ya19pZI4UoDQKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:pink_wool", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnBpbmtfd29vbAQJAG5hbWVfaGFzaPiVA2pFeoFLAwoAbmV0d29ya19pZOZRO6oKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:white_carpet", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OndoaXRlX2NhcnBldAQJAG5hbWVfaGFzaNeMHTI1fWPXAwoAbmV0d29ya19pZEahDFcKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:light_gray_carpet", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY2FycGV0BAkAbmFtZV9oYXNoHPw6ArBAsP0DCgBuZXR3b3JrX2lkQoAeUAoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:gray_carpet", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmdyYXlfY2FycGV0BAkAbmFtZV9oYXNoZVR0OI+1VRADCgBuZXR3b3JrX2lkETF4WwoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:black_carpet", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJsYWNrX2NhcnBldAQJAG5hbWVfaGFzaOk7LP9NptyhAwoAbmV0d29ya19pZFjmXtIKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:brown_carpet", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJyb3duX2NhcnBldAQJAG5hbWVfaGFzaNaXFyOsAvIvAwoAbmV0d29ya19pZHPjFuoKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:red_carpet", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9jYXJwZXQECQBuYW1lX2hhc2i9eSKBf6SO3wMKAG5ldHdvcmtfaWQuhI/KCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:orange_carpet", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Om9yYW5nZV9jYXJwZXQECQBuYW1lX2hhc2hIUkO4HlAdygMKAG5ldHdvcmtfaWSyKV9OCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:yellow_carpet", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19jYXJwZXQECQBuYW1lX2hhc2hSDKX3scCamwMKAG5ldHdvcmtfaWT8nq+ECgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:lime_carpet", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmxpbWVfY2FycGV0BAkAbmFtZV9oYXNo+6KFOpzsib4DCgBuZXR3b3JrX2lkT+DS4woGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:green_carpet", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmdyZWVuX2NhcnBldAQJAG5hbWVfaGFzaCHPMP9ltqFJAwoAbmV0d29ya19pZBgwAvAKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:cyan_carpet", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmN5YW5fY2FycGV0BAkAbmFtZV9oYXNobXf62dQBJj8DCgBuZXR3b3JrX2lkKVppLgoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:light_blue_carpet", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY2FycGV0BAkAbmFtZV9oYXNo20l4oktdZ3sDCgBuZXR3b3JrX2lkjdeMiwoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:blue_carpet", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmJsdWVfY2FycGV0BAkAbmFtZV9oYXNo3p3lsW0eQwsDCgBuZXR3b3JrX2lkAovdPQoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:purple_carpet", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnBsZV9jYXJwZXQECQBuYW1lX2hhc2jwIA9pW/qp7QMKAG5ldHdvcmtfaWTqJqhjCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:magenta_carpet", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hZ2VudGFfY2FycGV0BAkAbmFtZV9oYXNoFXT36YNNZhMDCgBuZXR3b3JrX2lk+tqsGAoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:pink_carpet", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfY2FycGV0BAkAbmFtZV9oYXNoHll72oqk+OoDCgBuZXR3b3JrX2lkrnBYDwoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:white_concrete_powder", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OndoaXRlX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaFUk9iXVjwV8AwoAbmV0d29ya19pZJPZY8AKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:light_gray_concrete_powder", + "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNo7EUk30hmUtYDCgBuZXR3b3JrX2lkh8jVIwoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:gray_concrete_powder", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmdyYXlfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoW77af6WihdwDCgBuZXR3b3JrX2lkSsqC1woGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:black_concrete_powder", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmJsYWNrX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaAfWYp0xtgcfAwoAbmV0d29ya19pZMWTC8EKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:brown_concrete_powder", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmJyb3duX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaB74EeiLO46XAwoAbmV0d29ya19pZEDHKqwKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:red_concrete_powder", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OnJlZF9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2gjFut6Z/VH1gMKAG5ldHdvcmtfaWSvcmwYCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:orange_concrete_powder", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0Om9yYW5nZV9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2gADDj2IJiw+gMKAG5ldHdvcmtfaWTHph0FCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:yellow_concrete_powder", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OnllbGxvd19jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2iy6qKNn3ob5wMKAG5ldHdvcmtfaWQZAI39CgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:lime_concrete_powder", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmxpbWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNo4dYIPslbXPUDCgBuZXR3b3JrX2lk2O8X0AoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:green_concrete_powder", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmdyZWVuX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaM/c9x2aJh3HAwoAbmV0d29ya19pZA0VfBMKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:cyan_concrete_powder", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmN5YW5fY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNok+xKAe7XXjoDCgBuZXR3b3JrX2lkmkn6uwoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:light_blue_concrete_powder", + "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNogScpIQceyAEDCgBuZXR3b3JrX2lkOmVSbgoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:blue_concrete_powder", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmJsdWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoFp7mmeL86r0DCgBuZXR3b3JrX2lkS3b3RQoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:purple_concrete_powder", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OnB1cnBsZV9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2iYcVU04hoStwMKAG5ldHdvcmtfaWQXimEjCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:magenta_concrete_powder", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0Om1hZ2VudGFfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoy/70q6VPsWgDCgBuZXR3b3JrX2lkf9mxQwoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:pink_concrete_powder", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnBpbmtfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoVikSAf8DwV0DCgBuZXR3b3JrX2lku2MivwoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:white_concrete", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OndoaXRlX2NvbmNyZXRlBAkAbmFtZV9oYXNo6zAp7lsLlvkDCgBuZXR3b3JrX2lk3MAYQAoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:light_gray_concrete", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY29uY3JldGUECQBuYW1lX2hhc2hEtet5wuDIKAMKAG5ldHdvcmtfaWQISs02CgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:gray_concrete", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmdyYXlfY29uY3JldGUECQBuYW1lX2hhc2j92INnb0a83AMKAG5ldHdvcmtfaWQj8RHwCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:black_concrete", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmJsYWNrX2NvbmNyZXRlBAkAbmFtZV9oYXNo2X7NDIQmZ70DCgBuZXR3b3JrX2lk2uiVDQoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:brown_concrete", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmJyb3duX2NvbmNyZXRlBAkAbmFtZV9oYXNoeka02BwXf6oDCgBuZXR3b3JrX2lkYf+xDQoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:red_concrete", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZF9jb25jcmV0ZQQJAG5hbWVfaGFzaPWmNowLGubqAwoAbmV0d29ya19pZKwyx58KBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:orange_concrete", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om9yYW5nZV9jb25jcmV0ZQQJAG5hbWVfaGFzaAgE8XmaAi6+AwoAbmV0d29ya19pZMDQNz8KBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:yellow_concrete", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnllbGxvd19jb25jcmV0ZQQJAG5hbWVfaGFzaE6ONfJPBd0+AwoAbmV0d29ya19pZMarutwKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:lime_concrete", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmxpbWVfY29uY3JldGUECQBuYW1lX2hhc2gnd8JW6wmJcAMKAG5ldHdvcmtfaWTd47aoCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:green_concrete", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmdyZWVuX2NvbmNyZXRlBAkAbmFtZV9oYXNokbFxRKchQZkDCgBuZXR3b3JrX2lkmhZWUgoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:cyan_concrete", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmN5YW5fY29uY3JldGUECQBuYW1lX2hhc2hFRrWJ33qj1wMKAG5ldHdvcmtfaWQbi5b8CgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:light_blue_concrete", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY29uY3JldGUECQBuYW1lX2hhc2gHAe0kl0SE4AMKAG5ldHdvcmtfaWRL/GbSCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:blue_concrete", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmJsdWVfY29uY3JldGUECQBuYW1lX2hhc2hiay301nnj1wMKAG5ldHdvcmtfaWRMvFXNCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:purple_concrete", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnB1cnBsZV9jb25jcmV0ZQQJAG5hbWVfaGFzaHBHflsPIwdXAwoAbmV0d29ya19pZCyKA5gKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:magenta_concrete", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0Om1hZ2VudGFfY29uY3JldGUECQBuYW1lX2hhc2gN7LuB/OvdZAMKAG5ldHdvcmtfaWTc6ZOdCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:pink_concrete", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnBpbmtfY29uY3JldGUECQBuYW1lX2hhc2ii2G5F0u3SOAMKAG5ldHdvcmtfaWSszGgrCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:clay", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OmNsYXkECQBuYW1lX2hhc2j/S6sKXRcpzwMKAG5ldHdvcmtfaWRmsb8nCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:hardened_clay", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmhhcmRlbmVkX2NsYXkECQBuYW1lX2hhc2jrnRwCJ0krJAMKAG5ldHdvcmtfaWRBCOrrCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:white_terracotta", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OndoaXRlX3RlcnJhY290dGEECQBuYW1lX2hhc2j3RSdgmnAIewMKAG5ldHdvcmtfaWSimKw+CgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:light_gray_terracotta", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmxpZ2h0X2dyYXlfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAz1Ri3wIxomAwoAbmV0d29ya19pZH5qgOcKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:gray_terracotta", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmdyYXlfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAXdSLAaNZ9vAwoAbmV0d29ya19pZM1QDV0KBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:black_terracotta", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmJsYWNrX3RlcnJhY290dGEECQBuYW1lX2hhc2jxssdv5vlbpgMKAG5ldHdvcmtfaWRE3Ru/CgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:brown_terracotta", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmJyb3duX3RlcnJhY290dGEECQBuYW1lX2hhc2gG4kPenmOF9gMKAG5ldHdvcmtfaWQ/i0iNCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:red_terracotta", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNo7fX56HXFejEDCgBuZXR3b3JrX2lk8tTF8QoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:orange_terracotta", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0Om9yYW5nZV90ZXJyYWNvdHRhBAkAbmFtZV9oYXNo0Hjmql3sruMDCgBuZXR3b3JrX2lklmqmkAoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:yellow_terracotta", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnllbGxvd190ZXJyYWNvdHRhBAkAbmFtZV9oYXNoqkyKKrmA3VcDCgBuZXR3b3JrX2lkaM/orAoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:lime_terracotta", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmxpbWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaANjADFOF9v7AwoAbmV0d29ya19pZJt0XsgKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:green_terracotta", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmdyZWVuX3RlcnJhY290dGEECQBuYW1lX2hhc2j5Ybq36yYwRQMKAG5ldHdvcmtfaWQ8kGdHCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:cyan_terracotta", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmN5YW5fdGVycmFjb3R0YQQJAG5hbWVfaGFzaN09COzMuHwAAwoAbmV0d29ya19pZIWPCzoKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:light_blue_terracotta", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmxpZ2h0X2JsdWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaOMytez7cOZiAwoAbmV0d29ya19pZFHK1UsKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:blue_terracotta", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmJsdWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaF6inyTK5RpAAwoAbmV0d29ya19pZF5mVZIKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:purple_terracotta", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnB1cnBsZV90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoKF7YG61yTbEDCgBuZXR3b3JrX2lkhtRDlwoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:magenta_terracotta", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0Om1hZ2VudGFfdGVycmFjb3R0YQQJAG5hbWVfaGFzaLWvtpAVtztyAwoAbmV0d29ya19pZN5SoakKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:pink_terracotta", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnBpbmtfdGVycmFjb3R0YQQJAG5hbWVfaGFzaJ7mzvyzSQZTAwoAbmV0d29ya19pZDJWe4YKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:white_glazed_terracotta", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OndoaXRlX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoiVzCdoHAJo0DCgBuZXR3b3JrX2lkIlj9AAoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:silver_glazed_terracotta", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnNpbHZlcl9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAVsA0CnhzA4AwoAbmV0d29ya19pZPnxtJEKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:gray_glazed_terracotta", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmdyYXlfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2jvLZt9u/lF/AMKAG5ldHdvcmtfaWQVU8eFCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:black_glazed_terracotta", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmJsYWNrX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoe8I4xAXbO5UDCgBuZXR3b3JrX2lk2Icb9AoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:brown_glazed_terracotta", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmJyb3duX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoSiNZOobbpjoDCgBuZXR3b3JrX2lkJy0jwgoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:red_glazed_terracotta", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnJlZF9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaBdWFGLmCLFVAwoAbmV0d29ya19pZMYBJSEKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:orange_glazed_terracotta", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0Om9yYW5nZV9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaMyJMrnPr7szAwoAbmV0d29ya19pZN6+7TUKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:yellow_glazed_terracotta", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnllbGxvd19nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaN6NaIhf6m0uAwoAbmV0d29ya19pZKRHXeoKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:lime_glazed_terracotta", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmxpbWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2iF3E68/rB2EAMKAG5ldHdvcmtfaWSP7qQWCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:green_glazed_terracotta", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmdyZWVuX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNow5mo8aQDFboDCgBuZXR3b3JrX2lkoF11kgoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:cyan_glazed_terracotta", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmN5YW5fZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2gnNB+cCFRJhwMKAG5ldHdvcmtfaWT9buMtCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:light_blue_glazed_terracotta", + "block_state_b64": "CgAACAQAbmFtZSYAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2gladnCDBKCigMKAG5ldHdvcmtfaWS5CszFCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:blue_glazed_terracotta", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmJsdWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2giOZK+2nB1igMKAG5ldHdvcmtfaWR+e22CCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:purple_glazed_terracotta", + "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnB1cnBsZV9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaIQU03txeAfHAwoAbmV0d29ya19pZLKbSE4KBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:magenta_glazed_terracotta", + "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0Om1hZ2VudGFfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2i/SNqDJbfjMgMKAG5ldHdvcmtfaWQKf9UvCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:pink_glazed_terracotta", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OnBpbmtfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2hik8DVt4g+twMKAG5ldHdvcmtfaWTKzav2CgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:purpur_block", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnB1cnB1cl9ibG9jawQJAG5hbWVfaGFzaAgLwnUZGlzsAwoAbmV0d29ya19pZLD8ox4KBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQcAZGVmYXVsdAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:purpur_block", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnB1cnB1cl9ibG9jawQJAG5hbWVfaGFzaAgLwnUZGlzsAwoAbmV0d29ya19pZPSAFFsKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQUAbGluZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:packed_mud", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnBhY2tlZF9tdWQECQBuYW1lX2hhc2gHOMa121h4FgMKAG5ldHdvcmtfaWTUb6LyCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:mud_bricks", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Om11ZF9icmlja3MECQBuYW1lX2hhc2iDL/SVl/PewQMKAG5ldHdvcmtfaWSkBjaDCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:nether_wart_block", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0Om5ldGhlcl93YXJ0X2Jsb2NrBAkAbmFtZV9oYXNo9XGS4GNnlV4DCgBuZXR3b3JrX2lkh3apIgoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:warped_wart_block", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OndhcnBlZF93YXJ0X2Jsb2NrBAkAbmFtZV9oYXNo9IqDS9yUPJoDCgBuZXR3b3JrX2lkMpKAbAoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:shroomlight", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnNocm9vbWxpZ2h0BAkAbmFtZV9oYXNoZHCHcHX/HYADCgBuZXR3b3JrX2lkLG2JiwoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:crimson_nylium", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fbnlsaXVtBAkAbmFtZV9oYXNoOr6DJYW2bFYDCgBuZXR3b3JrX2lkuWpRDgoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:warped_nylium", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9ueWxpdW0ECQBuYW1lX2hhc2g0Zf89cfr3rwMKAG5ldHdvcmtfaWSu/kekCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:netherrack", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Om5ldGhlcnJhY2sECQBuYW1lX2hhc2i/r5ZyRsvPyQMKAG5ldHdvcmtfaWTAiTOACgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:basalt", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmJhc2FsdAQJAG5hbWVfaGFzaH+UQO2yWodiAwoAbmV0d29ya19pZBPNSV4KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:polished_basalt", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnBvbGlzaGVkX2Jhc2FsdAQJAG5hbWVfaGFzaMS+L0gMnRcBAwoAbmV0d29ya19pZF+/mHwKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:smooth_basalt", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnNtb290aF9iYXNhbHQECQBuYW1lX2hhc2jKPUdz89kuNAMKAG5ldHdvcmtfaWTkb/oVCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:soul_soil", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnNvdWxfc29pbAQJAG5hbWVfaGFzaC1/87ccutuTAwoAbmV0d29ya19pZKc63SMKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:dirt", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OmRpcnQECQBuYW1lX2hhc2hXp6jnXAe+kQMKAG5ldHdvcmtfaWQmkQtoCgYAc3RhdGVzCAkAZGlydF90eXBlBgBub3JtYWwAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:dirt", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OmRpcnQECQBuYW1lX2hhc2hXp6jnXAe+kQMKAG5ldHdvcmtfaWQId9pLCgYAc3RhdGVzCAkAZGlydF90eXBlBgBjb2Fyc2UAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:farmland", + "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OmZhcm1sYW5kBAkAbmFtZV9oYXNoxyQ5ag7LolADCgBuZXR3b3JrX2lkX618FQoGAHN0YXRlcwMSAG1vaXN0dXJpemVkX2Ftb3VudAAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:grass", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmdyYXNzBAkAbmFtZV9oYXNosppASPWFlsUDCgBuZXR3b3JrX2lkhLLQkQoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:grass_path", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmdyYXNzX3BhdGgECQBuYW1lX2hhc2i0/KZV8Qsy+gMKAG5ldHdvcmtfaWT7CcdzCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:podzol", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBvZHpvbAQJAG5hbWVfaGFzaBzqokRjH4Z1AwoAbmV0d29ya19pZPPS/GUKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:mycelium", + "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0Om15Y2VsaXVtBAkAbmFtZV9oYXNojTN09cKickIDCgBuZXR3b3JrX2lkLNPxXQoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:mud", + "block_state_b64": "CgAACAQAbmFtZQ0AbWluZWNyYWZ0Om11ZAQJAG5hbWVfaGFzaPb/3P+uLy+9AwoAbmV0d29ya19pZPIUlUkKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:stone", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lky8FPmgoGAHN0YXRlcwgKAHN0b25lX3R5cGUFAHN0b25lAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:iron_ore", + "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0Omlyb25fb3JlBAkAbmFtZV9oYXNoS7BYtLnfx3gDCgBuZXR3b3JrX2lk3loneQoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:gold_ore", + "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OmdvbGRfb3JlBAkAbmFtZV9oYXNoC5Y+DUGXLC4DCgBuZXR3b3JrX2lkNhvMfwoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:diamond_ore", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmRpYW1vbmRfb3JlBAkAbmFtZV9oYXNokUOJ2wZZrGQDCgBuZXR3b3JrX2lk/dChVAoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:lapis_ore", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmxhcGlzX29yZQQJAG5hbWVfaGFzaMrmrUrSzb7qAwoAbmV0d29ya19pZMg+qK4KBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:redstone_ore", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZHN0b25lX29yZQQJAG5hbWVfaGFzaFHVnp8Wc4JbAwoAbmV0d29ya19pZKDYvQoKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:coal_ore", + "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OmNvYWxfb3JlBAkAbmFtZV9oYXNo1OjA+Iuy51oDCgBuZXR3b3JrX2lk+R/aKAoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:copper_ore", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmNvcHBlcl9vcmUECQBuYW1lX2hhc2iSZduSntOzOwMKAG5ldHdvcmtfaWQtIuCnCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:emerald_ore", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmVtZXJhbGRfb3JlBAkAbmFtZV9oYXNoJTovr+VgINsDCgBuZXR3b3JrX2lknbkqCgoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:quartz_ore", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnF1YXJ0el9vcmUECQBuYW1lX2hhc2g0yNHLMK9TaQMKAG5ldHdvcmtfaWSzN7nzCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:nether_gold_ore", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om5ldGhlcl9nb2xkX29yZQQJAG5hbWVfaGFzaEJZ7segIBgBAwoAbmV0d29ya19pZNI9pDgKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:ancient_debris", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmFuY2llbnRfZGVicmlzBAkAbmFtZV9oYXNoNrbxMc9AwKcDCgBuZXR3b3JrX2lkrSNjEAoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:deepslate_iron_ore", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9pcm9uX29yZQQJAG5hbWVfaGFzaB/fDL9pgvXXAwoAbmV0d29ya19pZFA0bz4KBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:deepslate_gold_ore", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9nb2xkX29yZQQJAG5hbWVfaGFzaF9G7WYhKFinAwoAbmV0d29ya19pZHQTfBUKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:deepslate_diamond_ore", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV9kaWFtb25kX29yZQQJAG5hbWVfaGFzaEUH5USh+iD3AwoAbmV0d29ya19pZHP6VzAKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:deepslate_lapis_ore", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV9sYXBpc19vcmUECQBuYW1lX2hhc2j+yFxU/KZs1gMKAG5ldHdvcmtfaWRKINzICgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:deepslate_redstone_ore", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmRlZXBzbGF0ZV9yZWRzdG9uZV9vcmUECQBuYW1lX2hhc2iVgM3wWWD6ugMKAG5ldHdvcmtfaWReBdYRCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:deepslate_emerald_ore", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV9lbWVyYWxkX29yZQQJAG5hbWVfaGFzaNlfo5HTwS6wAwoAbmV0d29ya19pZNeie6sKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:deepslate_coal_ore", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9jb2FsX29yZQQJAG5hbWVfaGFzaIjikmcbRrPPAwoAbmV0d29ya19pZD9TiygKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:deepslate_copper_ore", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9jb3BwZXJfb3JlBAkAbmFtZV9oYXNottjV4Ev5LAQDCgBuZXR3b3JrX2lkP23rgQoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:gravel", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmdyYXZlbAQJAG5hbWVfaGFzaOFxz8XJd2r/AwoAbmV0d29ya19pZBpfI1sKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:stone", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lkbtgs0goGAHN0YXRlcwgKAHN0b25lX3R5cGUHAGdyYW5pdGUAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:stone", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lk3sDePAoGAHN0YXRlcwgKAHN0b25lX3R5cGUHAGRpb3JpdGUAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:stone", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lkYG+0YwoGAHN0YXRlcwgKAHN0b25lX3R5cGUIAGFuZGVzaXRlAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:blackstone", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmJsYWNrc3RvbmUECQBuYW1lX2hhc2iMFYziD80D6QMKAG5ldHdvcmtfaWSrUryHCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:deepslate", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmRlZXBzbGF0ZQQJAG5hbWVfaGFzaKX5pAblxz8TAwoAbmV0d29ya19pZOJoQjsKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:stone", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lkREbyhwoGAHN0YXRlcwgKAHN0b25lX3R5cGUOAGdyYW5pdGVfc21vb3RoAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:stone", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lk/EZ3UwoGAHN0YXRlcwgKAHN0b25lX3R5cGUOAGRpb3JpdGVfc21vb3RoAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:stone", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lkmjeVIwoGAHN0YXRlcwgKAHN0b25lX3R5cGUPAGFuZGVzaXRlX3Ntb290aAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:polished_blackstone", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmUECQBuYW1lX2hhc2jT9fHCl6vWQQMKAG5ldHdvcmtfaWR/Ho6oCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:polished_deepslate", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaHC1edoaWF3uAwoAbmV0d29ya19pZCPeQsEKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:sand", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OnNhbmQECQBuYW1lX2hhc2i6lthXXbAyWAMKAG5ldHdvcmtfaWTekU/mCgYAc3RhdGVzCAkAc2FuZF90eXBlBgBub3JtYWwAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:sand", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OnNhbmQECQBuYW1lX2hhc2i6lthXXbAyWAMKAG5ldHdvcmtfaWSTgcqmCgYAc3RhdGVzCAkAc2FuZF90eXBlAwByZWQAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:cactus", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmNhY3R1cwQJAG5hbWVfaGFzaCG9zL0N4wvGAwoAbmV0d29ya19pZDeCERAKBgBzdGF0ZXMDAwBhZ2UAAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:oak_log", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0Om9ha19sb2cECQBuYW1lX2hhc2ho6TS+K7PZFQMKAG5ldHdvcmtfaWQjfjoxCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:stripped_oak_log", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0cmlwcGVkX29ha19sb2cECQBuYW1lX2hhc2h8dqh+OOHU4wMKAG5ldHdvcmtfaWSYKjdrCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:spruce_log", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnNwcnVjZV9sb2cECQBuYW1lX2hhc2hZ03qaLoF3WgMKAG5ldHdvcmtfaWRlFD8eCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:stripped_spruce_log", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX3NwcnVjZV9sb2cECQBuYW1lX2hhc2iNrhKjS5IyrgMKAG5ldHdvcmtfaWRQcEC3CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:birch_log", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmJpcmNoX2xvZwQJAG5hbWVfaGFzaBUzT3NxsZAnAwoAbmV0d29ya19pZBKN3VQKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:stripped_birch_log", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnN0cmlwcGVkX2JpcmNoX2xvZwQJAG5hbWVfaGFzaCFKS4AeuSidAwoAbmV0d29ya19pZN0IONIKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:jungle_log", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Omp1bmdsZV9sb2cECQBuYW1lX2hhc2gkwW0KNulqDgMKAG5ldHdvcmtfaWQaziU/CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:stripped_jungle_log", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2p1bmdsZV9sb2cECQBuYW1lX2hhc2hAwMsgOk02JAMKAG5ldHdvcmtfaWQvls0eCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:acacia_log", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmFjYWNpYV9sb2cECQBuYW1lX2hhc2iV48VpYhjoYQMKAG5ldHdvcmtfaWRxEqe0CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:stripped_acacia_log", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2FjYWNpYV9sb2cECQBuYW1lX2hhc2hJb0lQqnEqlgMKAG5ldHdvcmtfaWRg3IdRCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:dark_oak_log", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRhcmtfb2FrX2xvZwQJAG5hbWVfaGFzaIWfVRd0XUo3AwoAbmV0d29ya19pZPMM7LYKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:stripped_dark_oak_log", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2Rhcmtfb2FrX2xvZwQJAG5hbWVfaGFzaPFTdxRdPwkOAwoAbmV0d29ya19pZDIzenIKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:mangrove_log", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0Om1hbmdyb3ZlX2xvZwQJAG5hbWVfaGFzaHZe6DzPZBobAwoAbmV0d29ya19pZG6DuYkKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:stripped_mangrove_log", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX21hbmdyb3ZlX2xvZwQJAG5hbWVfaGFzaLqIBo4hwA//AwoAbmV0d29ya19pZPtRn7UKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:cherry_log", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmNoZXJyeV9sb2cECQBuYW1lX2hhc2hwFlaioppB1wMKAG5ldHdvcmtfaWS2sdXECgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:stripped_cherry_log", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2NoZXJyeV9sb2cECQBuYW1lX2hhc2i85H6G+WhXaAMKAG5ldHdvcmtfaWRjzoglCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:crimson_stem", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmNyaW1zb25fc3RlbQQJAG5hbWVfaGFzaM0FzfL0UTKZAwoAbmV0d29ya19pZKvzID0KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:stripped_crimson_stem", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2NyaW1zb25fc3RlbQQJAG5hbWVfaGFzaDlA6nood57EAwoAbmV0d29ya19pZHrIqjIKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:warped_stem", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OndhcnBlZF9zdGVtBAkAbmFtZV9oYXNon7cKfPZxdrUDCgBuZXR3b3JrX2lkerWyMwoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:stripped_warped_stem", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX3dhcnBlZF9zdGVtBAkAbmFtZV9oYXNoEw+y0dDPSd8DCgBuZXR3b3JrX2lkIQ9vBAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWSYGFlqCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlAwBvYWsAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWSxnUzvCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlAwBvYWsAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWToyw4RCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlBgBzcHJ1Y2UAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWTL0a3ZCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlBgBzcHJ1Y2UAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWQV99vJCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlBQBiaXJjaAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWQYDJk1CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlBQBiaXJjaAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWSfH48gCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlBgBqdW5nbGUAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWQ44auiCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlBgBqdW5nbGUAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWSogpPYCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlBgBhY2FjaWEAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWSD7hT1CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlBgBhY2FjaWEAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWQagb3gCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlCABkYXJrX29hawADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:wood", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWQdnWU+CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlCABkYXJrX29hawADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:mangrove_wood", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Om1hbmdyb3ZlX3dvb2QECQBuYW1lX2hhc2iXVxG0JG2fVAMKAG5ldHdvcmtfaWTok1JCCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:stripped_mangrove_wood", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OnN0cmlwcGVkX21hbmdyb3ZlX3dvb2QECQBuYW1lX2hhc2h7CkbaBF7/WAMKAG5ldHdvcmtfaWQLAX88CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:cherry_wood", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNoZXJyeV93b29kBAkAbmFtZV9oYXNoAW8srlmpBM8DCgBuZXR3b3JrX2lkEALMfAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AQwAc3RyaXBwZWRfYml0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:stripped_cherry_wood", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX2NoZXJyeV93b29kBAkAbmFtZV9oYXNo/e7KXv+CB38DCgBuZXR3b3JrX2lkg5aVtQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:crimson_hyphae", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25faHlwaGFlBAkAbmFtZV9oYXNouRmKmfSqEWADCgBuZXR3b3JrX2lk+Tm5rQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:stripped_crimson_hyphae", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnN0cmlwcGVkX2NyaW1zb25faHlwaGFlBAkAbmFtZV9oYXNoFffwmABq4LUDCgBuZXR3b3JrX2lkZAlUbgoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:warped_hyphae", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9oeXBoYWUECQBuYW1lX2hhc2hn8plQUr6pmQMKAG5ldHdvcmtfaWRU2AIBCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:stripped_warped_hyphae", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OnN0cmlwcGVkX3dhcnBlZF9oeXBoYWUECQBuYW1lX2hhc2irKq+HYPSgjQMKAG5ldHdvcmtfaWSbrOPDCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:bamboo_block", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJhbWJvb19ibG9jawQJAG5hbWVfaGFzaAbDeur6stIBAwoAbmV0d29ya19pZCJAwn0KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:stripped_bamboo_block", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2JhbWJvb19ibG9jawQJAG5hbWVfaGFzaJpwytpZOZM9AwoAbmV0d29ya19pZKuRbNEKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:leaves", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmxlYXZlcwQJAG5hbWVfaGFzaACPIsusW0mnAwoAbmV0d29ya19pZOmqtzMKBgBzdGF0ZXMIDQBvbGRfbGVhZl90eXBlAwBvYWsBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:leaves", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmxlYXZlcwQJAG5hbWVfaGFzaACPIsusW0mnAwoAbmV0d29ya19pZFMVNEQKBgBzdGF0ZXMIDQBvbGRfbGVhZl90eXBlBgBzcHJ1Y2UBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:leaves", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmxlYXZlcwQJAG5hbWVfaGFzaACPIsusW0mnAwoAbmV0d29ya19pZKCZEm8KBgBzdGF0ZXMIDQBvbGRfbGVhZl90eXBlBQBiaXJjaAEOAHBlcnNpc3RlbnRfYml0AAEKAHVwZGF0ZV9iaXQAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:leaves", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmxlYXZlcwQJAG5hbWVfaGFzaACPIsusW0mnAwoAbmV0d29ya19pZABprGgKBgBzdGF0ZXMIDQBvbGRfbGVhZl90eXBlBgBqdW5nbGUBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:leaves2", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmxlYXZlczIECQBuYW1lX2hhc2gy/bgrncY1ZAMKAG5ldHdvcmtfaWSFh3olCgYAc3RhdGVzCA0AbmV3X2xlYWZfdHlwZQYAYWNhY2lhAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:leaves2", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmxlYXZlczIECQBuYW1lX2hhc2gy/bgrncY1ZAMKAG5ldHdvcmtfaWTvEAyeCgYAc3RhdGVzCA0AbmV3X2xlYWZfdHlwZQgAZGFya19vYWsBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:mangrove_leaves", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX2xlYXZlcwQJAG5hbWVfaGFzaKyI/dWvhEG8AwoAbmV0d29ya19pZPQxCZ8KBgBzdGF0ZXMBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:cherry_leaves", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9sZWF2ZXMECQBuYW1lX2hhc2giTs9ChhYBlQMKAG5ldHdvcmtfaWR8bPpwCgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:azalea_leaves", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmF6YWxlYV9sZWF2ZXMECQBuYW1lX2hhc2iXFhD57wFS7AMKAG5ldHdvcmtfaWTNB/9ECgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:azalea_leaves_flowered", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmF6YWxlYV9sZWF2ZXNfZmxvd2VyZWQECQBuYW1lX2hhc2gs8jxlS/pMrwMKAG5ldHdvcmtfaWQ7W4PyCgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:sapling", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWQmoOEvCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUDAG9hawADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:sapling", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWQO8pAmCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUGAHNwcnVjZQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:sapling", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWQDHhokCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUFAGJpcmNoAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:sapling", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWTdQrcyCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUGAGp1bmdsZQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:sapling", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWRCDffNCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUGAGFjYWNpYQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:sapling", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWR0BRzPCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUIAGRhcmtfb2FrAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:mangrove_propagule", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0Om1hbmdyb3ZlX3Byb3BhZ3VsZQQJAG5hbWVfaGFzaJGeox6hkfLFAwoAbmV0d29ya19pZAIpvpYKBgBzdGF0ZXMBBwBoYW5naW5nAAMPAHByb3BhZ3VsZV9zdGFnZQAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:cherry_sapling", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNoZXJyeV9zYXBsaW5nBAkAbmFtZV9oYXNoGrPpNMf1LtcDCgBuZXR3b3JrX2lkypakXQoGAHN0YXRlcwEHAGFnZV9iaXQAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:bee_nest", + "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OmJlZV9uZXN0BAkAbmFtZV9oYXNo2R2WBxUHEZIDCgBuZXR3b3JrX2lkiXWLEAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAADCwBob25leV9sZXZlbAAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:wheat_seeds" + }, + { + "id": "minecraft:pumpkin_seeds" + }, + { + "id": "minecraft:melon_seeds" + }, + { + "id": "minecraft:beetroot_seeds" + }, + { + "id": "minecraft:torchflower_seeds" + }, + { + "id": "minecraft:pitcher_pod" + }, + { + "id": "minecraft:wheat" + }, + { + "id": "minecraft:beetroot" + }, + { + "id": "minecraft:potato" + }, + { + "id": "minecraft:poisonous_potato" + }, + { + "id": "minecraft:carrot" + }, + { + "id": "minecraft:golden_carrot" + }, + { + "id": "minecraft:apple" + }, + { + "id": "minecraft:golden_apple" + }, + { + "id": "minecraft:enchanted_golden_apple" + }, + { + "id": "minecraft:melon_block", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1lbG9uX2Jsb2NrBAkAbmFtZV9oYXNoXxSm0iYpAx8DCgBuZXR3b3JrX2lkC9rqygoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:melon_slice" + }, + { + "id": "minecraft:glistering_melon_slice" + }, + { + "id": "minecraft:sweet_berries" + }, + { + "id": "minecraft:glow_berries" + }, + { + "id": "minecraft:pumpkin", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnB1bXBraW4ECQBuYW1lX2hhc2gc8A3jaSzWbgMKAG5ldHdvcmtfaWRFGA+xCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:carved_pumpkin", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNhcnZlZF9wdW1wa2luBAkAbmFtZV9oYXNoPu1T0MJuG90DCgBuZXR3b3JrX2lkXNNn5QoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:lit_pumpkin", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmxpdF9wdW1wa2luBAkAbmFtZV9oYXNo7gWtEm2uPL0DCgBuZXR3b3JrX2lki8sU4AoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:honeycomb" + }, + { + "id": "minecraft:tallgrass", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnRhbGxncmFzcwQJAG5hbWVfaGFzaC3PXpAXXYswAwoAbmV0d29ya19pZOh33DMKBgBzdGF0ZXMIDwB0YWxsX2dyYXNzX3R5cGUEAGZlcm4AAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:double_plant", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZMx1sfgKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQQAZmVybgEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:tallgrass", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnRhbGxncmFzcwQJAG5hbWVfaGFzaC3PXpAXXYswAwoAbmV0d29ya19pZErptfIKBgBzdGF0ZXMIDwB0YWxsX2dyYXNzX3R5cGUEAHRhbGwAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:double_plant", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZAbadmIKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQUAZ3Jhc3MBDwB1cHBlcl9ibG9ja19iaXQAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:nether_sprouts" + }, + { + "id": "minecraft:fire_coral", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmZpcmVfY29yYWwECQBuYW1lX2hhc2hOHyyECVQVJwMKAG5ldHdvcmtfaWS9vF0UCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:brain_coral", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmJyYWluX2NvcmFsBAkAbmFtZV9oYXNoRiWlLCwA2ycDCgBuZXR3b3JrX2lkrjAuhgoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:bubble_coral", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJ1YmJsZV9jb3JhbAQJAG5hbWVfaGFzaJz6rWnl+v2qAwoAbmV0d29ya19pZImIWy0KBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:tube_coral", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnR1YmVfY29yYWwECQBuYW1lX2hhc2iYa8oO/tgk7wMKAG5ldHdvcmtfaWRTfND5CgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:horn_coral", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Omhvcm5fY29yYWwECQBuYW1lX2hhc2iZnRHjZbnLPgMKAG5ldHdvcmtfaWR+GGp8CgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:dead_fire_coral", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfZmlyZV9jb3JhbAQJAG5hbWVfaGFzaEPU6tFy/latAwoAbmV0d29ya19pZNMa7V4KBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:dead_brain_coral", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmRlYWRfYnJhaW5fY29yYWwECQBuYW1lX2hhc2j5L6QJCISvzwMKAG5ldHdvcmtfaWQkKzeiCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:dead_bubble_coral", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmRlYWRfYnViYmxlX2NvcmFsBAkAbmFtZV9oYXNoSTOZ/8wpeNYDCgBuZXR3b3JrX2lka6w9DAoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:dead_tube_coral", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfdHViZV9jb3JhbAQJAG5hbWVfaGFzaJGjNWhlaIJeAwoAbmV0d29ya19pZO3Z0ygKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:dead_horn_coral", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfaG9ybl9jb3JhbAQJAG5hbWVfaGFzaJBkz3qt+g2cAwoAbmV0d29ya19pZBAN+eYKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:coral_fan", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZOg7iS4KBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgMAcmVkAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:coral_fan", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZIDj8HMKBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgQAcGluawMTAGNvcmFsX2Zhbl9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:coral_fan", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZLCJP0kKBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgYAcHVycGxlAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:coral_fan", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZFz2ly4KBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgQAYmx1ZQMTAGNvcmFsX2Zhbl9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:coral_fan", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZE4TgnYKBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgYAeWVsbG93AxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:coral_fan_dead", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkdhLQzwoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yAwByZWQDEwBjb3JhbF9mYW5fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:coral_fan_dead", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkSi6srQoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABwaW5rAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:coral_fan_dead", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkGiGSzAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgBwdXJwbGUDEwBjb3JhbF9mYW5fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:coral_fan_dead", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkmvZKOgoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABibHVlAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:coral_fan_dead", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lknLw+4QoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgB5ZWxsb3cDEwBjb3JhbF9mYW5fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:crimson_roots", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNyaW1zb25fcm9vdHMECQBuYW1lX2hhc2j1fWgQLViv5QMKAG5ldHdvcmtfaWRLh5DXCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:warped_roots", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OndhcnBlZF9yb290cwQJAG5hbWVfaGFzaBc3WvbJOLlkAwoAbmV0d29ya19pZNLgDnAKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:yellow_flower", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19mbG93ZXIECQBuYW1lX2hhc2jWbU1pF0OUGAMKAG5ldHdvcmtfaWQgO3hpCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWSqsqQGCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUFAHBvcHB5AAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWTqDajjCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUGAG9yY2hpZAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWT5CjveCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUGAGFsbGl1bQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWTORIBJCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUJAGhvdXN0b25pYQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWTuNhmYCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUJAHR1bGlwX3JlZAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWT0O4nfCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUMAHR1bGlwX29yYW5nZQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWTqkthyCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGULAHR1bGlwX3doaXRlAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWRMbBA7CgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUKAHR1bGlwX3BpbmsAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWRexMAuCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUFAG94ZXllAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWQgs7BECgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUKAGNvcm5mbG93ZXIAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:red_flower", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWRvDuNbCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUSAGxpbHlfb2ZfdGhlX3ZhbGxleQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:double_plant", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZOemRt4KBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQkAc3VuZmxvd2VyAQ8AdXBwZXJfYmxvY2tfYml0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:double_plant", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZOFugoEKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQcAc3lyaW5nYQEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:double_plant", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZN4O+/gKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQQAcm9zZQEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:double_plant", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZI3w4GMKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQcAcGFlb25pYQEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:pitcher_plant", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnBpdGNoZXJfcGxhbnQECQBuYW1lX2hhc2hRJHzsbDH+SQMKAG5ldHdvcmtfaWRnY76VCgYAc3RhdGVzAQ8AdXBwZXJfYmxvY2tfYml0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:pink_petals", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfcGV0YWxzBAkAbmFtZV9oYXNo6DQwN9SwV3QDCgBuZXR3b3JrX2lkNWneGgoGAHN0YXRlcwMGAGdyb3d0aAAAAAAIHABtaW5lY3JhZnQ6Y2FyZGluYWxfZGlyZWN0aW9uBQBzb3V0aAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:wither_rose", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OndpdGhlcl9yb3NlBAkAbmFtZV9oYXNoaSKxl3I516gDCgBuZXR3b3JrX2lkATXLPwoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:torchflower", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnRvcmNoZmxvd2VyBAkAbmFtZV9oYXNoL+mHtElwbqQDCgBuZXR3b3JrX2lkI34O+AoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:white_dye" + }, + { + "id": "minecraft:light_gray_dye" + }, + { + "id": "minecraft:gray_dye" + }, + { + "id": "minecraft:black_dye" + }, + { + "id": "minecraft:brown_dye" + }, + { + "id": "minecraft:red_dye" + }, + { + "id": "minecraft:orange_dye" + }, + { + "id": "minecraft:yellow_dye" + }, + { + "id": "minecraft:lime_dye" + }, + { + "id": "minecraft:green_dye" + }, + { + "id": "minecraft:cyan_dye" + }, + { + "id": "minecraft:light_blue_dye" + }, + { + "id": "minecraft:blue_dye" + }, + { + "id": "minecraft:purple_dye" + }, + { + "id": "minecraft:magenta_dye" + }, + { + "id": "minecraft:pink_dye" + }, + { + "id": "minecraft:ink_sac" + }, + { + "id": "minecraft:glow_ink_sac" + }, + { + "id": "minecraft:cocoa_beans" + }, + { + "id": "minecraft:lapis_lazuli" + }, + { + "id": "minecraft:bone_meal" + }, + { + "id": "minecraft:vine", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OnZpbmUECQBuYW1lX2hhc2j0Sj8/XeXOLAMKAG5ldHdvcmtfaWSUkDtbCgYAc3RhdGVzAxMAdmluZV9kaXJlY3Rpb25fYml0cwAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:weeping_vines", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndlZXBpbmdfdmluZXMECQBuYW1lX2hhc2jrLgLHkQygiwMKAG5ldHdvcmtfaWQ8NHSJCgYAc3RhdGVzAxEAd2VlcGluZ192aW5lc19hZ2UAAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:twisting_vines", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnR3aXN0aW5nX3ZpbmVzBAkAbmFtZV9oYXNoDYR5QgVUQJADCgBuZXR3b3JrX2lk5kYVIQoGAHN0YXRlcwMSAHR3aXN0aW5nX3ZpbmVzX2FnZQAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:waterlily", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OndhdGVybGlseQQJAG5hbWVfaGFzaEHgC4c1SXg0AwoAbmV0d29ya19pZOOerp8KBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:seagrass", + "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OnNlYWdyYXNzBAkAbmFtZV9oYXNoHSBFtoHdWxIDCgBuZXR3b3JrX2lkd3lhEAoGAHN0YXRlcwgOAHNlYV9ncmFzc190eXBlBwBkZWZhdWx0AAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:kelp" + }, + { + "id": "minecraft:deadbush", + "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OmRlYWRidXNoBAkAbmFtZV9oYXNoPFODe4IScnYDCgBuZXR3b3JrX2lkVfnl+goGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:bamboo", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmJhbWJvbwQJAG5hbWVfaGFzaBgpGmyzhedCAwoAbmV0d29ya19pZIZv1nYKBgBzdGF0ZXMBBwBhZ2VfYml0AAgQAGJhbWJvb19sZWFmX3NpemUJAG5vX2xlYXZlcwgWAGJhbWJvb19zdGFsa190aGlja25lc3MEAHRoaW4AAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:snow", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OnNub3cECQBuYW1lX2hhc2gVHr5XXdETWAMKAG5ldHdvcmtfaWQ0zCeHCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:ice", + "block_state_b64": "CgAACAQAbmFtZQ0AbWluZWNyYWZ0OmljZQQJAG5hbWVfaGFzaNF26f+uUT29AwoAbmV0d29ya19pZOUMaQYKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:packed_ice", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnBhY2tlZF9pY2UECQBuYW1lX2hhc2hk4bu123ZrFgMKAG5ldHdvcmtfaWTr/ooaCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:blue_ice", + "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OmJsdWVfaWNlBAkAbmFtZV9oYXNo+EKxYgFhKcgDCgBuZXR3b3JrX2lkxfsA8goGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:snow_layer", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnNub3dfbGF5ZXIECQBuYW1lX2hhc2hXka6atMYUCQMKAG5ldHdvcmtfaWRCrIPcCgYAc3RhdGVzAQsAY292ZXJlZF9iaXQAAwYAaGVpZ2h0AAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:pointed_dripstone", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnBvaW50ZWRfZHJpcHN0b25lBAkAbmFtZV9oYXNoJMISzmHQgt8DCgBuZXR3b3JrX2lkbWrtYgoGAHN0YXRlcwgTAGRyaXBzdG9uZV90aGlja25lc3MDAHRpcAEHAGhhbmdpbmcBAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:dripstone_block", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRyaXBzdG9uZV9ibG9jawQJAG5hbWVfaGFzaIIXnEqY77YsAwoAbmV0d29ya19pZMZi2kwKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:moss_carpet", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vc3NfY2FycGV0BAkAbmFtZV9oYXNo/NEDxRPTshYDCgBuZXR3b3JrX2lkaGG3QwoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:moss_block", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Om1vc3NfYmxvY2sECQBuYW1lX2hhc2iovcsPUYX2tgMKAG5ldHdvcmtfaWT3JSbfCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:dirt_with_roots", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRpcnRfd2l0aF9yb290cwQJAG5hbWVfaGFzaLCNDYPviDCIAwoAbmV0d29ya19pZNCkwzoKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:hanging_roots", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Omhhbmdpbmdfcm9vdHMECQBuYW1lX2hhc2jaXn+Y5UZpDAMKAG5ldHdvcmtfaWRU4c2vCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:mangrove_roots", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hbmdyb3ZlX3Jvb3RzBAkAbmFtZV9oYXNoa786PzQGZ6kDCgBuZXR3b3JrX2lklA0AHgoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:muddy_mangrove_roots", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0Om11ZGR5X21hbmdyb3ZlX3Jvb3RzBAkAbmFtZV9oYXNo9YApdHpo1RkDCgBuZXR3b3JrX2lkH0Oc4woGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:big_dripleaf", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJpZ19kcmlwbGVhZgQJAG5hbWVfaGFzaGBEhXjo6qSdAwoAbmV0d29ya19pZMETsb8KBgBzdGF0ZXMBEQBiaWdfZHJpcGxlYWZfaGVhZAEIEQBiaWdfZHJpcGxlYWZfdGlsdAQAbm9uZQgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:small_dripleaf_block", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnNtYWxsX2RyaXBsZWFmX2Jsb2NrBAkAbmFtZV9oYXNojxRAgXP9uWADCgBuZXR3b3JrX2lkozbVPwoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24EAGVhc3QBDwB1cHBlcl9ibG9ja19iaXQBAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:spore_blossom", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnNwb3JlX2Jsb3Nzb20ECQBuYW1lX2hhc2il3U72Gbco2gMKAG5ldHdvcmtfaWSbbbgcCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:azalea", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmF6YWxlYQQJAG5hbWVfaGFzaNyUl+BW9JrBAwoAbmV0d29ya19pZO/XZtQKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:flowering_azalea", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmZsb3dlcmluZ19hemFsZWEECQBuYW1lX2hhc2ie9r33wz8kiwMKAG5ldHdvcmtfaWQ3ij0VCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:glow_lichen", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Omdsb3dfbGljaGVuBAkAbmFtZV9oYXNobyPUrIYlo44DCgBuZXR3b3JrX2lkCh8lSAoGAHN0YXRlcwMZAG11bHRpX2ZhY2VfZGlyZWN0aW9uX2JpdHM/AAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:amethyst_block", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmFtZXRoeXN0X2Jsb2NrBAkAbmFtZV9oYXNob+JK1iiAthcDCgBuZXR3b3JrX2lk8HtpzgoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:budding_amethyst", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmJ1ZGRpbmdfYW1ldGh5c3QECQBuYW1lX2hhc2gJvAwfI14fxgMKAG5ldHdvcmtfaWTQYqfACgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:amethyst_cluster", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmFtZXRoeXN0X2NsdXN0ZXIECQBuYW1lX2hhc2jK82S88Jgm8wMKAG5ldHdvcmtfaWSCPMPGCgYAc3RhdGVzCBQAbWluZWNyYWZ0OmJsb2NrX2ZhY2UCAHVwAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:large_amethyst_bud", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmxhcmdlX2FtZXRoeXN0X2J1ZAQJAG5hbWVfaGFzaAHhdpWD+sd5AwoAbmV0d29ya19pZKkQxOcKBgBzdGF0ZXMIFABtaW5lY3JhZnQ6YmxvY2tfZmFjZQIAdXAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:medium_amethyst_bud", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0Om1lZGl1bV9hbWV0aHlzdF9idWQECQBuYW1lX2hhc2g5lBGtC0DzZQMKAG5ldHdvcmtfaWSYiP4gCgYAc3RhdGVzCBQAbWluZWNyYWZ0OmJsb2NrX2ZhY2UCAHVwAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:small_amethyst_bud", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnNtYWxsX2FtZXRoeXN0X2J1ZAQJAG5hbWVfaGFzaEnb4+q9PO4YAwoAbmV0d29ya19pZGWzxrQKBgBzdGF0ZXMIFABtaW5lY3JhZnQ6YmxvY2tfZmFjZQIAdXAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:tuff", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OnR1ZmYECQBuYW1lX2hhc2h1Rwc1XYsBGwMKAG5ldHdvcmtfaWRwQGn0CgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:calcite", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmNhbGNpdGUECQBuYW1lX2hhc2ixKLu8ZIdzDQMKAG5ldHdvcmtfaWQlSbJDCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:chicken" + }, + { + "id": "minecraft:porkchop" + }, + { + "id": "minecraft:beef" + }, + { + "id": "minecraft:mutton" + }, + { + "id": "minecraft:rabbit" + }, + { + "id": "minecraft:cod" + }, + { + "id": "minecraft:salmon" + }, + { + "id": "minecraft:tropical_fish" + }, + { + "id": "minecraft:pufferfish" + }, + { + "id": "minecraft:brown_mushroom", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmJyb3duX211c2hyb29tBAkAbmFtZV9oYXNonYw/FO78WDoDCgBuZXR3b3JrX2lkLh1OXAoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:red_mushroom", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZF9tdXNocm9vbQQJAG5hbWVfaGFzaPpzJua7669xAwoAbmV0d29ya19pZCvWPYkKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:crimson_fungus", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fZnVuZ3VzBAkAbmFtZV9oYXNolIcCUuFM2u0DCgBuZXR3b3JrX2lkD2NN0QoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:warped_fungus", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9mdW5ndXMECQBuYW1lX2hhc2gq8bSnRVTAFgMKAG5ldHdvcmtfaWTkwS+rCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:brown_mushroom_block", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkdOMhDAoGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cw4AAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:red_mushroom_block", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnJlZF9tdXNocm9vbV9ibG9jawQJAG5hbWVfaGFzaJTTyJbth9M9AwoAbmV0d29ya19pZM+AyboKBgBzdGF0ZXMDEgBodWdlX211c2hyb29tX2JpdHMOAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:brown_mushroom_block", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkbdt3CAoGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cw8AAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:brown_mushroom_block", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkSrMl9goGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cwAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:egg" + }, + { + "id": "minecraft:sugar_cane" + }, + { + "id": "minecraft:sugar" + }, + { + "id": "minecraft:rotten_flesh" + }, + { + "id": "minecraft:bone" + }, + { + "id": "minecraft:web", + "block_state_b64": "CgAACAQAbmFtZQ0AbWluZWNyYWZ0OndlYgQJAG5hbWVfaGFzaA4GKQCvG4i9AwoAbmV0d29ya19pZApt+jgKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:spider_eye" + }, + { + "id": "minecraft:mob_spawner", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vYl9zcGF3bmVyBAkAbmFtZV9oYXNoNwGrCV/Fkh8DCgBuZXR3b3JrX2lkM1wTmgoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:monster_egg", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkqXH7RgoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGUFAHN0b25lAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:monster_egg", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkeIBb6QoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGULAGNvYmJsZXN0b25lAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:monster_egg", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkDZ2cFQoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGULAHN0b25lX2JyaWNrAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:monster_egg", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkOR/cTAoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGURAG1vc3N5X3N0b25lX2JyaWNrAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:monster_egg", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkqdwlHAoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGUTAGNyYWNrZWRfc3RvbmVfYnJpY2sAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:monster_egg", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkFqqPggoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGUUAGNoaXNlbGVkX3N0b25lX2JyaWNrAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:infested_deepslate", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmluZmVzdGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaICF2VYccxF1AwoAbmV0d29ya19pZDa/624KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:dragon_egg", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmRyYWdvbl9lZ2cECQBuYW1lX2hhc2inMzXrV+/e1wMKAG5ldHdvcmtfaWTgO1yRCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:turtle_egg", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnR1cnRsZV9lZ2cECQBuYW1lX2hhc2iwSRcxOJIJ9gMKAG5ldHdvcmtfaWSIRNUhCgYAc3RhdGVzCA0AY3JhY2tlZF9zdGF0ZQkAbm9fY3JhY2tzCBAAdHVydGxlX2VnZ19jb3VudAcAb25lX2VnZwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:sniffer_egg", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnNuaWZmZXJfZWdnBAkAbmFtZV9oYXNoY1lozc8lPcYDCgBuZXR3b3JrX2lk7yb/2QoGAHN0YXRlcwgNAGNyYWNrZWRfc3RhdGUJAG5vX2NyYWNrcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:frog_spawn", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmZyb2dfc3Bhd24ECQBuYW1lX2hhc2iWmd7idp3ZZwMKAG5ldHdvcmtfaWRFzJudCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:pearlescent_froglight", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnBlYXJsZXNjZW50X2Zyb2dsaWdodAQJAG5hbWVfaGFzaKkcFRyycYGyAwoAbmV0d29ya19pZJqYakAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:verdant_froglight", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnZlcmRhbnRfZnJvZ2xpZ2h0BAkAbmFtZV9oYXNoA+eXuTBohrQDCgBuZXR3b3JrX2lkDIVnsQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:ochre_froglight", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om9jaHJlX2Zyb2dsaWdodAQJAG5hbWVfaGFzaMY59kjPe+c3AwoAbmV0d29ya19pZO2TD50KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:chicken_spawn_egg" + }, + { + "id": "minecraft:bee_spawn_egg" + }, + { + "id": "minecraft:cow_spawn_egg" + }, + { + "id": "minecraft:pig_spawn_egg" + }, + { + "id": "minecraft:sheep_spawn_egg" + }, + { + "id": "minecraft:wolf_spawn_egg" + }, + { + "id": "minecraft:polar_bear_spawn_egg" + }, + { + "id": "minecraft:ocelot_spawn_egg" + }, + { + "id": "minecraft:cat_spawn_egg" + }, + { + "id": "minecraft:mooshroom_spawn_egg" + }, + { + "id": "minecraft:bat_spawn_egg" + }, + { + "id": "minecraft:parrot_spawn_egg" + }, + { + "id": "minecraft:rabbit_spawn_egg" + }, + { + "id": "minecraft:llama_spawn_egg" + }, + { + "id": "minecraft:horse_spawn_egg" + }, + { + "id": "minecraft:donkey_spawn_egg" + }, + { + "id": "minecraft:mule_spawn_egg" + }, + { + "id": "minecraft:skeleton_horse_spawn_egg" + }, + { + "id": "minecraft:zombie_horse_spawn_egg" + }, + { + "id": "minecraft:tropical_fish_spawn_egg" + }, + { + "id": "minecraft:cod_spawn_egg" + }, + { + "id": "minecraft:pufferfish_spawn_egg" + }, + { + "id": "minecraft:salmon_spawn_egg" + }, + { + "id": "minecraft:dolphin_spawn_egg" + }, + { + "id": "minecraft:turtle_spawn_egg" + }, + { + "id": "minecraft:panda_spawn_egg" + }, + { + "id": "minecraft:fox_spawn_egg" + }, + { + "id": "minecraft:creeper_spawn_egg" + }, + { + "id": "minecraft:enderman_spawn_egg" + }, + { + "id": "minecraft:silverfish_spawn_egg" + }, + { + "id": "minecraft:skeleton_spawn_egg" + }, + { + "id": "minecraft:wither_skeleton_spawn_egg" + }, + { + "id": "minecraft:stray_spawn_egg" + }, + { + "id": "minecraft:slime_spawn_egg" + }, + { + "id": "minecraft:spider_spawn_egg" + }, + { + "id": "minecraft:zombie_spawn_egg" + }, + { + "id": "minecraft:zombie_pigman_spawn_egg" + }, + { + "id": "minecraft:husk_spawn_egg" + }, + { + "id": "minecraft:drowned_spawn_egg" + }, + { + "id": "minecraft:squid_spawn_egg" + }, + { + "id": "minecraft:glow_squid_spawn_egg" + }, + { + "id": "minecraft:cave_spider_spawn_egg" + }, + { + "id": "minecraft:witch_spawn_egg" + }, + { + "id": "minecraft:guardian_spawn_egg" + }, + { + "id": "minecraft:elder_guardian_spawn_egg" + }, + { + "id": "minecraft:endermite_spawn_egg" + }, + { + "id": "minecraft:magma_cube_spawn_egg" + }, + { + "id": "minecraft:strider_spawn_egg" + }, + { + "id": "minecraft:hoglin_spawn_egg" + }, + { + "id": "minecraft:piglin_spawn_egg" + }, + { + "id": "minecraft:zoglin_spawn_egg" + }, + { + "id": "minecraft:piglin_brute_spawn_egg" + }, + { + "id": "minecraft:goat_spawn_egg" + }, + { + "id": "minecraft:axolotl_spawn_egg" + }, + { + "id": "minecraft:warden_spawn_egg" + }, + { + "id": "minecraft:allay_spawn_egg" + }, + { + "id": "minecraft:frog_spawn_egg" + }, + { + "id": "minecraft:tadpole_spawn_egg" + }, + { + "id": "minecraft:trader_llama_spawn_egg" + }, + { + "id": "minecraft:camel_spawn_egg" + }, + { + "id": "minecraft:ghast_spawn_egg" + }, + { + "id": "minecraft:blaze_spawn_egg" + }, + { + "id": "minecraft:shulker_spawn_egg" + }, + { + "id": "minecraft:vindicator_spawn_egg" + }, + { + "id": "minecraft:evoker_spawn_egg" + }, + { + "id": "minecraft:vex_spawn_egg" + }, + { + "id": "minecraft:villager_spawn_egg" + }, + { + "id": "minecraft:wandering_trader_spawn_egg" + }, + { + "id": "minecraft:zombie_villager_spawn_egg" + }, + { + "id": "minecraft:phantom_spawn_egg" + }, + { + "id": "minecraft:pillager_spawn_egg" + }, + { + "id": "minecraft:ravager_spawn_egg" + }, + { + "id": "minecraft:iron_golem_spawn_egg" + }, + { + "id": "minecraft:snow_golem_spawn_egg" + }, + { + "id": "minecraft:sniffer_spawn_egg" + }, + { + "id": "minecraft:obsidian", + "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0Om9ic2lkaWFuBAkAbmFtZV9oYXNoiz4qrb8QjyEDCgBuZXR3b3JrX2lkuqnPpQoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:crying_obsidian", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmNyeWluZ19vYnNpZGlhbgQJAG5hbWVfaGFzaKT0JlA7Z1K+AwoAbmV0d29ya19pZCjbPV4KBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:bedrock", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmJlZHJvY2sECQBuYW1lX2hhc2hWfFrh4LVtxwMKAG5ldHdvcmtfaWT7fKz1CgYAc3RhdGVzAQ4AaW5maW5pYnVybl9iaXQAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:soul_sand", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnNvdWxfc2FuZAQJAG5hbWVfaGFzaMaf+bccu+KTAwoAbmV0d29ya19pZBQSHrMKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:magma", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0Om1hZ21hBAkAbmFtZV9oYXNoqyTjKaIsWfYDCgBuZXR3b3JrX2lkyfWAZgoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:nether_wart" + }, + { + "id": "minecraft:end_stone", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmVuZF9zdG9uZQQJAG5hbWVfaGFzaH1J9jA39GJNAwoAbmV0d29ya19pZFeFQ7UKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:chorus_flower", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNob3J1c19mbG93ZXIECQBuYW1lX2hhc2iMpSodli5uawMKAG5ldHdvcmtfaWRnd1ZWCgYAc3RhdGVzAwMAYWdlAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:chorus_plant", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmNob3J1c19wbGFudAQJAG5hbWVfaGFzaJhSrmNGKwaMAwoAbmV0d29ya19pZA3uVqMKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:chorus_fruit" + }, + { + "id": "minecraft:popped_chorus_fruit" + }, + { + "id": "minecraft:sponge", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnNwb25nZQQJAG5hbWVfaGFzaLrd2ScYRDMiAwoAbmV0d29ya19pZF01rO0KBgBzdGF0ZXMICwBzcG9uZ2VfdHlwZQMAZHJ5AAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:sponge", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnNwb25nZQQJAG5hbWVfaGFzaLrd2ScYRDMiAwoAbmV0d29ya19pZPiOc4QKBgBzdGF0ZXMICwBzcG9uZ2VfdHlwZQMAd2V0AAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkGnlaAwoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABibHVlAQgAZGVhZF9iaXQAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkSnHuagoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABwaW5rAQgAZGVhZF9iaXQAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkmkHyegoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgBwdXJwbGUBCABkZWFkX2JpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkdpUDxgoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yAwByZWQBCABkZWFkX2JpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkYNWvYgoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgB5ZWxsb3cBCABkZWFkX2JpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkZSxBQgoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABibHVlAQgAZGVhZF9iaXQBAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lklSTVqQoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABwaW5rAQgAZGVhZF9iaXQBAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lk5fTYuQoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgBwdXJwbGUBCABkZWFkX2JpdAEAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkwUjqBAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yAwByZWQBCABkZWFkX2JpdAEAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:coral_block", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkq4iWoQoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgB5ZWxsb3cBCABkZWFkX2JpdAEAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:sculk", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnNjdWxrBAkAbmFtZV9oYXNo2Lq7T5yQF8kDCgBuZXR3b3JrX2lkyqUPPgoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:sculk_vein", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnNjdWxrX3ZlaW4ECQBuYW1lX2hhc2gJUdhVooV4zwMKAG5ldHdvcmtfaWSUfn1XCgYAc3RhdGVzAxkAbXVsdGlfZmFjZV9kaXJlY3Rpb25fYml0cwAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:sculk_catalyst", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnNjdWxrX2NhdGFseXN0BAkAbmFtZV9oYXNo+gCpbrCHST4DCgBuZXR3b3JrX2lkMJ2n/woGAHN0YXRlcwEFAGJsb29tAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:sculk_shrieker", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnNjdWxrX3Nocmlla2VyBAkAbmFtZV9oYXNo5OXtyObniQ4DCgBuZXR3b3JrX2lkxapoNAoGAHN0YXRlcwEGAGFjdGl2ZQABCgBjYW5fc3VtbW9uAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:sculk_sensor", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnNjdWxrX3NlbnNvcgQJAG5hbWVfaGFzaCkmHreeTgNnAwoAbmV0d29ya19pZLj2WPcKBgBzdGF0ZXMDEgBzY3Vsa19zZW5zb3JfcGhhc2UAAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:calibrated_sculk_sensor", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmNhbGlicmF0ZWRfc2N1bGtfc2Vuc29yBAkAbmFtZV9oYXNoffAcXXN/iJUDCgBuZXR3b3JrX2lkwOx3QQoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAxIAc2N1bGtfc2Vuc29yX3BoYXNlAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:reinforced_deepslate", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnJlaW5mb3JjZWRfZGVlcHNsYXRlBAkAbmFtZV9oYXNoldDmj91EapQDCgBuZXR3b3JrX2lkHIt+aQoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:leather_helmet" + }, + { + "id": "minecraft:chainmail_helmet" + }, + { + "id": "minecraft:iron_helmet" + }, + { + "id": "minecraft:golden_helmet" + }, + { + "id": "minecraft:diamond_helmet" + }, + { + "id": "minecraft:netherite_helmet" + }, + { + "id": "minecraft:leather_chestplate" + }, + { + "id": "minecraft:chainmail_chestplate" + }, + { + "id": "minecraft:iron_chestplate" + }, + { + "id": "minecraft:golden_chestplate" + }, + { + "id": "minecraft:diamond_chestplate" + }, + { + "id": "minecraft:netherite_chestplate" + }, + { + "id": "minecraft:leather_leggings" + }, + { + "id": "minecraft:chainmail_leggings" + }, + { + "id": "minecraft:iron_leggings" + }, + { + "id": "minecraft:golden_leggings" + }, + { + "id": "minecraft:diamond_leggings" + }, + { + "id": "minecraft:netherite_leggings" + }, + { + "id": "minecraft:leather_boots" + }, + { + "id": "minecraft:chainmail_boots" + }, + { + "id": "minecraft:iron_boots" + }, + { + "id": "minecraft:golden_boots" + }, + { + "id": "minecraft:diamond_boots" + }, + { + "id": "minecraft:netherite_boots" + }, + { + "id": "minecraft:wooden_sword" + }, + { + "id": "minecraft:stone_sword" + }, + { + "id": "minecraft:iron_sword" + }, + { + "id": "minecraft:golden_sword" + }, + { + "id": "minecraft:diamond_sword" + }, + { + "id": "minecraft:netherite_sword" + }, + { + "id": "minecraft:wooden_axe" + }, + { + "id": "minecraft:stone_axe" + }, + { + "id": "minecraft:iron_axe" + }, + { + "id": "minecraft:golden_axe" + }, + { + "id": "minecraft:diamond_axe" + }, + { + "id": "minecraft:netherite_axe" + }, + { + "id": "minecraft:wooden_pickaxe" + }, + { + "id": "minecraft:stone_pickaxe" + }, + { + "id": "minecraft:iron_pickaxe" + }, + { + "id": "minecraft:golden_pickaxe" + }, + { + "id": "minecraft:diamond_pickaxe" + }, + { + "id": "minecraft:netherite_pickaxe" + }, + { + "id": "minecraft:wooden_shovel" + }, + { + "id": "minecraft:stone_shovel" + }, + { + "id": "minecraft:iron_shovel" + }, + { + "id": "minecraft:golden_shovel" + }, + { + "id": "minecraft:diamond_shovel" + }, + { + "id": "minecraft:netherite_shovel" + }, + { + "id": "minecraft:wooden_hoe" + }, + { + "id": "minecraft:stone_hoe" + }, + { + "id": "minecraft:iron_hoe" + }, + { + "id": "minecraft:golden_hoe" + }, + { + "id": "minecraft:diamond_hoe" + }, + { + "id": "minecraft:netherite_hoe" + }, + { + "id": "minecraft:bow" + }, + { + "id": "minecraft:crossbow" + }, + { + "id": "minecraft:arrow" + }, + { + "id": "minecraft:arrow", + "damage": 6 + }, + { + "id": "minecraft:arrow", + "damage": 7 + }, + { + "id": "minecraft:arrow", + "damage": 8 + }, + { + "id": "minecraft:arrow", + "damage": 9 + }, + { + "id": "minecraft:arrow", + "damage": 10 + }, + { + "id": "minecraft:arrow", + "damage": 11 + }, + { + "id": "minecraft:arrow", + "damage": 12 + }, + { + "id": "minecraft:arrow", + "damage": 13 + }, + { + "id": "minecraft:arrow", + "damage": 14 + }, + { + "id": "minecraft:arrow", + "damage": 15 + }, + { + "id": "minecraft:arrow", + "damage": 16 + }, + { + "id": "minecraft:arrow", + "damage": 17 + }, + { + "id": "minecraft:arrow", + "damage": 18 + }, + { + "id": "minecraft:arrow", + "damage": 19 + }, + { + "id": "minecraft:arrow", + "damage": 20 + }, + { + "id": "minecraft:arrow", + "damage": 21 + }, + { + "id": "minecraft:arrow", + "damage": 22 + }, + { + "id": "minecraft:arrow", + "damage": 23 + }, + { + "id": "minecraft:arrow", + "damage": 24 + }, + { + "id": "minecraft:arrow", + "damage": 25 + }, + { + "id": "minecraft:arrow", + "damage": 26 + }, + { + "id": "minecraft:arrow", + "damage": 27 + }, + { + "id": "minecraft:arrow", + "damage": 28 + }, + { + "id": "minecraft:arrow", + "damage": 29 + }, + { + "id": "minecraft:arrow", + "damage": 30 + }, + { + "id": "minecraft:arrow", + "damage": 31 + }, + { + "id": "minecraft:arrow", + "damage": 32 + }, + { + "id": "minecraft:arrow", + "damage": 33 + }, + { + "id": "minecraft:arrow", + "damage": 34 + }, + { + "id": "minecraft:arrow", + "damage": 35 + }, + { + "id": "minecraft:arrow", + "damage": 36 + }, + { + "id": "minecraft:arrow", + "damage": 37 + }, + { + "id": "minecraft:arrow", + "damage": 38 + }, + { + "id": "minecraft:arrow", + "damage": 39 + }, + { + "id": "minecraft:arrow", + "damage": 40 + }, + { + "id": "minecraft:arrow", + "damage": 41 + }, + { + "id": "minecraft:arrow", + "damage": 42 + }, + { + "id": "minecraft:arrow", + "damage": 43 + }, + { + "id": "minecraft:shield" + }, + { + "id": "minecraft:cooked_chicken" + }, + { + "id": "minecraft:cooked_porkchop" + }, + { + "id": "minecraft:cooked_beef" + }, + { + "id": "minecraft:cooked_mutton" + }, + { + "id": "minecraft:cooked_rabbit" + }, + { + "id": "minecraft:cooked_cod" + }, + { + "id": "minecraft:cooked_salmon" + }, + { + "id": "minecraft:bread" + }, + { + "id": "minecraft:mushroom_stew" + }, + { + "id": "minecraft:beetroot_soup" + }, + { + "id": "minecraft:rabbit_stew" + }, + { + "id": "minecraft:baked_potato" + }, + { + "id": "minecraft:cookie" + }, + { + "id": "minecraft:pumpkin_pie" + }, + { + "id": "minecraft:cake" + }, + { + "id": "minecraft:dried_kelp" + }, + { + "id": "minecraft:fishing_rod" + }, + { + "id": "minecraft:carrot_on_a_stick" + }, + { + "id": "minecraft:warped_fungus_on_a_stick" + }, + { + "id": "minecraft:snowball" + }, + { + "id": "minecraft:shears" + }, + { + "id": "minecraft:flint_and_steel" + }, + { + "id": "minecraft:lead" + }, + { + "id": "minecraft:clock" + }, + { + "id": "minecraft:compass" + }, + { + "id": "minecraft:recovery_compass" + }, + { + "id": "minecraft:goat_horn" + }, + { + "id": "minecraft:goat_horn", + "damage": 1 + }, + { + "id": "minecraft:goat_horn", + "damage": 2 + }, + { + "id": "minecraft:goat_horn", + "damage": 3 + }, + { + "id": "minecraft:goat_horn", + "damage": 4 + }, + { + "id": "minecraft:goat_horn", + "damage": 5 + }, + { + "id": "minecraft:goat_horn", + "damage": 6 + }, + { + "id": "minecraft:goat_horn", + "damage": 7 + }, + { + "id": "minecraft:empty_map" + }, + { + "id": "minecraft:empty_map", + "damage": 2 + }, + { + "id": "minecraft:saddle" + }, + { + "id": "minecraft:leather_horse_armor" + }, + { + "id": "minecraft:iron_horse_armor" + }, + { + "id": "minecraft:golden_horse_armor" + }, + { + "id": "minecraft:diamond_horse_armor" + }, + { + "id": "minecraft:trident" + }, + { + "id": "minecraft:turtle_helmet" + }, + { + "id": "minecraft:elytra" + }, + { + "id": "minecraft:totem_of_undying" + }, + { + "id": "minecraft:glass_bottle" + }, + { + "id": "minecraft:experience_bottle" + }, + { + "id": "minecraft:potion" + }, + { + "id": "minecraft:potion", + "damage": 1 + }, + { + "id": "minecraft:potion", + "damage": 2 + }, + { + "id": "minecraft:potion", + "damage": 3 + }, + { + "id": "minecraft:potion", + "damage": 4 + }, + { + "id": "minecraft:potion", + "damage": 5 + }, + { + "id": "minecraft:potion", + "damage": 6 + }, + { + "id": "minecraft:potion", + "damage": 7 + }, + { + "id": "minecraft:potion", + "damage": 8 + }, + { + "id": "minecraft:potion", + "damage": 9 + }, + { + "id": "minecraft:potion", + "damage": 10 + }, + { + "id": "minecraft:potion", + "damage": 11 + }, + { + "id": "minecraft:potion", + "damage": 12 + }, + { + "id": "minecraft:potion", + "damage": 13 + }, + { + "id": "minecraft:potion", + "damage": 14 + }, + { + "id": "minecraft:potion", + "damage": 15 + }, + { + "id": "minecraft:potion", + "damage": 16 + }, + { + "id": "minecraft:potion", + "damage": 17 + }, + { + "id": "minecraft:potion", + "damage": 18 + }, + { + "id": "minecraft:potion", + "damage": 19 + }, + { + "id": "minecraft:potion", + "damage": 20 + }, + { + "id": "minecraft:potion", + "damage": 21 + }, + { + "id": "minecraft:potion", + "damage": 22 + }, + { + "id": "minecraft:potion", + "damage": 23 + }, + { + "id": "minecraft:potion", + "damage": 24 + }, + { + "id": "minecraft:potion", + "damage": 25 + }, + { + "id": "minecraft:potion", + "damage": 26 + }, + { + "id": "minecraft:potion", + "damage": 27 + }, + { + "id": "minecraft:potion", + "damage": 28 + }, + { + "id": "minecraft:potion", + "damage": 29 + }, + { + "id": "minecraft:potion", + "damage": 30 + }, + { + "id": "minecraft:potion", + "damage": 31 + }, + { + "id": "minecraft:potion", + "damage": 32 + }, + { + "id": "minecraft:potion", + "damage": 33 + }, + { + "id": "minecraft:potion", + "damage": 34 + }, + { + "id": "minecraft:potion", + "damage": 35 + }, + { + "id": "minecraft:potion", + "damage": 36 + }, + { + "id": "minecraft:potion", + "damage": 37 + }, + { + "id": "minecraft:potion", + "damage": 38 + }, + { + "id": "minecraft:potion", + "damage": 39 + }, + { + "id": "minecraft:potion", + "damage": 40 + }, + { + "id": "minecraft:potion", + "damage": 41 + }, + { + "id": "minecraft:potion", + "damage": 42 + }, + { + "id": "minecraft:splash_potion" + }, + { + "id": "minecraft:splash_potion", + "damage": 1 + }, + { + "id": "minecraft:splash_potion", + "damage": 2 + }, + { + "id": "minecraft:splash_potion", + "damage": 3 + }, + { + "id": "minecraft:splash_potion", + "damage": 4 + }, + { + "id": "minecraft:splash_potion", + "damage": 5 + }, + { + "id": "minecraft:splash_potion", + "damage": 6 + }, + { + "id": "minecraft:splash_potion", + "damage": 7 + }, + { + "id": "minecraft:splash_potion", + "damage": 8 + }, + { + "id": "minecraft:splash_potion", + "damage": 9 + }, + { + "id": "minecraft:splash_potion", + "damage": 10 + }, + { + "id": "minecraft:splash_potion", + "damage": 11 + }, + { + "id": "minecraft:splash_potion", + "damage": 12 + }, + { + "id": "minecraft:splash_potion", + "damage": 13 + }, + { + "id": "minecraft:splash_potion", + "damage": 14 + }, + { + "id": "minecraft:splash_potion", + "damage": 15 + }, + { + "id": "minecraft:splash_potion", + "damage": 16 + }, + { + "id": "minecraft:splash_potion", + "damage": 17 + }, + { + "id": "minecraft:splash_potion", + "damage": 18 + }, + { + "id": "minecraft:splash_potion", + "damage": 19 + }, + { + "id": "minecraft:splash_potion", + "damage": 20 + }, + { + "id": "minecraft:splash_potion", + "damage": 21 + }, + { + "id": "minecraft:splash_potion", + "damage": 22 + }, + { + "id": "minecraft:splash_potion", + "damage": 23 + }, + { + "id": "minecraft:splash_potion", + "damage": 24 + }, + { + "id": "minecraft:splash_potion", + "damage": 25 + }, + { + "id": "minecraft:splash_potion", + "damage": 26 + }, + { + "id": "minecraft:splash_potion", + "damage": 27 + }, + { + "id": "minecraft:splash_potion", + "damage": 28 + }, + { + "id": "minecraft:splash_potion", + "damage": 29 + }, + { + "id": "minecraft:splash_potion", + "damage": 30 + }, + { + "id": "minecraft:splash_potion", + "damage": 31 + }, + { + "id": "minecraft:splash_potion", + "damage": 32 + }, + { + "id": "minecraft:splash_potion", + "damage": 33 + }, + { + "id": "minecraft:splash_potion", + "damage": 34 + }, + { + "id": "minecraft:splash_potion", + "damage": 35 + }, + { + "id": "minecraft:splash_potion", + "damage": 36 + }, + { + "id": "minecraft:splash_potion", + "damage": 37 + }, + { + "id": "minecraft:splash_potion", + "damage": 38 + }, + { + "id": "minecraft:splash_potion", + "damage": 39 + }, + { + "id": "minecraft:splash_potion", + "damage": 40 + }, + { + "id": "minecraft:splash_potion", + "damage": 41 + }, + { + "id": "minecraft:splash_potion", + "damage": 42 + }, + { + "id": "minecraft:lingering_potion" + }, + { + "id": "minecraft:lingering_potion", + "damage": 1 + }, + { + "id": "minecraft:lingering_potion", + "damage": 2 + }, + { + "id": "minecraft:lingering_potion", + "damage": 3 + }, + { + "id": "minecraft:lingering_potion", + "damage": 4 + }, + { + "id": "minecraft:lingering_potion", + "damage": 5 + }, + { + "id": "minecraft:lingering_potion", + "damage": 6 + }, + { + "id": "minecraft:lingering_potion", + "damage": 7 + }, + { + "id": "minecraft:lingering_potion", + "damage": 8 + }, + { + "id": "minecraft:lingering_potion", + "damage": 9 + }, + { + "id": "minecraft:lingering_potion", + "damage": 10 + }, + { + "id": "minecraft:lingering_potion", + "damage": 11 + }, + { + "id": "minecraft:lingering_potion", + "damage": 12 + }, + { + "id": "minecraft:lingering_potion", + "damage": 13 + }, + { + "id": "minecraft:lingering_potion", + "damage": 14 + }, + { + "id": "minecraft:lingering_potion", + "damage": 15 + }, + { + "id": "minecraft:lingering_potion", + "damage": 16 + }, + { + "id": "minecraft:lingering_potion", + "damage": 17 + }, + { + "id": "minecraft:lingering_potion", + "damage": 18 + }, + { + "id": "minecraft:lingering_potion", + "damage": 19 + }, + { + "id": "minecraft:lingering_potion", + "damage": 20 + }, + { + "id": "minecraft:lingering_potion", + "damage": 21 + }, + { + "id": "minecraft:lingering_potion", + "damage": 22 + }, + { + "id": "minecraft:lingering_potion", + "damage": 23 + }, + { + "id": "minecraft:lingering_potion", + "damage": 24 + }, + { + "id": "minecraft:lingering_potion", + "damage": 25 + }, + { + "id": "minecraft:lingering_potion", + "damage": 26 + }, + { + "id": "minecraft:lingering_potion", + "damage": 27 + }, + { + "id": "minecraft:lingering_potion", + "damage": 28 + }, + { + "id": "minecraft:lingering_potion", + "damage": 29 + }, + { + "id": "minecraft:lingering_potion", + "damage": 30 + }, + { + "id": "minecraft:lingering_potion", + "damage": 31 + }, + { + "id": "minecraft:lingering_potion", + "damage": 32 + }, + { + "id": "minecraft:lingering_potion", + "damage": 33 + }, + { + "id": "minecraft:lingering_potion", + "damage": 34 + }, + { + "id": "minecraft:lingering_potion", + "damage": 35 + }, + { + "id": "minecraft:lingering_potion", + "damage": 36 + }, + { + "id": "minecraft:lingering_potion", + "damage": 37 + }, + { + "id": "minecraft:lingering_potion", + "damage": 38 + }, + { + "id": "minecraft:lingering_potion", + "damage": 39 + }, + { + "id": "minecraft:lingering_potion", + "damage": 40 + }, + { + "id": "minecraft:lingering_potion", + "damage": 41 + }, + { + "id": "minecraft:lingering_potion", + "damage": 42 + }, + { + "id": "minecraft:spyglass" + }, + { + "id": "minecraft:brush" + }, + { + "id": "minecraft:stick" + }, + { + "id": "minecraft:bed" + }, + { + "id": "minecraft:bed", + "damage": 8 + }, + { + "id": "minecraft:bed", + "damage": 7 + }, + { + "id": "minecraft:bed", + "damage": 15 + }, + { + "id": "minecraft:bed", + "damage": 12 + }, + { + "id": "minecraft:bed", + "damage": 14 + }, + { + "id": "minecraft:bed", + "damage": 1 + }, + { + "id": "minecraft:bed", + "damage": 4 + }, + { + "id": "minecraft:bed", + "damage": 5 + }, + { + "id": "minecraft:bed", + "damage": 13 + }, + { + "id": "minecraft:bed", + "damage": 9 + }, + { + "id": "minecraft:bed", + "damage": 3 + }, + { + "id": "minecraft:bed", + "damage": 11 + }, + { + "id": "minecraft:bed", + "damage": 10 + }, + { + "id": "minecraft:bed", + "damage": 2 + }, + { + "id": "minecraft:bed", + "damage": 6 + }, + { + "id": "minecraft:torch", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnRvcmNoBAkAbmFtZV9oYXNoagn7rmDBzisDCgBuZXR3b3JrX2lk+BwwuQoGAHN0YXRlcwgWAHRvcmNoX2ZhY2luZ19kaXJlY3Rpb24HAHVua25vd24AAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:soul_torch", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnNvdWxfdG9yY2gECQBuYW1lX2hhc2huixOT04BRdQMKAG5ldHdvcmtfaWShbFILCgYAc3RhdGVzCBYAdG9yY2hfZmFjaW5nX2RpcmVjdGlvbgcAdW5rbm93bgADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:sea_pickle", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnNlYV9waWNrbGUECQBuYW1lX2hhc2iONEfZJB+glgMKAG5ldHdvcmtfaWSINWQyCgYAc3RhdGVzAw0AY2x1c3Rlcl9jb3VudAAAAAABCABkZWFkX2JpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:lantern", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmxhbnRlcm4ECQBuYW1lX2hhc2hMw44VI2HWygMKAG5ldHdvcmtfaWRkjQvzCgYAc3RhdGVzAQcAaGFuZ2luZwAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:soul_lantern", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnNvdWxfbGFudGVybgQJAG5hbWVfaGFzaGjIpjxk9z+RAwoAbmV0d29ya19pZGfoP8cKBgBzdGF0ZXMBBwBoYW5naW5nAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:candle", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmNhbmRsZQQJAG5hbWVfaGFzaHPd+MsNdWTfAwoAbmV0d29ya19pZHsBMA0KBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:white_candle", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OndoaXRlX2NhbmRsZQQJAG5hbWVfaGFzaN1EG5Q1mHiEAwoAbmV0d29ya19pZKN1mmgKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:orange_candle", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Om9yYW5nZV9jYW5kbGUECQBuYW1lX2hhc2jySEVWHgUIHQMKAG5ldHdvcmtfaWSfVz82CgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:magenta_candle", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hZ2VudGFfY2FuZGxlBAkAbmFtZV9oYXNoG0u6YIOoBSEDCgBuZXR3b3JrX2lk9xGNkQoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:light_blue_candle", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY2FuZGxlBAkAbmFtZV9oYXNocXGeK0zgrG0DCgBuZXR3b3JrX2lk2m1y8goGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:yellow_candle", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19jYW5kbGUECQBuYW1lX2hhc2i00dtusU3CqQMKAG5ldHdvcmtfaWR9LTmpCgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:lime_candle", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmxpbWVfY2FuZGxlBAkAbmFtZV9oYXNokcmrw5xvz7ADCgBuZXR3b3JrX2lkIAUu6QoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:pink_candle", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfY2FuZGxlBAkAbmFtZV9oYXNoQJdEY4sZ0dwDCgBuZXR3b3JrX2lk23Rn5AoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:gray_candle", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmdyYXlfY2FuZGxlBAkAbmFtZV9oYXNoS5poSo9wBDEDCgBuZXR3b3JrX2lk3trRCAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:light_gray_candle", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY2FuZGxlBAkAbmFtZV9oYXNo9ruTZLBNMasDCgBuZXR3b3JrX2lkb6DOegoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:cyan_candle", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmN5YW5fY2FuZGxlBAkAbmFtZV9oYXNoc/M8PNVcjOwDCgBuZXR3b3JrX2lkZoIQOQoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:purple_candle", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnBsZV9jYW5kbGUECQBuYW1lX2hhc2jaI3xUW0/myQMKAG5ldHdvcmtfaWSnLI2BCgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:blue_candle", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmJsdWVfY2FuZGxlBAkAbmFtZV9oYXNoAASSPW6TgQADCgBuZXR3b3JrX2lkrxrjQAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:brown_candle", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJyb3duX2NhbmRsZQQJAG5hbWVfaGFzaDia0l6s1+WYAwoAbmV0d29ya19pZKSkBXYKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:green_candle", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmdyZWVuX2NhbmRsZQQJAG5hbWVfaGFzaLeFPO1l+fIoAwoAbmV0d29ya19pZBkznDsKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:red_candle", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9jYW5kbGUECQBuYW1lX2hhc2jjAQpGf59ZdwMKAG5ldHdvcmtfaWRbb88GCgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:black_candle", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJsYWNrX2NhbmRsZQQJAG5hbWVfaGFzaB+wRDpOqREKAwoAbmV0d29ya19pZNnOnuEKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:crafting_table", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyYWZ0aW5nX3RhYmxlBAkAbmFtZV9oYXNoe76VAmjvbpYDCgBuZXR3b3JrX2lkwCxwaAoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:cartography_table", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmNhcnRvZ3JhcGh5X3RhYmxlBAkAbmFtZV9oYXNomaWiiD/znP8DCgBuZXR3b3JrX2lkI6FzMwoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:fletching_table", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmZsZXRjaGluZ190YWJsZQQJAG5hbWVfaGFzaPFibh8unKyUAwoAbmV0d29ya19pZJ2mW0oKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:smithing_table", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnNtaXRoaW5nX3RhYmxlBAkAbmFtZV9oYXNo4tFES2xOXEYDCgBuZXR3b3JrX2lkXWMBzQoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:beehive", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmJlZWhpdmUECQBuYW1lX2hhc2hCcqn12UbNpwMKAG5ldHdvcmtfaWR/idcaCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAMLAGhvbmV5X2xldmVsAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:suspicious_sand", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnN1c3BpY2lvdXNfc2FuZAQJAG5hbWVfaGFzaL67QsuvLP00AwoAbmV0d29ya19pZKnkaIAKBgBzdGF0ZXMDEABicnVzaGVkX3Byb2dyZXNzAAAAAAEHAGhhbmdpbmcBAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:suspicious_gravel", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN1c3BpY2lvdXNfZ3JhdmVsBAkAbmFtZV9oYXNoJSVbGNk7C3oDCgBuZXR3b3JrX2lkvIEJAAoGAHN0YXRlcwMQAGJydXNoZWRfcHJvZ3Jlc3MAAAAAAQcAaGFuZ2luZwEAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:campfire" + }, + { + "id": "minecraft:soul_campfire" + }, + { + "id": "minecraft:furnace", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmZ1cm5hY2UECQBuYW1lX2hhc2ioOQrludYY8wMKAG5ldHdvcmtfaWRZxnDOCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:blast_furnace", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmJsYXN0X2Z1cm5hY2UECQBuYW1lX2hhc2ivDbnjkpGm5QMKAG5ldHdvcmtfaWTcEbV/CgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:smoker", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnNtb2tlcgQJAG5hbWVfaGFzaJd1rDMkRWomAwoAbmV0d29ya19pZGWswMwKBgBzdGF0ZXMIHABtaW5lY3JhZnQ6Y2FyZGluYWxfZGlyZWN0aW9uBQBzb3V0aAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:respawn_anchor", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnJlc3Bhd25fYW5jaG9yBAkAbmFtZV9oYXNoZOdcjW05qigDCgBuZXR3b3JrX2lkmhMcaQoGAHN0YXRlcwMVAHJlc3Bhd25fYW5jaG9yX2NoYXJnZQAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:brewing_stand" + }, + { + "id": "minecraft:anvil", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmFudmlsBAkAbmFtZV9oYXNoNqB3fgcUCbwDCgBuZXR3b3JrX2lk8Z3VowoGAHN0YXRlcwgGAGRhbWFnZQkAdW5kYW1hZ2VkCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:anvil", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmFudmlsBAkAbmFtZV9oYXNoNqB3fgcUCbwDCgBuZXR3b3JrX2lkpiv8BAoGAHN0YXRlcwgGAGRhbWFnZRAAc2xpZ2h0bHlfZGFtYWdlZAgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:anvil", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmFudmlsBAkAbmFtZV9oYXNoNqB3fgcUCbwDCgBuZXR3b3JrX2lkFu+pdwoGAHN0YXRlcwgGAGRhbWFnZQwAdmVyeV9kYW1hZ2VkCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:grindstone", + "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmdyaW5kc3RvbmUECQBuYW1lX2hhc2id56zc0nk99wMKAG5ldHdvcmtfaWS4Es07CgYAc3RhdGVzCAoAYXR0YWNobWVudAgAc3RhbmRpbmcDCQBkaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:enchanting_table", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmVuY2hhbnRpbmdfdGFibGUECQBuYW1lX2hhc2jgIx24VLvMvwMKAG5ldHdvcmtfaWRliFFJCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:bookshelf", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmJvb2tzaGVsZgQJAG5hbWVfaGFzaDU04DrgJCS9AwoAbmV0d29ya19pZBcWwIwKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:chiseled_bookshelf", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmNoaXNlbGVkX2Jvb2tzaGVsZgQJAG5hbWVfaGFzaNXDBnsIsywYAwoAbmV0d29ya19pZIprt5IKBgBzdGF0ZXMDDABib29rc19zdG9yZWQAAAAAAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:lectern", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmxlY3Rlcm4ECQBuYW1lX2hhc2j5Z4Mmi/1QxAMKAG5ldHdvcmtfaWR4JfDHCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgBCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:cauldron" + }, + { + "id": "minecraft:composter", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmNvbXBvc3RlcgQJAG5hbWVfaGFzaPAADHptzeWJAwoAbmV0d29ya19pZHIL6i4KBgBzdGF0ZXMDFABjb21wb3N0ZXJfZmlsbF9sZXZlbAAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:chest", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmNoZXN0BAkAbmFtZV9oYXNog9ozMxlcA88DCgBuZXR3b3JrX2lkDkOFvAoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAG5vcnRoAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:trapped_chest", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnRyYXBwZWRfY2hlc3QECQBuYW1lX2hhc2g2qpF9stsEjgMKAG5ldHdvcmtfaWTjJWYxCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAbm9ydGgAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:ender_chest", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmVuZGVyX2NoZXN0BAkAbmFtZV9oYXNohEZzOFdg0WUDCgBuZXR3b3JrX2lkx4jiSQoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAG5vcnRoAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:barrel", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmJhcnJlbAQJAG5hbWVfaGFzaHDkRPGymiRqAwoAbmV0d29ya19pZPnxzgsKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:undyed_shulker_box", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnVuZHllZF9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaOC9mypm/MlBAwoAbmV0d29ya19pZJ8rxp0KBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:white_shulker_box", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OndoaXRlX3NodWxrZXJfYm94BAkAbmFtZV9oYXNosK79m1rPUBwDCgBuZXR3b3JrX2lkjrET6goGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:light_gray_shulker_box", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2iBe5zq7PxHmgMKAG5ldHdvcmtfaWSCVJv0CgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:gray_shulker_box", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmdyYXlfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2ga2s8ctjHUhgMKAG5ldHdvcmtfaWS3WMsWCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:black_shulker_box", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmJsYWNrX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoPm03OZphrp8DCgBuZXR3b3JrX2lkXHztNAoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:brown_shulker_box", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmJyb3duX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoT3DD6qAL9cADCgBuZXR3b3JrX2lkaXxpYQoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:red_shulker_box", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnJlZF9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaMIlKSCzqSZoAwoAbmV0d29ya19pZNrf+icKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:orange_shulker_box", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0Om9yYW5nZV9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaG2MAXU67wGrAwoAbmV0d29ya19pZGoO05gKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:yellow_shulker_box", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnllbGxvd19zaHVsa2VyX2JveAQJAG5hbWVfaGFzaIsLwQHYjcIEAwoAbmV0d29ya19pZBCBSiYKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:lime_shulker_box", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmxpbWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2hUwBkg+faUGAMKAG5ldHdvcmtfaWRJeKqqCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:green_shulker_box", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmdyZWVuX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoZgUeT3LupLUDCgBuZXR3b3JrX2lkzJiohQoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:cyan_shulker_box", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmN5YW5fc2h1bGtlcl9ib3gECQBuYW1lX2hhc2gSfbjteXg5yAMKAG5ldHdvcmtfaWTHeliECgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:light_blue_shulker_box", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2h0VFCX0qsRxQMKAG5ldHdvcmtfaWQXD8U0CgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:blue_shulker_box", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmJsdWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2hn9gS0XIe6rAMKAG5ldHdvcmtfaWTO4PJaCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:purple_shulker_box", + "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnB1cnBsZV9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaEV/lkNPxRDdAwoAbmV0d29ya19pZFK25GAKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:magenta_shulker_box", + "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0Om1hZ2VudGFfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2iqWM7IJHxcFgMKAG5ldHdvcmtfaWTyyudTCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:pink_shulker_box", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnBpbmtfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2in1tkJ1GNcZgMKAG5ldHdvcmtfaWQOEGXjCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:armor_stand" + }, + { + "id": "minecraft:noteblock", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0Om5vdGVibG9jawQJAG5hbWVfaGFzaHPA8dBBH0UaAwoAbmV0d29ya19pZH1U5QkKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:jukebox", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0Omp1a2Vib3gECQBuYW1lX2hhc2ieAIPExf/ZfgMKAG5ldHdvcmtfaWSmR7JfCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:music_disc_13" + }, + { + "id": "minecraft:music_disc_cat" + }, + { + "id": "minecraft:music_disc_blocks" + }, + { + "id": "minecraft:music_disc_chirp" + }, + { + "id": "minecraft:music_disc_far" + }, + { + "id": "minecraft:music_disc_mall" + }, + { + "id": "minecraft:music_disc_mellohi" + }, + { + "id": "minecraft:music_disc_stal" + }, + { + "id": "minecraft:music_disc_strad" + }, + { + "id": "minecraft:music_disc_ward" + }, + { + "id": "minecraft:music_disc_11" + }, + { + "id": "minecraft:music_disc_wait" + }, + { + "id": "minecraft:music_disc_otherside" + }, + { + "id": "minecraft:music_disc_5" + }, + { + "id": "minecraft:music_disc_pigstep" + }, + { + "id": "minecraft:music_disc_relic" + }, + { + "id": "minecraft:disc_fragment_5" + }, + { + "id": "minecraft:glowstone_dust" + }, + { + "id": "minecraft:glowstone", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0Omdsb3dzdG9uZQQJAG5hbWVfaGFzaFYqXNkefIlPAwoAbmV0d29ya19pZGT7WYYKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:redstone_lamp", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZHN0b25lX2xhbXAECQBuYW1lX2hhc2hJ9V80caPvEgMKAG5ldHdvcmtfaWRvNPwnCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:sea_lantern", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnNlYV9sYW50ZXJuBAkAbmFtZV9oYXNoLPsv1TX9M+QDCgBuZXR3b3JrX2lk1PPVyAoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:oak_sign" + }, + { + "id": "minecraft:spruce_sign" + }, + { + "id": "minecraft:birch_sign" + }, + { + "id": "minecraft:jungle_sign" + }, + { + "id": "minecraft:acacia_sign" + }, + { + "id": "minecraft:dark_oak_sign" + }, + { + "id": "minecraft:mangrove_sign" + }, + { + "id": "minecraft:cherry_sign" + }, + { + "id": "minecraft:bamboo_sign" + }, + { + "id": "minecraft:crimson_sign" + }, + { + "id": "minecraft:warped_sign" + }, + { + "id": "minecraft:oak_hanging_sign" + }, + { + "id": "minecraft:spruce_hanging_sign" + }, + { + "id": "minecraft:birch_hanging_sign" + }, + { + "id": "minecraft:jungle_hanging_sign" + }, + { + "id": "minecraft:acacia_hanging_sign" + }, + { + "id": "minecraft:dark_oak_hanging_sign" + }, + { + "id": "minecraft:mangrove_hanging_sign" + }, + { + "id": "minecraft:cherry_hanging_sign" + }, + { + "id": "minecraft:bamboo_hanging_sign" + }, + { + "id": "minecraft:crimson_hanging_sign" + }, + { + "id": "minecraft:warped_hanging_sign" + }, + { + "id": "minecraft:painting" + }, + { + "id": "minecraft:frame" + }, + { + "id": "minecraft:glow_frame" + }, + { + "id": "minecraft:honey_bottle" + }, + { + "id": "minecraft:flower_pot" + }, + { + "id": "minecraft:bowl" + }, + { + "id": "minecraft:bucket" + }, + { + "id": "minecraft:milk_bucket" + }, + { + "id": "minecraft:water_bucket" + }, + { + "id": "minecraft:lava_bucket" + }, + { + "id": "minecraft:cod_bucket" + }, + { + "id": "minecraft:salmon_bucket" + }, + { + "id": "minecraft:tropical_fish_bucket" + }, + { + "id": "minecraft:pufferfish_bucket" + }, + { + "id": "minecraft:powder_snow_bucket" + }, + { + "id": "minecraft:axolotl_bucket" + }, + { + "id": "minecraft:tadpole_bucket" + }, + { + "id": "minecraft:skull", + "damage": 3 + }, + { + "id": "minecraft:skull", + "damage": 2 + }, + { + "id": "minecraft:skull", + "damage": 4 + }, + { + "id": "minecraft:skull", + "damage": 5 + }, + { + "id": "minecraft:skull" + }, + { + "id": "minecraft:skull", + "damage": 1 + }, + { + "id": "minecraft:skull", + "damage": 6 + }, + { + "id": "minecraft:beacon", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmJlYWNvbgQJAG5hbWVfaGFzaACwhhfSkdkHAwoAbmV0d29ya19pZF8jfiEKBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:bell", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OmJlbGwECQBuYW1lX2hhc2iPqsgDXRcsxAMKAG5ldHdvcmtfaWT7zhOoCgYAc3RhdGVzCAoAYXR0YWNobWVudAgAc3RhbmRpbmcDCQBkaXJlY3Rpb24AAAAAAQoAdG9nZ2xlX2JpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:conduit", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmNvbmR1aXQECQBuYW1lX2hhc2jqxKAxq2EaWQMKAG5ldHdvcmtfaWTWcBVnCgYAc3RhdGVzAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:stonecutter_block", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lY3V0dGVyX2Jsb2NrBAkAbmFtZV9oYXNoQAXTbAM3MeYDCgBuZXR3b3JrX2lkWS4RjAoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAG5vcnRoAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:end_portal_frame", + "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmVuZF9wb3J0YWxfZnJhbWUECQBuYW1lX2hhc2gqofyUIjGOpQMKAG5ldHdvcmtfaWRbGHf8CgYAc3RhdGVzARIAZW5kX3BvcnRhbF9leWVfYml0AAgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:coal" + }, + { + "id": "minecraft:charcoal" + }, + { + "id": "minecraft:diamond" + }, + { + "id": "minecraft:iron_nugget" + }, + { + "id": "minecraft:raw_iron" + }, + { + "id": "minecraft:raw_gold" + }, + { + "id": "minecraft:raw_copper" + }, + { + "id": "minecraft:copper_ingot" + }, + { + "id": "minecraft:iron_ingot" + }, + { + "id": "minecraft:netherite_scrap" + }, + { + "id": "minecraft:netherite_ingot" + }, + { + "id": "minecraft:gold_nugget" + }, + { + "id": "minecraft:gold_ingot" + }, + { + "id": "minecraft:emerald" + }, + { + "id": "minecraft:quartz" + }, + { + "id": "minecraft:clay_ball" + }, + { + "id": "minecraft:brick" + }, + { + "id": "minecraft:netherbrick" + }, + { + "id": "minecraft:prismarine_shard" + }, + { + "id": "minecraft:amethyst_shard" + }, + { + "id": "minecraft:prismarine_crystals" + }, + { + "id": "minecraft:nautilus_shell" + }, + { + "id": "minecraft:heart_of_the_sea" + }, + { + "id": "minecraft:scute" + }, + { + "id": "minecraft:phantom_membrane" + }, + { + "id": "minecraft:string" + }, + { + "id": "minecraft:feather" + }, + { + "id": "minecraft:flint" + }, + { + "id": "minecraft:gunpowder" + }, + { + "id": "minecraft:leather" + }, + { + "id": "minecraft:rabbit_hide" + }, + { + "id": "minecraft:rabbit_foot" + }, + { + "id": "minecraft:fire_charge" + }, + { + "id": "minecraft:blaze_rod" + }, + { + "id": "minecraft:blaze_powder" + }, + { + "id": "minecraft:magma_cream" + }, + { + "id": "minecraft:fermented_spider_eye" + }, + { + "id": "minecraft:echo_shard" + }, + { + "id": "minecraft:dragon_breath" + }, + { + "id": "minecraft:shulker_shell" + }, + { + "id": "minecraft:ghast_tear" + }, + { + "id": "minecraft:slime_ball" + }, + { + "id": "minecraft:ender_pearl" + }, + { + "id": "minecraft:ender_eye" + }, + { + "id": "minecraft:nether_star" + }, + { + "id": "minecraft:end_rod", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmVuZF9yb2QECQBuYW1lX2hhc2jx/q5cEA0hmQMKAG5ldHdvcmtfaWQ2eM8kCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:lightning_rod", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmxpZ2h0bmluZ19yb2QECQBuYW1lX2hhc2ioXQF1xvfHNQMKAG5ldHdvcmtfaWRLuHyACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:end_crystal" + }, + { + "id": "minecraft:paper" + }, + { + "id": "minecraft:book" + }, + { + "id": "minecraft:writable_book" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQFAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQFAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQFAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQGAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQGAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQGAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQHAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQHAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQHAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQIAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAUAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAUAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAUAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQMAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQMAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQNAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQNAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQOAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQOAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQOAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAUAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQQAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQRAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQRAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQRAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQSAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQSAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQSAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAUAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQUAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQUAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQVAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQWAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQXAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQXAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQXAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQYAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQYAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQYAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQZAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQZAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQaAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQbAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQcAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAUAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQeAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQeAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQeAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQfAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQfAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQfAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQgAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQhAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQjAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQjAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQjAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQkAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQkAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQkAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQlAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQlAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQlAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:oak_boat" + }, + { + "id": "minecraft:spruce_boat" + }, + { + "id": "minecraft:birch_boat" + }, + { + "id": "minecraft:jungle_boat" + }, + { + "id": "minecraft:acacia_boat" + }, + { + "id": "minecraft:dark_oak_boat" + }, + { + "id": "minecraft:mangrove_boat" + }, + { + "id": "minecraft:cherry_boat" + }, + { + "id": "minecraft:bamboo_raft" + }, + { + "id": "minecraft:oak_chest_boat" + }, + { + "id": "minecraft:spruce_chest_boat" + }, + { + "id": "minecraft:birch_chest_boat" + }, + { + "id": "minecraft:jungle_chest_boat" + }, + { + "id": "minecraft:acacia_chest_boat" + }, + { + "id": "minecraft:dark_oak_chest_boat" + }, + { + "id": "minecraft:mangrove_chest_boat" + }, + { + "id": "minecraft:cherry_chest_boat" + }, + { + "id": "minecraft:bamboo_chest_raft" + }, + { + "id": "minecraft:rail", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OnJhaWwECQBuYW1lX2hhc2hUzmhUXYJDUQMKAG5ldHdvcmtfaWR+Sp6YCgYAc3RhdGVzAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:golden_rail", + "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmdvbGRlbl9yYWlsBAkAbmFtZV9oYXNoOoV5MaKipoUDCgBuZXR3b3JrX2lkfAcxLwoGAHN0YXRlcwENAHJhaWxfZGF0YV9iaXQAAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:detector_rail", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmRldGVjdG9yX3JhaWwECQBuYW1lX2hhc2gVUk31qOysUQMKAG5ldHdvcmtfaWRVW/aICgYAc3RhdGVzAQ0AcmFpbF9kYXRhX2JpdAADDgByYWlsX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:activator_rail", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmFjdGl2YXRvcl9yYWlsBAkAbmFtZV9oYXNosIL91qriCRkDCgBuZXR3b3JrX2lkZfckmwoGAHN0YXRlcwENAHJhaWxfZGF0YV9iaXQAAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:minecart" + }, + { + "id": "minecraft:chest_minecart" + }, + { + "id": "minecraft:hopper_minecart" + }, + { + "id": "minecraft:tnt_minecart" + }, + { + "id": "minecraft:redstone" + }, + { + "id": "minecraft:redstone_block", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZHN0b25lX2Jsb2NrBAkAbmFtZV9oYXNoRhULL0r8o0sDCgBuZXR3b3JrX2lklayOHgoGAHN0YXRlcwADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:redstone_torch", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZHN0b25lX3RvcmNoBAkAbmFtZV9oYXNoizFRjpYMIDgDCgBuZXR3b3JrX2lkuHz7yAoGAHN0YXRlcwgWAHRvcmNoX2ZhY2luZ19kaXJlY3Rpb24HAHVua25vd24AAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:lever", + "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmxldmVyBAkAbmFtZV9oYXNoGMJeLJsUMLYDCgBuZXR3b3JrX2lkEF/GuAoGAHN0YXRlcwgPAGxldmVyX2RpcmVjdGlvbg4AZG93bl9lYXN0X3dlc3QBCABvcGVuX2JpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:wooden_button", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Ondvb2Rlbl9idXR0b24ECQBuYW1lX2hhc2hR7PgSTQt0sQMKAG5ldHdvcmtfaWSU07kYCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:spruce_button", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9idXR0b24ECQBuYW1lX2hhc2jBW9Z8aYE7YQMKAG5ldHdvcmtfaWTkUIGuCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:birch_button", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX2J1dHRvbgQJAG5hbWVfaGFzaJXYgGuSHbTwAwoAbmV0d29ya19pZGWp3yoKBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:jungle_button", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9idXR0b24ECQBuYW1lX2hhc2iCgNANcJs+BQMKAG5ldHdvcmtfaWT9fImWCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:acacia_button", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9idXR0b24ECQBuYW1lX2hhc2gVvmcT7LTO0wMKAG5ldHdvcmtfaWRQnxIJCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:dark_oak_button", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX2J1dHRvbgQJAG5hbWVfaGFzaIV10ZGGrCIEAwoAbmV0d29ya19pZN5vAmIKBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:mangrove_button", + "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX2J1dHRvbgQJAG5hbWVfaGFzaNzeYYKLgOzJAwoAbmV0d29ya19pZAFEGQ0KBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:cherry_button", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9idXR0b24ECQBuYW1lX2hhc2j2/IHjeAbUcwMKAG5ldHdvcmtfaWRJ1irQCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:bamboo_button", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19idXR0b24ECQBuYW1lX2hhc2j7AddMi+6nsgMKAG5ldHdvcmtfaWSa9w4/CgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:stone_button", + "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnN0b25lX2J1dHRvbgQJAG5hbWVfaGFzaM4ejMctmvohAwoAbmV0d29ya19pZMw+aC0KBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:crimson_button", + "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fYnV0dG9uBAkAbmFtZV9oYXNofnjYHaYIeWgDCgBuZXR3b3JrX2lk+n1vyQoGAHN0YXRlcwESAGJ1dHRvbl9wcmVzc2VkX2JpdAADEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:warped_button", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9idXR0b24ECQBuYW1lX2hhc2jwkV2EU6Cn1QMKAG5ldHdvcmtfaWTnHnk1CgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:polished_blackstone_button", + "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnV0dG9uBAkAbmFtZV9oYXNojmxzQKS0S/EDCgBuZXR3b3JrX2lkDtQ95woGAHN0YXRlcwESAGJ1dHRvbl9wcmVzc2VkX2JpdAADEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:tripwire_hook", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnRyaXB3aXJlX2hvb2sECQBuYW1lX2hhc2gQdp+oGZLNnAMKAG5ldHdvcmtfaWSy+1KJCgYAc3RhdGVzAQwAYXR0YWNoZWRfYml0AAMJAGRpcmVjdGlvbgAAAAABCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:wooden_pressure_plate", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0Ondvb2Rlbl9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaGkGs5kCuA74AwoAbmV0d29ya19pZDRzPNwKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:spruce_pressure_plate", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnNwcnVjZV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaNmwuq549fJKAwoAbmV0d29ya19pZLQMCw0KBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:birch_pressure_plate", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmJpcmNoX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNorQkT9kDdlTwDCgBuZXR3b3JrX2lkH0G97AoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:jungle_pressure_plate", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0Omp1bmdsZV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaJ7DcteCkb8/AwoAbmV0d29ya19pZLdPBSAKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:acacia_pressure_plate", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmFjYWNpYV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaC2frZtfoYqCAwoAbmV0d29ya19pZIDdI18KBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:dark_oak_pressure_plate", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmRhcmtfb2FrX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoHUCJsTy52pwDCgBuZXR3b3JrX2lkKpi8rAoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:mangrove_pressure_plate", + "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0Om1hbmdyb3ZlX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoiDsTfJaX100DCgBuZXR3b3JrX2lkuwWDyQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:cherry_pressure_plate", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmNoZXJyeV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaALMqYEZDUQHAwoAbmV0d29ya19pZPNT+r0KBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:bamboo_pressure_plate", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmJhbWJvb19wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaNvxJ7NIAaqlAwoAbmV0d29ya19pZIZ8XnYKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:crimson_pressure_plate", + "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmNyaW1zb25fcHJlc3N1cmVfcGxhdGUECQBuYW1lX2hhc2hqBDVDAd31/gMKAG5ldHdvcmtfaWRmV18LCgYAc3RhdGVzAw8AcmVkc3RvbmVfc2lnbmFsAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:warped_pressure_plate", + "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OndhcnBlZF9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaBxFoQksWtYUAwoAbmV0d29ya19pZJVRoIcKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:stone_pressure_plate", + "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnN0b25lX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNounJuTBUTrU8DCgBuZXR3b3JrX2lkjDydwQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:light_weighted_pressure_plate", + "block_state_b64": "CgAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X3dlaWdodGVkX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoOyOJkNxLtkEDCgBuZXR3b3JrX2lkrr2AjgoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:heavy_weighted_pressure_plate", + "block_state_b64": "CgAACAQAbmFtZScAbWluZWNyYWZ0OmhlYXZ5X3dlaWdodGVkX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoltgDmDvTajUDCgBuZXR3b3JrX2lkFxVKuQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:polished_blackstone_pressure_plate", + "block_state_b64": "CgAACAQAbmFtZSwAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfcHJlc3N1cmVfcGxhdGUECQBuYW1lX2hhc2h65Ci6/CeGqwMKAG5ldHdvcmtfaWTaSW5xCgYAc3RhdGVzAw8AcmVkc3RvbmVfc2lnbmFsAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:observer", + "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0Om9ic2VydmVyBAkAbmFtZV9oYXNoYhlh1lpmHTgDCgBuZXR3b3JrX2lkQEh55goGAHN0YXRlcwgaAG1pbmVjcmFmdDpmYWNpbmdfZGlyZWN0aW9uBABkb3duAQsAcG93ZXJlZF9iaXQAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:daylight_detector", + "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmRheWxpZ2h0X2RldGVjdG9yBAkAbmFtZV9oYXNoV0F0s7B7PVgDCgBuZXR3b3JrX2lkri5afQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:repeater" + }, + { + "id": "minecraft:comparator" + }, + { + "id": "minecraft:hopper" + }, + { + "id": "minecraft:dropper", + "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmRyb3BwZXIECQBuYW1lX2hhc2joXP7XqU0l3QMKAG5ldHdvcmtfaWQfQN6zCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgMAAAABDQB0cmlnZ2VyZWRfYml0AAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:dispenser", + "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmRpc3BlbnNlcgQJAG5hbWVfaGFzaP1RR+zAbYP2AwoAbmV0d29ya19pZGAayD0KBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAwAAAAENAHRyaWdnZXJlZF9iaXQAAAMHAHZlcnNpb24DKBQBAA==" + }, + { + "id": "minecraft:piston", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBpc3RvbgQJAG5hbWVfaGFzaDs3AFh1fL0uAwoAbmV0d29ya19pZLD/5XQKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAQAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:sticky_piston", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnN0aWNreV9waXN0b24ECQBuYW1lX2hhc2hPFJFJSiJ0ZQMKAG5ldHdvcmtfaWT/MzCJCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgEAAAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:tnt", + "block_state_b64": "CgAACAQAbmFtZQ0AbWluZWNyYWZ0OnRudAQJAG5hbWVfaGFzaEYOHwCvJH29AwoAbmV0d29ya19pZCGfjU4KBgBzdGF0ZXMBFABhbGxvd191bmRlcndhdGVyX2JpdAABCwBleHBsb2RlX2JpdAAAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:name_tag" + }, + { + "id": "minecraft:loom", + "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Omxvb20ECQBuYW1lX2hhc2i7DKjAXNq8TAMKAG5ldHdvcmtfaWR/49HXCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:banner" + }, + { + "id": "minecraft:banner", + "damage": 8 + }, + { + "id": "minecraft:banner", + "damage": 7 + }, + { + "id": "minecraft:banner", + "damage": 15 + }, + { + "id": "minecraft:banner", + "damage": 12 + }, + { + "id": "minecraft:banner", + "damage": 14 + }, + { + "id": "minecraft:banner", + "damage": 1 + }, + { + "id": "minecraft:banner", + "damage": 4 + }, + { + "id": "minecraft:banner", + "damage": 5 + }, + { + "id": "minecraft:banner", + "damage": 13 + }, + { + "id": "minecraft:banner", + "damage": 9 + }, + { + "id": "minecraft:banner", + "damage": 3 + }, + { + "id": "minecraft:banner", + "damage": 11 + }, + { + "id": "minecraft:banner", + "damage": 10 + }, + { + "id": "minecraft:banner", + "damage": 2 + }, + { + "id": "minecraft:banner", + "damage": 6 + }, + { + "id": "minecraft:banner", + "damage": 15, + "nbt_b64": "CgAAAwQAVHlwZQEAAAAA" + }, + { + "id": "minecraft:creeper_banner_pattern" + }, + { + "id": "minecraft:skull_banner_pattern" + }, + { + "id": "minecraft:flower_banner_pattern" + }, + { + "id": "minecraft:mojang_banner_pattern" + }, + { + "id": "minecraft:field_masoned_banner_pattern" + }, + { + "id": "minecraft:bordure_indented_banner_pattern" + }, + { + "id": "minecraft:piglin_banner_pattern" + }, + { + "id": "minecraft:globe_banner_pattern" + }, + { + "id": "minecraft:angler_pottery_sherd" + }, + { + "id": "minecraft:archer_pottery_sherd" + }, + { + "id": "minecraft:arms_up_pottery_sherd" + }, + { + "id": "minecraft:blade_pottery_sherd" + }, + { + "id": "minecraft:brewer_pottery_sherd" + }, + { + "id": "minecraft:burn_pottery_sherd" + }, + { + "id": "minecraft:danger_pottery_sherd" + }, + { + "id": "minecraft:explorer_pottery_sherd" + }, + { + "id": "minecraft:friend_pottery_sherd" + }, + { + "id": "minecraft:heart_pottery_sherd" + }, + { + "id": "minecraft:heartbreak_pottery_sherd" + }, + { + "id": "minecraft:howl_pottery_sherd" + }, + { + "id": "minecraft:miner_pottery_sherd" + }, + { + "id": "minecraft:mourner_pottery_sherd" + }, + { + "id": "minecraft:plenty_pottery_sherd" + }, + { + "id": "minecraft:prize_pottery_sherd" + }, + { + "id": "minecraft:sheaf_pottery_sherd" + }, + { + "id": "minecraft:shelter_pottery_sherd" + }, + { + "id": "minecraft:skull_pottery_sherd" + }, + { + "id": "minecraft:snort_pottery_sherd" + }, + { + "id": "minecraft:netherite_upgrade_smithing_template" + }, + { + "id": "minecraft:sentry_armor_trim_smithing_template" + }, + { + "id": "minecraft:vex_armor_trim_smithing_template" + }, + { + "id": "minecraft:wild_armor_trim_smithing_template" + }, + { + "id": "minecraft:coast_armor_trim_smithing_template" + }, + { + "id": "minecraft:dune_armor_trim_smithing_template" + }, + { + "id": "minecraft:wayfinder_armor_trim_smithing_template" + }, + { + "id": "minecraft:shaper_armor_trim_smithing_template" + }, + { + "id": "minecraft:raiser_armor_trim_smithing_template" + }, + { + "id": "minecraft:host_armor_trim_smithing_template" + }, + { + "id": "minecraft:ward_armor_trim_smithing_template" + }, + { + "id": "minecraft:silence_armor_trim_smithing_template" + }, + { + "id": "minecraft:tide_armor_trim_smithing_template" + }, + { + "id": "minecraft:snout_armor_trim_smithing_template" + }, + { + "id": "minecraft:rib_armor_trim_smithing_template" + }, + { + "id": "minecraft:eye_armor_trim_smithing_template" + }, + { + "id": "minecraft:spire_armor_trim_smithing_template" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwAAAAAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAABwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAIBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAHBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAPBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAMBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAOBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAABBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAEBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAFBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAANBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAJBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAADBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAALBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAKBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAACBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_rocket", + "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAGBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" + }, + { + "id": "minecraft:firework_star", + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yIR0d/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 8, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yUk9H/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 7, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yl52d/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 15, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9y8PDw/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 12, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9y2rM6/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 14, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yHYD5/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 1, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yJi6w/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 4, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yqkQ8/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 5, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yuDKJ/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 13, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yvU7H/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 9, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yqovz/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 3, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yMlSD/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 11, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yPdj+/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 10, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yH8eA/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 2, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yFnxe/wA=" + }, + { + "id": "minecraft:firework_star", + "damage": 6, + "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9ynJwW/wA=" + }, + { + "id": "minecraft:chain" + }, + { + "id": "minecraft:target", + "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnRhcmdldAQJAG5hbWVfaGFzaJc66SVbYlaxAwoAbmV0d29ya19pZPBozs0KBgBzdGF0ZXMAAwcAdmVyc2lvbgMoFAEA" + }, + { + "id": "minecraft:decorated_pot", + "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmRlY29yYXRlZF9wb3QECQBuYW1lX2hhc2jjQgckn8VTvwMKAG5ldHdvcmtfaWRwvkUUCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAygUAQA=" + }, + { + "id": "minecraft:lodestone_compass" + }, + { + "id": "minecraft:wither_spawn_egg" + }, + { + "id": "minecraft:ender_dragon_spawn_egg" + } + ] +} \ No newline at end of file diff --git a/core/src/main/resources/bedrock/runtime_item_states.1_20_40.json b/core/src/main/resources/bedrock/runtime_item_states.1_20_40.json new file mode 100644 index 000000000..861b29c8a --- /dev/null +++ b/core/src/main/resources/bedrock/runtime_item_states.1_20_40.json @@ -0,0 +1,5570 @@ +[ + { + "name": "minecraft:acacia_boat", + "id": 381 + }, + { + "name": "minecraft:acacia_button", + "id": -140 + }, + { + "name": "minecraft:acacia_chest_boat", + "id": 649 + }, + { + "name": "minecraft:acacia_door", + "id": 563 + }, + { + "name": "minecraft:acacia_fence", + "id": -575 + }, + { + "name": "minecraft:acacia_fence_gate", + "id": 187 + }, + { + "name": "minecraft:acacia_hanging_sign", + "id": -504 + }, + { + "name": "minecraft:acacia_log", + "id": 162 + }, + { + "name": "minecraft:acacia_pressure_plate", + "id": -150 + }, + { + "name": "minecraft:acacia_sign", + "id": 586 + }, + { + "name": "minecraft:acacia_stairs", + "id": 163 + }, + { + "name": "minecraft:acacia_standing_sign", + "id": -190 + }, + { + "name": "minecraft:acacia_trapdoor", + "id": -145 + }, + { + "name": "minecraft:acacia_wall_sign", + "id": -191 + }, + { + "name": "minecraft:activator_rail", + "id": 126 + }, + { + "name": "minecraft:agent_spawn_egg", + "id": 489 + }, + { + "name": "minecraft:air", + "id": -158 + }, + { + "name": "minecraft:allay_spawn_egg", + "id": 638 + }, + { + "name": "minecraft:allow", + "id": 210 + }, + { + "name": "minecraft:amethyst_block", + "id": -327 + }, + { + "name": "minecraft:amethyst_cluster", + "id": -329 + }, + { + "name": "minecraft:amethyst_shard", + "id": 631 + }, + { + "name": "minecraft:ancient_debris", + "id": -271 + }, + { + "name": "minecraft:andesite_stairs", + "id": -171 + }, + { + "name": "minecraft:angler_pottery_sherd", + "id": 663 + }, + { + "name": "minecraft:anvil", + "id": 145 + }, + { + "name": "minecraft:apple", + "id": 257 + }, + { + "name": "minecraft:archer_pottery_sherd", + "id": 664 + }, + { + "name": "minecraft:armor_stand", + "id": 559 + }, + { + "name": "minecraft:arms_up_pottery_sherd", + "id": 665 + }, + { + "name": "minecraft:arrow", + "id": 303 + }, + { + "name": "minecraft:axolotl_bucket", + "id": 371 + }, + { + "name": "minecraft:axolotl_spawn_egg", + "id": 503 + }, + { + "name": "minecraft:azalea", + "id": -337 + }, + { + "name": "minecraft:azalea_leaves", + "id": -324 + }, + { + "name": "minecraft:azalea_leaves_flowered", + "id": -325 + }, + { + "name": "minecraft:baked_potato", + "id": 281 + }, + { + "name": "minecraft:balloon", + "id": 605 + }, + { + "name": "minecraft:bamboo", + "id": -163 + }, + { + "name": "minecraft:bamboo_block", + "id": -527 + }, + { + "name": "minecraft:bamboo_button", + "id": -511 + }, + { + "name": "minecraft:bamboo_chest_raft", + "id": 661 + }, + { + "name": "minecraft:bamboo_door", + "id": -517 + }, + { + "name": "minecraft:bamboo_double_slab", + "id": -521 + }, + { + "name": "minecraft:bamboo_fence", + "id": -515 + }, + { + "name": "minecraft:bamboo_fence_gate", + "id": -516 + }, + { + "name": "minecraft:bamboo_hanging_sign", + "id": -522 + }, + { + "name": "minecraft:bamboo_mosaic", + "id": -509 + }, + { + "name": "minecraft:bamboo_mosaic_double_slab", + "id": -525 + }, + { + "name": "minecraft:bamboo_mosaic_slab", + "id": -524 + }, + { + "name": "minecraft:bamboo_mosaic_stairs", + "id": -523 + }, + { + "name": "minecraft:bamboo_planks", + "id": -510 + }, + { + "name": "minecraft:bamboo_pressure_plate", + "id": -514 + }, + { + "name": "minecraft:bamboo_raft", + "id": 660 + }, + { + "name": "minecraft:bamboo_sapling", + "id": -164 + }, + { + "name": "minecraft:bamboo_sign", + "id": 659 + }, + { + "name": "minecraft:bamboo_slab", + "id": -513 + }, + { + "name": "minecraft:bamboo_stairs", + "id": -512 + }, + { + "name": "minecraft:bamboo_standing_sign", + "id": -518 + }, + { + "name": "minecraft:bamboo_trapdoor", + "id": -520 + }, + { + "name": "minecraft:bamboo_wall_sign", + "id": -519 + }, + { + "name": "minecraft:banner", + "id": 574 + }, + { + "name": "minecraft:banner_pattern", + "id": 716 + }, + { + "name": "minecraft:barrel", + "id": -203 + }, + { + "name": "minecraft:barrier", + "id": -161 + }, + { + "name": "minecraft:basalt", + "id": -234 + }, + { + "name": "minecraft:bat_spawn_egg", + "id": 455 + }, + { + "name": "minecraft:beacon", + "id": 138 + }, + { + "name": "minecraft:bed", + "id": 420 + }, + { + "name": "minecraft:bedrock", + "id": 7 + }, + { + "name": "minecraft:bee_nest", + "id": -218 + }, + { + "name": "minecraft:bee_spawn_egg", + "id": 496 + }, + { + "name": "minecraft:beef", + "id": 273 + }, + { + "name": "minecraft:beehive", + "id": -219 + }, + { + "name": "minecraft:beetroot", + "id": 285 + }, + { + "name": "minecraft:beetroot_seeds", + "id": 295 + }, + { + "name": "minecraft:beetroot_soup", + "id": 286 + }, + { + "name": "minecraft:bell", + "id": -206 + }, + { + "name": "minecraft:big_dripleaf", + "id": -323 + }, + { + "name": "minecraft:birch_boat", + "id": 378 + }, + { + "name": "minecraft:birch_button", + "id": -141 + }, + { + "name": "minecraft:birch_chest_boat", + "id": 646 + }, + { + "name": "minecraft:birch_door", + "id": 561 + }, + { + "name": "minecraft:birch_fence", + "id": -576 + }, + { + "name": "minecraft:birch_fence_gate", + "id": 184 + }, + { + "name": "minecraft:birch_hanging_sign", + "id": -502 + }, + { + "name": "minecraft:birch_log", + "id": -570 + }, + { + "name": "minecraft:birch_pressure_plate", + "id": -151 + }, + { + "name": "minecraft:birch_sign", + "id": 584 + }, + { + "name": "minecraft:birch_stairs", + "id": 135 + }, + { + "name": "minecraft:birch_standing_sign", + "id": -186 + }, + { + "name": "minecraft:birch_trapdoor", + "id": -146 + }, + { + "name": "minecraft:birch_wall_sign", + "id": -187 + }, + { + "name": "minecraft:black_candle", + "id": -428 + }, + { + "name": "minecraft:black_candle_cake", + "id": -445 + }, + { + "name": "minecraft:black_carpet", + "id": -611 + }, + { + "name": "minecraft:black_concrete", + "id": -642 + }, + { + "name": "minecraft:black_concrete_powder", + "id": -723 + }, + { + "name": "minecraft:black_dye", + "id": 397 + }, + { + "name": "minecraft:black_glazed_terracotta", + "id": 235 + }, + { + "name": "minecraft:black_shulker_box", + "id": -627 + }, + { + "name": "minecraft:black_stained_glass", + "id": -687 + }, + { + "name": "minecraft:black_stained_glass_pane", + "id": -657 + }, + { + "name": "minecraft:black_terracotta", + "id": -738 + }, + { + "name": "minecraft:black_wool", + "id": -554 + }, + { + "name": "minecraft:blackstone", + "id": -273 + }, + { + "name": "minecraft:blackstone_double_slab", + "id": -283 + }, + { + "name": "minecraft:blackstone_slab", + "id": -282 + }, + { + "name": "minecraft:blackstone_stairs", + "id": -276 + }, + { + "name": "minecraft:blackstone_wall", + "id": -277 + }, + { + "name": "minecraft:blade_pottery_sherd", + "id": 666 + }, + { + "name": "minecraft:blast_furnace", + "id": -196 + }, + { + "name": "minecraft:blaze_powder", + "id": 431 + }, + { + "name": "minecraft:blaze_rod", + "id": 425 + }, + { + "name": "minecraft:blaze_spawn_egg", + "id": 458 + }, + { + "name": "minecraft:bleach", + "id": 603 + }, + { + "name": "minecraft:blue_candle", + "id": -424 + }, + { + "name": "minecraft:blue_candle_cake", + "id": -441 + }, + { + "name": "minecraft:blue_carpet", + "id": -607 + }, + { + "name": "minecraft:blue_concrete", + "id": -638 + }, + { + "name": "minecraft:blue_concrete_powder", + "id": -719 + }, + { + "name": "minecraft:blue_dye", + "id": 401 + }, + { + "name": "minecraft:blue_glazed_terracotta", + "id": 231 + }, + { + "name": "minecraft:blue_ice", + "id": -11 + }, + { + "name": "minecraft:blue_shulker_box", + "id": -623 + }, + { + "name": "minecraft:blue_stained_glass", + "id": -683 + }, + { + "name": "minecraft:blue_stained_glass_pane", + "id": -653 + }, + { + "name": "minecraft:blue_terracotta", + "id": -734 + }, + { + "name": "minecraft:blue_wool", + "id": -563 + }, + { + "name": "minecraft:boat", + "id": 714 + }, + { + "name": "minecraft:bone", + "id": 417 + }, + { + "name": "minecraft:bone_block", + "id": 216 + }, + { + "name": "minecraft:bone_meal", + "id": 413 + }, + { + "name": "minecraft:book", + "id": 389 + }, + { + "name": "minecraft:bookshelf", + "id": 47 + }, + { + "name": "minecraft:border_block", + "id": 212 + }, + { + "name": "minecraft:bordure_indented_banner_pattern", + "id": 593 + }, + { + "name": "minecraft:bow", + "id": 302 + }, + { + "name": "minecraft:bowl", + "id": 323 + }, + { + "name": "minecraft:brain_coral", + "id": -581 + }, + { + "name": "minecraft:bread", + "id": 261 + }, + { + "name": "minecraft:brewer_pottery_sherd", + "id": 667 + }, + { + "name": "minecraft:brewing_stand", + "id": 433 + }, + { + "name": "minecraft:brick", + "id": 385 + }, + { + "name": "minecraft:brick_block", + "id": 45 + }, + { + "name": "minecraft:brick_stairs", + "id": 108 + }, + { + "name": "minecraft:brown_candle", + "id": -425 + }, + { + "name": "minecraft:brown_candle_cake", + "id": -442 + }, + { + "name": "minecraft:brown_carpet", + "id": -608 + }, + { + "name": "minecraft:brown_concrete", + "id": -639 + }, + { + "name": "minecraft:brown_concrete_powder", + "id": -720 + }, + { + "name": "minecraft:brown_dye", + "id": 400 + }, + { + "name": "minecraft:brown_glazed_terracotta", + "id": 232 + }, + { + "name": "minecraft:brown_mushroom", + "id": 39 + }, + { + "name": "minecraft:brown_mushroom_block", + "id": 99 + }, + { + "name": "minecraft:brown_shulker_box", + "id": -624 + }, + { + "name": "minecraft:brown_stained_glass", + "id": -684 + }, + { + "name": "minecraft:brown_stained_glass_pane", + "id": -654 + }, + { + "name": "minecraft:brown_terracotta", + "id": -735 + }, + { + "name": "minecraft:brown_wool", + "id": -555 + }, + { + "name": "minecraft:brush", + "id": 683 + }, + { + "name": "minecraft:bubble_column", + "id": -160 + }, + { + "name": "minecraft:bubble_coral", + "id": -582 + }, + { + "name": "minecraft:bucket", + "id": 362 + }, + { + "name": "minecraft:budding_amethyst", + "id": -328 + }, + { + "name": "minecraft:burn_pottery_sherd", + "id": 668 + }, + { + "name": "minecraft:cactus", + "id": 81 + }, + { + "name": "minecraft:cake", + "id": 419 + }, + { + "name": "minecraft:calcite", + "id": -326 + }, + { + "name": "minecraft:calibrated_sculk_sensor", + "id": -580 + }, + { + "name": "minecraft:camel_spawn_egg", + "id": 662 + }, + { + "name": "minecraft:camera", + "id": 600 + }, + { + "name": "minecraft:campfire", + "id": 596 + }, + { + "name": "minecraft:candle", + "id": -412 + }, + { + "name": "minecraft:candle_cake", + "id": -429 + }, + { + "name": "minecraft:carpet", + "id": 704 + }, + { + "name": "minecraft:carrot", + "id": 279 + }, + { + "name": "minecraft:carrot_on_a_stick", + "id": 524 + }, + { + "name": "minecraft:carrots", + "id": 141 + }, + { + "name": "minecraft:cartography_table", + "id": -200 + }, + { + "name": "minecraft:carved_pumpkin", + "id": -155 + }, + { + "name": "minecraft:cat_spawn_egg", + "id": 490 + }, + { + "name": "minecraft:cauldron", + "id": 434 + }, + { + "name": "minecraft:cave_spider_spawn_egg", + "id": 459 + }, + { + "name": "minecraft:cave_vines", + "id": -322 + }, + { + "name": "minecraft:cave_vines_body_with_berries", + "id": -375 + }, + { + "name": "minecraft:cave_vines_head_with_berries", + "id": -376 + }, + { + "name": "minecraft:chain", + "id": 626 + }, + { + "name": "minecraft:chain_command_block", + "id": 189 + }, + { + "name": "minecraft:chainmail_boots", + "id": 344 + }, + { + "name": "minecraft:chainmail_chestplate", + "id": 342 + }, + { + "name": "minecraft:chainmail_helmet", + "id": 341 + }, + { + "name": "minecraft:chainmail_leggings", + "id": 343 + }, + { + "name": "minecraft:charcoal", + "id": 305 + }, + { + "name": "minecraft:chemical_heat", + "id": 192 + }, + { + "name": "minecraft:chemistry_table", + "id": 238 + }, + { + "name": "minecraft:cherry_boat", + "id": 656 + }, + { + "name": "minecraft:cherry_button", + "id": -530 + }, + { + "name": "minecraft:cherry_chest_boat", + "id": 657 + }, + { + "name": "minecraft:cherry_door", + "id": -531 + }, + { + "name": "minecraft:cherry_double_slab", + "id": -540 + }, + { + "name": "minecraft:cherry_fence", + "id": -532 + }, + { + "name": "minecraft:cherry_fence_gate", + "id": -533 + }, + { + "name": "minecraft:cherry_hanging_sign", + "id": -534 + }, + { + "name": "minecraft:cherry_leaves", + "id": -548 + }, + { + "name": "minecraft:cherry_log", + "id": -536 + }, + { + "name": "minecraft:cherry_planks", + "id": -537 + }, + { + "name": "minecraft:cherry_pressure_plate", + "id": -538 + }, + { + "name": "minecraft:cherry_sapling", + "id": -547 + }, + { + "name": "minecraft:cherry_sign", + "id": 658 + }, + { + "name": "minecraft:cherry_slab", + "id": -539 + }, + { + "name": "minecraft:cherry_stairs", + "id": -541 + }, + { + "name": "minecraft:cherry_standing_sign", + "id": -542 + }, + { + "name": "minecraft:cherry_trapdoor", + "id": -543 + }, + { + "name": "minecraft:cherry_wall_sign", + "id": -544 + }, + { + "name": "minecraft:cherry_wood", + "id": -546 + }, + { + "name": "minecraft:chest", + "id": 54 + }, + { + "name": "minecraft:chest_boat", + "id": 652 + }, + { + "name": "minecraft:chest_minecart", + "id": 391 + }, + { + "name": "minecraft:chicken", + "id": 275 + }, + { + "name": "minecraft:chicken_spawn_egg", + "id": 437 + }, + { + "name": "minecraft:chiseled_bookshelf", + "id": -526 + }, + { + "name": "minecraft:chiseled_deepslate", + "id": -395 + }, + { + "name": "minecraft:chiseled_nether_bricks", + "id": -302 + }, + { + "name": "minecraft:chiseled_polished_blackstone", + "id": -279 + }, + { + "name": "minecraft:chorus_flower", + "id": 200 + }, + { + "name": "minecraft:chorus_fruit", + "id": 565 + }, + { + "name": "minecraft:chorus_plant", + "id": 240 + }, + { + "name": "minecraft:clay", + "id": 82 + }, + { + "name": "minecraft:clay_ball", + "id": 386 + }, + { + "name": "minecraft:client_request_placeholder_block", + "id": -465 + }, + { + "name": "minecraft:clock", + "id": 395 + }, + { + "name": "minecraft:coal", + "id": 304 + }, + { + "name": "minecraft:coal_block", + "id": 173 + }, + { + "name": "minecraft:coal_ore", + "id": 16 + }, + { + "name": "minecraft:coast_armor_trim_smithing_template", + "id": 687 + }, + { + "name": "minecraft:cobbled_deepslate", + "id": -379 + }, + { + "name": "minecraft:cobbled_deepslate_double_slab", + "id": -396 + }, + { + "name": "minecraft:cobbled_deepslate_slab", + "id": -380 + }, + { + "name": "minecraft:cobbled_deepslate_stairs", + "id": -381 + }, + { + "name": "minecraft:cobbled_deepslate_wall", + "id": -382 + }, + { + "name": "minecraft:cobblestone", + "id": 4 + }, + { + "name": "minecraft:cobblestone_wall", + "id": 139 + }, + { + "name": "minecraft:cocoa", + "id": 127 + }, + { + "name": "minecraft:cocoa_beans", + "id": 414 + }, + { + "name": "minecraft:cod", + "id": 264 + }, + { + "name": "minecraft:cod_bucket", + "id": 366 + }, + { + "name": "minecraft:cod_spawn_egg", + "id": 482 + }, + { + "name": "minecraft:colored_torch_bp", + "id": 204 + }, + { + "name": "minecraft:colored_torch_rg", + "id": 202 + }, + { + "name": "minecraft:command_block", + "id": 137 + }, + { + "name": "minecraft:command_block_minecart", + "id": 570 + }, + { + "name": "minecraft:comparator", + "id": 529 + }, + { + "name": "minecraft:compass", + "id": 393 + }, + { + "name": "minecraft:composter", + "id": -213 + }, + { + "name": "minecraft:compound", + "id": 601 + }, + { + "name": "minecraft:concrete", + "id": 709 + }, + { + "name": "minecraft:concrete_powder", + "id": 710 + }, + { + "name": "minecraft:conduit", + "id": -157 + }, + { + "name": "minecraft:cooked_beef", + "id": 274 + }, + { + "name": "minecraft:cooked_chicken", + "id": 276 + }, + { + "name": "minecraft:cooked_cod", + "id": 268 + }, + { + "name": "minecraft:cooked_mutton", + "id": 558 + }, + { + "name": "minecraft:cooked_porkchop", + "id": 263 + }, + { + "name": "minecraft:cooked_rabbit", + "id": 289 + }, + { + "name": "minecraft:cooked_salmon", + "id": 269 + }, + { + "name": "minecraft:cookie", + "id": 271 + }, + { + "name": "minecraft:copper_block", + "id": -340 + }, + { + "name": "minecraft:copper_ingot", + "id": 511 + }, + { + "name": "minecraft:copper_ore", + "id": -311 + }, + { + "name": "minecraft:coral", + "id": 707 + }, + { + "name": "minecraft:coral_block", + "id": -132 + }, + { + "name": "minecraft:coral_fan", + "id": -133 + }, + { + "name": "minecraft:coral_fan_dead", + "id": -134 + }, + { + "name": "minecraft:coral_fan_hang", + "id": -135 + }, + { + "name": "minecraft:coral_fan_hang2", + "id": -136 + }, + { + "name": "minecraft:coral_fan_hang3", + "id": -137 + }, + { + "name": "minecraft:cow_spawn_egg", + "id": 438 + }, + { + "name": "minecraft:cracked_deepslate_bricks", + "id": -410 + }, + { + "name": "minecraft:cracked_deepslate_tiles", + "id": -409 + }, + { + "name": "minecraft:cracked_nether_bricks", + "id": -303 + }, + { + "name": "minecraft:cracked_polished_blackstone_bricks", + "id": -280 + }, + { + "name": "minecraft:crafting_table", + "id": 58 + }, + { + "name": "minecraft:creeper_banner_pattern", + "id": 589 + }, + { + "name": "minecraft:creeper_spawn_egg", + "id": 443 + }, + { + "name": "minecraft:crimson_button", + "id": -260 + }, + { + "name": "minecraft:crimson_door", + "id": 623 + }, + { + "name": "minecraft:crimson_double_slab", + "id": -266 + }, + { + "name": "minecraft:crimson_fence", + "id": -256 + }, + { + "name": "minecraft:crimson_fence_gate", + "id": -258 + }, + { + "name": "minecraft:crimson_fungus", + "id": -228 + }, + { + "name": "minecraft:crimson_hanging_sign", + "id": -506 + }, + { + "name": "minecraft:crimson_hyphae", + "id": -299 + }, + { + "name": "minecraft:crimson_nylium", + "id": -232 + }, + { + "name": "minecraft:crimson_planks", + "id": -242 + }, + { + "name": "minecraft:crimson_pressure_plate", + "id": -262 + }, + { + "name": "minecraft:crimson_roots", + "id": -223 + }, + { + "name": "minecraft:crimson_sign", + "id": 621 + }, + { + "name": "minecraft:crimson_slab", + "id": -264 + }, + { + "name": "minecraft:crimson_stairs", + "id": -254 + }, + { + "name": "minecraft:crimson_standing_sign", + "id": -250 + }, + { + "name": "minecraft:crimson_stem", + "id": -225 + }, + { + "name": "minecraft:crimson_trapdoor", + "id": -246 + }, + { + "name": "minecraft:crimson_wall_sign", + "id": -252 + }, + { + "name": "minecraft:crossbow", + "id": 582 + }, + { + "name": "minecraft:crying_obsidian", + "id": -289 + }, + { + "name": "minecraft:cut_copper", + "id": -347 + }, + { + "name": "minecraft:cut_copper_slab", + "id": -361 + }, + { + "name": "minecraft:cut_copper_stairs", + "id": -354 + }, + { + "name": "minecraft:cyan_candle", + "id": -422 + }, + { + "name": "minecraft:cyan_candle_cake", + "id": -439 + }, + { + "name": "minecraft:cyan_carpet", + "id": -605 + }, + { + "name": "minecraft:cyan_concrete", + "id": -636 + }, + { + "name": "minecraft:cyan_concrete_powder", + "id": -717 + }, + { + "name": "minecraft:cyan_dye", + "id": 403 + }, + { + "name": "minecraft:cyan_glazed_terracotta", + "id": 229 + }, + { + "name": "minecraft:cyan_shulker_box", + "id": -621 + }, + { + "name": "minecraft:cyan_stained_glass", + "id": -681 + }, + { + "name": "minecraft:cyan_stained_glass_pane", + "id": -651 + }, + { + "name": "minecraft:cyan_terracotta", + "id": -732 + }, + { + "name": "minecraft:cyan_wool", + "id": -561 + }, + { + "name": "minecraft:danger_pottery_sherd", + "id": 669 + }, + { + "name": "minecraft:dark_oak_boat", + "id": 382 + }, + { + "name": "minecraft:dark_oak_button", + "id": -142 + }, + { + "name": "minecraft:dark_oak_chest_boat", + "id": 650 + }, + { + "name": "minecraft:dark_oak_door", + "id": 564 + }, + { + "name": "minecraft:dark_oak_fence", + "id": -577 + }, + { + "name": "minecraft:dark_oak_fence_gate", + "id": 186 + }, + { + "name": "minecraft:dark_oak_hanging_sign", + "id": -505 + }, + { + "name": "minecraft:dark_oak_log", + "id": -572 + }, + { + "name": "minecraft:dark_oak_pressure_plate", + "id": -152 + }, + { + "name": "minecraft:dark_oak_sign", + "id": 587 + }, + { + "name": "minecraft:dark_oak_stairs", + "id": 164 + }, + { + "name": "minecraft:dark_oak_trapdoor", + "id": -147 + }, + { + "name": "minecraft:dark_prismarine_stairs", + "id": -3 + }, + { + "name": "minecraft:darkoak_standing_sign", + "id": -192 + }, + { + "name": "minecraft:darkoak_wall_sign", + "id": -193 + }, + { + "name": "minecraft:daylight_detector", + "id": 151 + }, + { + "name": "minecraft:daylight_detector_inverted", + "id": 178 + }, + { + "name": "minecraft:dead_brain_coral", + "id": -586 + }, + { + "name": "minecraft:dead_bubble_coral", + "id": -587 + }, + { + "name": "minecraft:dead_fire_coral", + "id": -588 + }, + { + "name": "minecraft:dead_horn_coral", + "id": -589 + }, + { + "name": "minecraft:dead_tube_coral", + "id": -585 + }, + { + "name": "minecraft:deadbush", + "id": 32 + }, + { + "name": "minecraft:decorated_pot", + "id": -551 + }, + { + "name": "minecraft:deepslate", + "id": -378 + }, + { + "name": "minecraft:deepslate_brick_double_slab", + "id": -399 + }, + { + "name": "minecraft:deepslate_brick_slab", + "id": -392 + }, + { + "name": "minecraft:deepslate_brick_stairs", + "id": -393 + }, + { + "name": "minecraft:deepslate_brick_wall", + "id": -394 + }, + { + "name": "minecraft:deepslate_bricks", + "id": -391 + }, + { + "name": "minecraft:deepslate_coal_ore", + "id": -406 + }, + { + "name": "minecraft:deepslate_copper_ore", + "id": -408 + }, + { + "name": "minecraft:deepslate_diamond_ore", + "id": -405 + }, + { + "name": "minecraft:deepslate_emerald_ore", + "id": -407 + }, + { + "name": "minecraft:deepslate_gold_ore", + "id": -402 + }, + { + "name": "minecraft:deepslate_iron_ore", + "id": -401 + }, + { + "name": "minecraft:deepslate_lapis_ore", + "id": -400 + }, + { + "name": "minecraft:deepslate_redstone_ore", + "id": -403 + }, + { + "name": "minecraft:deepslate_tile_double_slab", + "id": -398 + }, + { + "name": "minecraft:deepslate_tile_slab", + "id": -388 + }, + { + "name": "minecraft:deepslate_tile_stairs", + "id": -389 + }, + { + "name": "minecraft:deepslate_tile_wall", + "id": -390 + }, + { + "name": "minecraft:deepslate_tiles", + "id": -387 + }, + { + "name": "minecraft:deny", + "id": 211 + }, + { + "name": "minecraft:detector_rail", + "id": 28 + }, + { + "name": "minecraft:diamond", + "id": 306 + }, + { + "name": "minecraft:diamond_axe", + "id": 321 + }, + { + "name": "minecraft:diamond_block", + "id": 57 + }, + { + "name": "minecraft:diamond_boots", + "id": 352 + }, + { + "name": "minecraft:diamond_chestplate", + "id": 350 + }, + { + "name": "minecraft:diamond_helmet", + "id": 349 + }, + { + "name": "minecraft:diamond_hoe", + "id": 334 + }, + { + "name": "minecraft:diamond_horse_armor", + "id": 540 + }, + { + "name": "minecraft:diamond_leggings", + "id": 351 + }, + { + "name": "minecraft:diamond_ore", + "id": 56 + }, + { + "name": "minecraft:diamond_pickaxe", + "id": 320 + }, + { + "name": "minecraft:diamond_shovel", + "id": 319 + }, + { + "name": "minecraft:diamond_sword", + "id": 318 + }, + { + "name": "minecraft:diorite_stairs", + "id": -170 + }, + { + "name": "minecraft:dirt", + "id": 3 + }, + { + "name": "minecraft:dirt_with_roots", + "id": -318 + }, + { + "name": "minecraft:disc_fragment_5", + "id": 644 + }, + { + "name": "minecraft:dispenser", + "id": 23 + }, + { + "name": "minecraft:dolphin_spawn_egg", + "id": 486 + }, + { + "name": "minecraft:donkey_spawn_egg", + "id": 467 + }, + { + "name": "minecraft:double_cut_copper_slab", + "id": -368 + }, + { + "name": "minecraft:double_plant", + "id": 175 + }, + { + "name": "minecraft:double_stone_block_slab", + "id": 43 + }, + { + "name": "minecraft:double_stone_block_slab2", + "id": 181 + }, + { + "name": "minecraft:double_stone_block_slab3", + "id": -167 + }, + { + "name": "minecraft:double_stone_block_slab4", + "id": -168 + }, + { + "name": "minecraft:double_wooden_slab", + "id": 157 + }, + { + "name": "minecraft:dragon_breath", + "id": 567 + }, + { + "name": "minecraft:dragon_egg", + "id": 122 + }, + { + "name": "minecraft:dried_kelp", + "id": 270 + }, + { + "name": "minecraft:dried_kelp_block", + "id": -139 + }, + { + "name": "minecraft:dripstone_block", + "id": -317 + }, + { + "name": "minecraft:dropper", + "id": 125 + }, + { + "name": "minecraft:drowned_spawn_egg", + "id": 485 + }, + { + "name": "minecraft:dune_armor_trim_smithing_template", + "id": 686 + }, + { + "name": "minecraft:dye", + "id": 715 + }, + { + "name": "minecraft:echo_shard", + "id": 654 + }, + { + "name": "minecraft:egg", + "id": 392 + }, + { + "name": "minecraft:elder_guardian_spawn_egg", + "id": 473 + }, + { + "name": "minecraft:element_0", + "id": 36 + }, + { + "name": "minecraft:element_1", + "id": -12 + }, + { + "name": "minecraft:element_10", + "id": -21 + }, + { + "name": "minecraft:element_100", + "id": -111 + }, + { + "name": "minecraft:element_101", + "id": -112 + }, + { + "name": "minecraft:element_102", + "id": -113 + }, + { + "name": "minecraft:element_103", + "id": -114 + }, + { + "name": "minecraft:element_104", + "id": -115 + }, + { + "name": "minecraft:element_105", + "id": -116 + }, + { + "name": "minecraft:element_106", + "id": -117 + }, + { + "name": "minecraft:element_107", + "id": -118 + }, + { + "name": "minecraft:element_108", + "id": -119 + }, + { + "name": "minecraft:element_109", + "id": -120 + }, + { + "name": "minecraft:element_11", + "id": -22 + }, + { + "name": "minecraft:element_110", + "id": -121 + }, + { + "name": "minecraft:element_111", + "id": -122 + }, + { + "name": "minecraft:element_112", + "id": -123 + }, + { + "name": "minecraft:element_113", + "id": -124 + }, + { + "name": "minecraft:element_114", + "id": -125 + }, + { + "name": "minecraft:element_115", + "id": -126 + }, + { + "name": "minecraft:element_116", + "id": -127 + }, + { + "name": "minecraft:element_117", + "id": -128 + }, + { + "name": "minecraft:element_118", + "id": -129 + }, + { + "name": "minecraft:element_12", + "id": -23 + }, + { + "name": "minecraft:element_13", + "id": -24 + }, + { + "name": "minecraft:element_14", + "id": -25 + }, + { + "name": "minecraft:element_15", + "id": -26 + }, + { + "name": "minecraft:element_16", + "id": -27 + }, + { + "name": "minecraft:element_17", + "id": -28 + }, + { + "name": "minecraft:element_18", + "id": -29 + }, + { + "name": "minecraft:element_19", + "id": -30 + }, + { + "name": "minecraft:element_2", + "id": -13 + }, + { + "name": "minecraft:element_20", + "id": -31 + }, + { + "name": "minecraft:element_21", + "id": -32 + }, + { + "name": "minecraft:element_22", + "id": -33 + }, + { + "name": "minecraft:element_23", + "id": -34 + }, + { + "name": "minecraft:element_24", + "id": -35 + }, + { + "name": "minecraft:element_25", + "id": -36 + }, + { + "name": "minecraft:element_26", + "id": -37 + }, + { + "name": "minecraft:element_27", + "id": -38 + }, + { + "name": "minecraft:element_28", + "id": -39 + }, + { + "name": "minecraft:element_29", + "id": -40 + }, + { + "name": "minecraft:element_3", + "id": -14 + }, + { + "name": "minecraft:element_30", + "id": -41 + }, + { + "name": "minecraft:element_31", + "id": -42 + }, + { + "name": "minecraft:element_32", + "id": -43 + }, + { + "name": "minecraft:element_33", + "id": -44 + }, + { + "name": "minecraft:element_34", + "id": -45 + }, + { + "name": "minecraft:element_35", + "id": -46 + }, + { + "name": "minecraft:element_36", + "id": -47 + }, + { + "name": "minecraft:element_37", + "id": -48 + }, + { + "name": "minecraft:element_38", + "id": -49 + }, + { + "name": "minecraft:element_39", + "id": -50 + }, + { + "name": "minecraft:element_4", + "id": -15 + }, + { + "name": "minecraft:element_40", + "id": -51 + }, + { + "name": "minecraft:element_41", + "id": -52 + }, + { + "name": "minecraft:element_42", + "id": -53 + }, + { + "name": "minecraft:element_43", + "id": -54 + }, + { + "name": "minecraft:element_44", + "id": -55 + }, + { + "name": "minecraft:element_45", + "id": -56 + }, + { + "name": "minecraft:element_46", + "id": -57 + }, + { + "name": "minecraft:element_47", + "id": -58 + }, + { + "name": "minecraft:element_48", + "id": -59 + }, + { + "name": "minecraft:element_49", + "id": -60 + }, + { + "name": "minecraft:element_5", + "id": -16 + }, + { + "name": "minecraft:element_50", + "id": -61 + }, + { + "name": "minecraft:element_51", + "id": -62 + }, + { + "name": "minecraft:element_52", + "id": -63 + }, + { + "name": "minecraft:element_53", + "id": -64 + }, + { + "name": "minecraft:element_54", + "id": -65 + }, + { + "name": "minecraft:element_55", + "id": -66 + }, + { + "name": "minecraft:element_56", + "id": -67 + }, + { + "name": "minecraft:element_57", + "id": -68 + }, + { + "name": "minecraft:element_58", + "id": -69 + }, + { + "name": "minecraft:element_59", + "id": -70 + }, + { + "name": "minecraft:element_6", + "id": -17 + }, + { + "name": "minecraft:element_60", + "id": -71 + }, + { + "name": "minecraft:element_61", + "id": -72 + }, + { + "name": "minecraft:element_62", + "id": -73 + }, + { + "name": "minecraft:element_63", + "id": -74 + }, + { + "name": "minecraft:element_64", + "id": -75 + }, + { + "name": "minecraft:element_65", + "id": -76 + }, + { + "name": "minecraft:element_66", + "id": -77 + }, + { + "name": "minecraft:element_67", + "id": -78 + }, + { + "name": "minecraft:element_68", + "id": -79 + }, + { + "name": "minecraft:element_69", + "id": -80 + }, + { + "name": "minecraft:element_7", + "id": -18 + }, + { + "name": "minecraft:element_70", + "id": -81 + }, + { + "name": "minecraft:element_71", + "id": -82 + }, + { + "name": "minecraft:element_72", + "id": -83 + }, + { + "name": "minecraft:element_73", + "id": -84 + }, + { + "name": "minecraft:element_74", + "id": -85 + }, + { + "name": "minecraft:element_75", + "id": -86 + }, + { + "name": "minecraft:element_76", + "id": -87 + }, + { + "name": "minecraft:element_77", + "id": -88 + }, + { + "name": "minecraft:element_78", + "id": -89 + }, + { + "name": "minecraft:element_79", + "id": -90 + }, + { + "name": "minecraft:element_8", + "id": -19 + }, + { + "name": "minecraft:element_80", + "id": -91 + }, + { + "name": "minecraft:element_81", + "id": -92 + }, + { + "name": "minecraft:element_82", + "id": -93 + }, + { + "name": "minecraft:element_83", + "id": -94 + }, + { + "name": "minecraft:element_84", + "id": -95 + }, + { + "name": "minecraft:element_85", + "id": -96 + }, + { + "name": "minecraft:element_86", + "id": -97 + }, + { + "name": "minecraft:element_87", + "id": -98 + }, + { + "name": "minecraft:element_88", + "id": -99 + }, + { + "name": "minecraft:element_89", + "id": -100 + }, + { + "name": "minecraft:element_9", + "id": -20 + }, + { + "name": "minecraft:element_90", + "id": -101 + }, + { + "name": "minecraft:element_91", + "id": -102 + }, + { + "name": "minecraft:element_92", + "id": -103 + }, + { + "name": "minecraft:element_93", + "id": -104 + }, + { + "name": "minecraft:element_94", + "id": -105 + }, + { + "name": "minecraft:element_95", + "id": -106 + }, + { + "name": "minecraft:element_96", + "id": -107 + }, + { + "name": "minecraft:element_97", + "id": -108 + }, + { + "name": "minecraft:element_98", + "id": -109 + }, + { + "name": "minecraft:element_99", + "id": -110 + }, + { + "name": "minecraft:elytra", + "id": 571 + }, + { + "name": "minecraft:emerald", + "id": 519 + }, + { + "name": "minecraft:emerald_block", + "id": 133 + }, + { + "name": "minecraft:emerald_ore", + "id": 129 + }, + { + "name": "minecraft:empty_map", + "id": 522 + }, + { + "name": "minecraft:enchanted_book", + "id": 528 + }, + { + "name": "minecraft:enchanted_golden_apple", + "id": 259 + }, + { + "name": "minecraft:enchanting_table", + "id": 116 + }, + { + "name": "minecraft:end_brick_stairs", + "id": -178 + }, + { + "name": "minecraft:end_bricks", + "id": 206 + }, + { + "name": "minecraft:end_crystal", + "id": 718 + }, + { + "name": "minecraft:end_gateway", + "id": 209 + }, + { + "name": "minecraft:end_portal", + "id": 119 + }, + { + "name": "minecraft:end_portal_frame", + "id": 120 + }, + { + "name": "minecraft:end_rod", + "id": 208 + }, + { + "name": "minecraft:end_stone", + "id": 121 + }, + { + "name": "minecraft:ender_chest", + "id": 130 + }, + { + "name": "minecraft:ender_dragon_spawn_egg", + "id": 508 + }, + { + "name": "minecraft:ender_eye", + "id": 435 + }, + { + "name": "minecraft:ender_pearl", + "id": 424 + }, + { + "name": "minecraft:enderman_spawn_egg", + "id": 444 + }, + { + "name": "minecraft:endermite_spawn_egg", + "id": 462 + }, + { + "name": "minecraft:evoker_spawn_egg", + "id": 477 + }, + { + "name": "minecraft:experience_bottle", + "id": 515 + }, + { + "name": "minecraft:explorer_pottery_sherd", + "id": 670 + }, + { + "name": "minecraft:exposed_copper", + "id": -341 + }, + { + "name": "minecraft:exposed_cut_copper", + "id": -348 + }, + { + "name": "minecraft:exposed_cut_copper_slab", + "id": -362 + }, + { + "name": "minecraft:exposed_cut_copper_stairs", + "id": -355 + }, + { + "name": "minecraft:exposed_double_cut_copper_slab", + "id": -369 + }, + { + "name": "minecraft:eye_armor_trim_smithing_template", + "id": 690 + }, + { + "name": "minecraft:farmland", + "id": 60 + }, + { + "name": "minecraft:feather", + "id": 329 + }, + { + "name": "minecraft:fence", + "id": 706 + }, + { + "name": "minecraft:fence_gate", + "id": 107 + }, + { + "name": "minecraft:fermented_spider_eye", + "id": 430 + }, + { + "name": "minecraft:field_masoned_banner_pattern", + "id": 592 + }, + { + "name": "minecraft:filled_map", + "id": 422 + }, + { + "name": "minecraft:fire", + "id": 51 + }, + { + "name": "minecraft:fire_charge", + "id": 516 + }, + { + "name": "minecraft:fire_coral", + "id": -583 + }, + { + "name": "minecraft:firework_rocket", + "id": 526 + }, + { + "name": "minecraft:firework_star", + "id": 527 + }, + { + "name": "minecraft:fishing_rod", + "id": 394 + }, + { + "name": "minecraft:fletching_table", + "id": -201 + }, + { + "name": "minecraft:flint", + "id": 358 + }, + { + "name": "minecraft:flint_and_steel", + "id": 301 + }, + { + "name": "minecraft:flower_banner_pattern", + "id": 588 + }, + { + "name": "minecraft:flower_pot", + "id": 521 + }, + { + "name": "minecraft:flowering_azalea", + "id": -338 + }, + { + "name": "minecraft:flowing_lava", + "id": 10 + }, + { + "name": "minecraft:flowing_water", + "id": 8 + }, + { + "name": "minecraft:fox_spawn_egg", + "id": 492 + }, + { + "name": "minecraft:frame", + "id": 520 + }, + { + "name": "minecraft:friend_pottery_sherd", + "id": 671 + }, + { + "name": "minecraft:frog_spawn", + "id": -468 + }, + { + "name": "minecraft:frog_spawn_egg", + "id": 635 + }, + { + "name": "minecraft:frosted_ice", + "id": 207 + }, + { + "name": "minecraft:furnace", + "id": 61 + }, + { + "name": "minecraft:ghast_spawn_egg", + "id": 456 + }, + { + "name": "minecraft:ghast_tear", + "id": 426 + }, + { + "name": "minecraft:gilded_blackstone", + "id": -281 + }, + { + "name": "minecraft:glass", + "id": 20 + }, + { + "name": "minecraft:glass_bottle", + "id": 429 + }, + { + "name": "minecraft:glass_pane", + "id": 102 + }, + { + "name": "minecraft:glistering_melon_slice", + "id": 436 + }, + { + "name": "minecraft:globe_banner_pattern", + "id": 595 + }, + { + "name": "minecraft:glow_berries", + "id": 719 + }, + { + "name": "minecraft:glow_frame", + "id": 630 + }, + { + "name": "minecraft:glow_ink_sac", + "id": 510 + }, + { + "name": "minecraft:glow_lichen", + "id": -411 + }, + { + "name": "minecraft:glow_squid_spawn_egg", + "id": 505 + }, + { + "name": "minecraft:glow_stick", + "id": 608 + }, + { + "name": "minecraft:glowingobsidian", + "id": 246 + }, + { + "name": "minecraft:glowstone", + "id": 89 + }, + { + "name": "minecraft:glowstone_dust", + "id": 396 + }, + { + "name": "minecraft:goat_horn", + "id": 634 + }, + { + "name": "minecraft:goat_spawn_egg", + "id": 504 + }, + { + "name": "minecraft:gold_block", + "id": 41 + }, + { + "name": "minecraft:gold_ingot", + "id": 308 + }, + { + "name": "minecraft:gold_nugget", + "id": 427 + }, + { + "name": "minecraft:gold_ore", + "id": 14 + }, + { + "name": "minecraft:golden_apple", + "id": 258 + }, + { + "name": "minecraft:golden_axe", + "id": 327 + }, + { + "name": "minecraft:golden_boots", + "id": 356 + }, + { + "name": "minecraft:golden_carrot", + "id": 283 + }, + { + "name": "minecraft:golden_chestplate", + "id": 354 + }, + { + "name": "minecraft:golden_helmet", + "id": 353 + }, + { + "name": "minecraft:golden_hoe", + "id": 335 + }, + { + "name": "minecraft:golden_horse_armor", + "id": 539 + }, + { + "name": "minecraft:golden_leggings", + "id": 355 + }, + { + "name": "minecraft:golden_pickaxe", + "id": 326 + }, + { + "name": "minecraft:golden_rail", + "id": 27 + }, + { + "name": "minecraft:golden_shovel", + "id": 325 + }, + { + "name": "minecraft:golden_sword", + "id": 324 + }, + { + "name": "minecraft:granite_stairs", + "id": -169 + }, + { + "name": "minecraft:grass", + "id": 2 + }, + { + "name": "minecraft:grass_path", + "id": 198 + }, + { + "name": "minecraft:gravel", + "id": 13 + }, + { + "name": "minecraft:gray_candle", + "id": -420 + }, + { + "name": "minecraft:gray_candle_cake", + "id": -437 + }, + { + "name": "minecraft:gray_carpet", + "id": -603 + }, + { + "name": "minecraft:gray_concrete", + "id": -634 + }, + { + "name": "minecraft:gray_concrete_powder", + "id": -715 + }, + { + "name": "minecraft:gray_dye", + "id": 405 + }, + { + "name": "minecraft:gray_glazed_terracotta", + "id": 227 + }, + { + "name": "minecraft:gray_shulker_box", + "id": -619 + }, + { + "name": "minecraft:gray_stained_glass", + "id": -679 + }, + { + "name": "minecraft:gray_stained_glass_pane", + "id": -649 + }, + { + "name": "minecraft:gray_terracotta", + "id": -730 + }, + { + "name": "minecraft:gray_wool", + "id": -553 + }, + { + "name": "minecraft:green_candle", + "id": -426 + }, + { + "name": "minecraft:green_candle_cake", + "id": -443 + }, + { + "name": "minecraft:green_carpet", + "id": -609 + }, + { + "name": "minecraft:green_concrete", + "id": -640 + }, + { + "name": "minecraft:green_concrete_powder", + "id": -721 + }, + { + "name": "minecraft:green_dye", + "id": 399 + }, + { + "name": "minecraft:green_glazed_terracotta", + "id": 233 + }, + { + "name": "minecraft:green_shulker_box", + "id": -625 + }, + { + "name": "minecraft:green_stained_glass", + "id": -685 + }, + { + "name": "minecraft:green_stained_glass_pane", + "id": -655 + }, + { + "name": "minecraft:green_terracotta", + "id": -736 + }, + { + "name": "minecraft:green_wool", + "id": -560 + }, + { + "name": "minecraft:grindstone", + "id": -195 + }, + { + "name": "minecraft:guardian_spawn_egg", + "id": 463 + }, + { + "name": "minecraft:gunpowder", + "id": 330 + }, + { + "name": "minecraft:hanging_roots", + "id": -319 + }, + { + "name": "minecraft:hard_glass", + "id": 253 + }, + { + "name": "minecraft:hard_glass_pane", + "id": 190 + }, + { + "name": "minecraft:hard_stained_glass", + "id": 254 + }, + { + "name": "minecraft:hard_stained_glass_pane", + "id": 191 + }, + { + "name": "minecraft:hardened_clay", + "id": 172 + }, + { + "name": "minecraft:hay_block", + "id": 170 + }, + { + "name": "minecraft:heart_of_the_sea", + "id": 578 + }, + { + "name": "minecraft:heart_pottery_sherd", + "id": 672 + }, + { + "name": "minecraft:heartbreak_pottery_sherd", + "id": 673 + }, + { + "name": "minecraft:heavy_weighted_pressure_plate", + "id": 148 + }, + { + "name": "minecraft:hoglin_spawn_egg", + "id": 498 + }, + { + "name": "minecraft:honey_block", + "id": -220 + }, + { + "name": "minecraft:honey_bottle", + "id": 599 + }, + { + "name": "minecraft:honeycomb", + "id": 598 + }, + { + "name": "minecraft:honeycomb_block", + "id": -221 + }, + { + "name": "minecraft:hopper", + "id": 534 + }, + { + "name": "minecraft:hopper_minecart", + "id": 533 + }, + { + "name": "minecraft:horn_coral", + "id": -584 + }, + { + "name": "minecraft:horse_spawn_egg", + "id": 460 + }, + { + "name": "minecraft:host_armor_trim_smithing_template", + "id": 700 + }, + { + "name": "minecraft:howl_pottery_sherd", + "id": 674 + }, + { + "name": "minecraft:husk_spawn_egg", + "id": 465 + }, + { + "name": "minecraft:ice", + "id": 79 + }, + { + "name": "minecraft:ice_bomb", + "id": 602 + }, + { + "name": "minecraft:infested_deepslate", + "id": -454 + }, + { + "name": "minecraft:info_update", + "id": 248 + }, + { + "name": "minecraft:info_update2", + "id": 249 + }, + { + "name": "minecraft:ink_sac", + "id": 415 + }, + { + "name": "minecraft:invisible_bedrock", + "id": 95 + }, + { + "name": "minecraft:iron_axe", + "id": 300 + }, + { + "name": "minecraft:iron_bars", + "id": 101 + }, + { + "name": "minecraft:iron_block", + "id": 42 + }, + { + "name": "minecraft:iron_boots", + "id": 348 + }, + { + "name": "minecraft:iron_chestplate", + "id": 346 + }, + { + "name": "minecraft:iron_door", + "id": 374 + }, + { + "name": "minecraft:iron_golem_spawn_egg", + "id": 506 + }, + { + "name": "minecraft:iron_helmet", + "id": 345 + }, + { + "name": "minecraft:iron_hoe", + "id": 333 + }, + { + "name": "minecraft:iron_horse_armor", + "id": 538 + }, + { + "name": "minecraft:iron_ingot", + "id": 307 + }, + { + "name": "minecraft:iron_leggings", + "id": 347 + }, + { + "name": "minecraft:iron_nugget", + "id": 576 + }, + { + "name": "minecraft:iron_ore", + "id": 15 + }, + { + "name": "minecraft:iron_pickaxe", + "id": 299 + }, + { + "name": "minecraft:iron_shovel", + "id": 298 + }, + { + "name": "minecraft:iron_sword", + "id": 309 + }, + { + "name": "minecraft:iron_trapdoor", + "id": 167 + }, + { + "name": "minecraft:item.acacia_door", + "id": 196 + }, + { + "name": "minecraft:item.bed", + "id": 26 + }, + { + "name": "minecraft:item.beetroot", + "id": 244 + }, + { + "name": "minecraft:item.birch_door", + "id": 194 + }, + { + "name": "minecraft:item.brewing_stand", + "id": 117 + }, + { + "name": "minecraft:item.cake", + "id": 92 + }, + { + "name": "minecraft:item.camera", + "id": 242 + }, + { + "name": "minecraft:item.campfire", + "id": -209 + }, + { + "name": "minecraft:item.cauldron", + "id": 118 + }, + { + "name": "minecraft:item.chain", + "id": -286 + }, + { + "name": "minecraft:item.crimson_door", + "id": -244 + }, + { + "name": "minecraft:item.dark_oak_door", + "id": 197 + }, + { + "name": "minecraft:item.flower_pot", + "id": 140 + }, + { + "name": "minecraft:item.frame", + "id": 199 + }, + { + "name": "minecraft:item.glow_frame", + "id": -339 + }, + { + "name": "minecraft:item.hopper", + "id": 154 + }, + { + "name": "minecraft:item.iron_door", + "id": 71 + }, + { + "name": "minecraft:item.jungle_door", + "id": 195 + }, + { + "name": "minecraft:item.kelp", + "id": -138 + }, + { + "name": "minecraft:item.mangrove_door", + "id": -493 + }, + { + "name": "minecraft:item.nether_sprouts", + "id": -238 + }, + { + "name": "minecraft:item.nether_wart", + "id": 115 + }, + { + "name": "minecraft:item.reeds", + "id": 83 + }, + { + "name": "minecraft:item.skull", + "id": 144 + }, + { + "name": "minecraft:item.soul_campfire", + "id": -290 + }, + { + "name": "minecraft:item.spruce_door", + "id": 193 + }, + { + "name": "minecraft:item.warped_door", + "id": -245 + }, + { + "name": "minecraft:item.wheat", + "id": 59 + }, + { + "name": "minecraft:item.wooden_door", + "id": 64 + }, + { + "name": "minecraft:jigsaw", + "id": -211 + }, + { + "name": "minecraft:jukebox", + "id": 84 + }, + { + "name": "minecraft:jungle_boat", + "id": 379 + }, + { + "name": "minecraft:jungle_button", + "id": -143 + }, + { + "name": "minecraft:jungle_chest_boat", + "id": 647 + }, + { + "name": "minecraft:jungle_door", + "id": 562 + }, + { + "name": "minecraft:jungle_fence", + "id": -578 + }, + { + "name": "minecraft:jungle_fence_gate", + "id": 185 + }, + { + "name": "minecraft:jungle_hanging_sign", + "id": -503 + }, + { + "name": "minecraft:jungle_log", + "id": -571 + }, + { + "name": "minecraft:jungle_pressure_plate", + "id": -153 + }, + { + "name": "minecraft:jungle_sign", + "id": 585 + }, + { + "name": "minecraft:jungle_stairs", + "id": 136 + }, + { + "name": "minecraft:jungle_standing_sign", + "id": -188 + }, + { + "name": "minecraft:jungle_trapdoor", + "id": -148 + }, + { + "name": "minecraft:jungle_wall_sign", + "id": -189 + }, + { + "name": "minecraft:kelp", + "id": 384 + }, + { + "name": "minecraft:ladder", + "id": 65 + }, + { + "name": "minecraft:lantern", + "id": -208 + }, + { + "name": "minecraft:lapis_block", + "id": 22 + }, + { + "name": "minecraft:lapis_lazuli", + "id": 416 + }, + { + "name": "minecraft:lapis_ore", + "id": 21 + }, + { + "name": "minecraft:large_amethyst_bud", + "id": -330 + }, + { + "name": "minecraft:lava", + "id": 11 + }, + { + "name": "minecraft:lava_bucket", + "id": 365 + }, + { + "name": "minecraft:lead", + "id": 554 + }, + { + "name": "minecraft:leather", + "id": 383 + }, + { + "name": "minecraft:leather_boots", + "id": 340 + }, + { + "name": "minecraft:leather_chestplate", + "id": 338 + }, + { + "name": "minecraft:leather_helmet", + "id": 337 + }, + { + "name": "minecraft:leather_horse_armor", + "id": 537 + }, + { + "name": "minecraft:leather_leggings", + "id": 339 + }, + { + "name": "minecraft:leaves", + "id": 18 + }, + { + "name": "minecraft:leaves2", + "id": 161 + }, + { + "name": "minecraft:lectern", + "id": -194 + }, + { + "name": "minecraft:lever", + "id": 69 + }, + { + "name": "minecraft:light_block", + "id": -215 + }, + { + "name": "minecraft:light_blue_candle", + "id": -416 + }, + { + "name": "minecraft:light_blue_candle_cake", + "id": -433 + }, + { + "name": "minecraft:light_blue_carpet", + "id": -599 + }, + { + "name": "minecraft:light_blue_concrete", + "id": -630 + }, + { + "name": "minecraft:light_blue_concrete_powder", + "id": -711 + }, + { + "name": "minecraft:light_blue_dye", + "id": 409 + }, + { + "name": "minecraft:light_blue_glazed_terracotta", + "id": 223 + }, + { + "name": "minecraft:light_blue_shulker_box", + "id": -615 + }, + { + "name": "minecraft:light_blue_stained_glass", + "id": -675 + }, + { + "name": "minecraft:light_blue_stained_glass_pane", + "id": -645 + }, + { + "name": "minecraft:light_blue_terracotta", + "id": -726 + }, + { + "name": "minecraft:light_blue_wool", + "id": -562 + }, + { + "name": "minecraft:light_gray_candle", + "id": -421 + }, + { + "name": "minecraft:light_gray_candle_cake", + "id": -438 + }, + { + "name": "minecraft:light_gray_carpet", + "id": -604 + }, + { + "name": "minecraft:light_gray_concrete", + "id": -635 + }, + { + "name": "minecraft:light_gray_concrete_powder", + "id": -716 + }, + { + "name": "minecraft:light_gray_dye", + "id": 404 + }, + { + "name": "minecraft:light_gray_shulker_box", + "id": -620 + }, + { + "name": "minecraft:light_gray_stained_glass", + "id": -680 + }, + { + "name": "minecraft:light_gray_stained_glass_pane", + "id": -650 + }, + { + "name": "minecraft:light_gray_terracotta", + "id": -731 + }, + { + "name": "minecraft:light_gray_wool", + "id": -552 + }, + { + "name": "minecraft:light_weighted_pressure_plate", + "id": 147 + }, + { + "name": "minecraft:lightning_rod", + "id": -312 + }, + { + "name": "minecraft:lime_candle", + "id": -418 + }, + { + "name": "minecraft:lime_candle_cake", + "id": -435 + }, + { + "name": "minecraft:lime_carpet", + "id": -601 + }, + { + "name": "minecraft:lime_concrete", + "id": -632 + }, + { + "name": "minecraft:lime_concrete_powder", + "id": -713 + }, + { + "name": "minecraft:lime_dye", + "id": 407 + }, + { + "name": "minecraft:lime_glazed_terracotta", + "id": 225 + }, + { + "name": "minecraft:lime_shulker_box", + "id": -617 + }, + { + "name": "minecraft:lime_stained_glass", + "id": -677 + }, + { + "name": "minecraft:lime_stained_glass_pane", + "id": -647 + }, + { + "name": "minecraft:lime_terracotta", + "id": -728 + }, + { + "name": "minecraft:lime_wool", + "id": -559 + }, + { + "name": "minecraft:lingering_potion", + "id": 569 + }, + { + "name": "minecraft:lit_blast_furnace", + "id": -214 + }, + { + "name": "minecraft:lit_deepslate_redstone_ore", + "id": -404 + }, + { + "name": "minecraft:lit_furnace", + "id": 62 + }, + { + "name": "minecraft:lit_pumpkin", + "id": 91 + }, + { + "name": "minecraft:lit_redstone_lamp", + "id": 124 + }, + { + "name": "minecraft:lit_redstone_ore", + "id": 74 + }, + { + "name": "minecraft:lit_smoker", + "id": -199 + }, + { + "name": "minecraft:llama_spawn_egg", + "id": 475 + }, + { + "name": "minecraft:lodestone", + "id": -222 + }, + { + "name": "minecraft:lodestone_compass", + "id": 609 + }, + { + "name": "minecraft:log", + "id": 705 + }, + { + "name": "minecraft:log2", + "id": 708 + }, + { + "name": "minecraft:loom", + "id": -204 + }, + { + "name": "minecraft:magenta_candle", + "id": -415 + }, + { + "name": "minecraft:magenta_candle_cake", + "id": -432 + }, + { + "name": "minecraft:magenta_carpet", + "id": -598 + }, + { + "name": "minecraft:magenta_concrete", + "id": -629 + }, + { + "name": "minecraft:magenta_concrete_powder", + "id": -710 + }, + { + "name": "minecraft:magenta_dye", + "id": 410 + }, + { + "name": "minecraft:magenta_glazed_terracotta", + "id": 222 + }, + { + "name": "minecraft:magenta_shulker_box", + "id": -614 + }, + { + "name": "minecraft:magenta_stained_glass", + "id": -674 + }, + { + "name": "minecraft:magenta_stained_glass_pane", + "id": -644 + }, + { + "name": "minecraft:magenta_terracotta", + "id": -725 + }, + { + "name": "minecraft:magenta_wool", + "id": -565 + }, + { + "name": "minecraft:magma", + "id": 213 + }, + { + "name": "minecraft:magma_cream", + "id": 432 + }, + { + "name": "minecraft:magma_cube_spawn_egg", + "id": 457 + }, + { + "name": "minecraft:mangrove_boat", + "id": 642 + }, + { + "name": "minecraft:mangrove_button", + "id": -487 + }, + { + "name": "minecraft:mangrove_chest_boat", + "id": 651 + }, + { + "name": "minecraft:mangrove_door", + "id": 640 + }, + { + "name": "minecraft:mangrove_double_slab", + "id": -499 + }, + { + "name": "minecraft:mangrove_fence", + "id": -491 + }, + { + "name": "minecraft:mangrove_fence_gate", + "id": -492 + }, + { + "name": "minecraft:mangrove_hanging_sign", + "id": -508 + }, + { + "name": "minecraft:mangrove_leaves", + "id": -472 + }, + { + "name": "minecraft:mangrove_log", + "id": -484 + }, + { + "name": "minecraft:mangrove_planks", + "id": -486 + }, + { + "name": "minecraft:mangrove_pressure_plate", + "id": -490 + }, + { + "name": "minecraft:mangrove_propagule", + "id": -474 + }, + { + "name": "minecraft:mangrove_roots", + "id": -482 + }, + { + "name": "minecraft:mangrove_sign", + "id": 641 + }, + { + "name": "minecraft:mangrove_slab", + "id": -489 + }, + { + "name": "minecraft:mangrove_stairs", + "id": -488 + }, + { + "name": "minecraft:mangrove_standing_sign", + "id": -494 + }, + { + "name": "minecraft:mangrove_trapdoor", + "id": -496 + }, + { + "name": "minecraft:mangrove_wall_sign", + "id": -495 + }, + { + "name": "minecraft:mangrove_wood", + "id": -497 + }, + { + "name": "minecraft:medicine", + "id": 606 + }, + { + "name": "minecraft:medium_amethyst_bud", + "id": -331 + }, + { + "name": "minecraft:melon_block", + "id": 103 + }, + { + "name": "minecraft:melon_seeds", + "id": 293 + }, + { + "name": "minecraft:melon_slice", + "id": 272 + }, + { + "name": "minecraft:melon_stem", + "id": 105 + }, + { + "name": "minecraft:milk_bucket", + "id": 363 + }, + { + "name": "minecraft:minecart", + "id": 372 + }, + { + "name": "minecraft:miner_pottery_sherd", + "id": 675 + }, + { + "name": "minecraft:mob_spawner", + "id": 52 + }, + { + "name": "minecraft:mojang_banner_pattern", + "id": 591 + }, + { + "name": "minecraft:monster_egg", + "id": 97 + }, + { + "name": "minecraft:mooshroom_spawn_egg", + "id": 442 + }, + { + "name": "minecraft:moss_block", + "id": -320 + }, + { + "name": "minecraft:moss_carpet", + "id": -335 + }, + { + "name": "minecraft:mossy_cobblestone", + "id": 48 + }, + { + "name": "minecraft:mossy_cobblestone_stairs", + "id": -179 + }, + { + "name": "minecraft:mossy_stone_brick_stairs", + "id": -175 + }, + { + "name": "minecraft:mourner_pottery_sherd", + "id": 676 + }, + { + "name": "minecraft:moving_block", + "id": 250 + }, + { + "name": "minecraft:mud", + "id": -473 + }, + { + "name": "minecraft:mud_brick_double_slab", + "id": -479 + }, + { + "name": "minecraft:mud_brick_slab", + "id": -478 + }, + { + "name": "minecraft:mud_brick_stairs", + "id": -480 + }, + { + "name": "minecraft:mud_brick_wall", + "id": -481 + }, + { + "name": "minecraft:mud_bricks", + "id": -475 + }, + { + "name": "minecraft:muddy_mangrove_roots", + "id": -483 + }, + { + "name": "minecraft:mule_spawn_egg", + "id": 468 + }, + { + "name": "minecraft:mushroom_stew", + "id": 260 + }, + { + "name": "minecraft:music_disc_11", + "id": 551 + }, + { + "name": "minecraft:music_disc_13", + "id": 541 + }, + { + "name": "minecraft:music_disc_5", + "id": 643 + }, + { + "name": "minecraft:music_disc_blocks", + "id": 543 + }, + { + "name": "minecraft:music_disc_cat", + "id": 542 + }, + { + "name": "minecraft:music_disc_chirp", + "id": 544 + }, + { + "name": "minecraft:music_disc_far", + "id": 545 + }, + { + "name": "minecraft:music_disc_mall", + "id": 546 + }, + { + "name": "minecraft:music_disc_mellohi", + "id": 547 + }, + { + "name": "minecraft:music_disc_otherside", + "id": 633 + }, + { + "name": "minecraft:music_disc_pigstep", + "id": 627 + }, + { + "name": "minecraft:music_disc_relic", + "id": 701 + }, + { + "name": "minecraft:music_disc_stal", + "id": 548 + }, + { + "name": "minecraft:music_disc_strad", + "id": 549 + }, + { + "name": "minecraft:music_disc_wait", + "id": 552 + }, + { + "name": "minecraft:music_disc_ward", + "id": 550 + }, + { + "name": "minecraft:mutton", + "id": 557 + }, + { + "name": "minecraft:mycelium", + "id": 110 + }, + { + "name": "minecraft:name_tag", + "id": 555 + }, + { + "name": "minecraft:nautilus_shell", + "id": 577 + }, + { + "name": "minecraft:nether_brick", + "id": 112 + }, + { + "name": "minecraft:nether_brick_fence", + "id": 113 + }, + { + "name": "minecraft:nether_brick_stairs", + "id": 114 + }, + { + "name": "minecraft:nether_gold_ore", + "id": -288 + }, + { + "name": "minecraft:nether_sprouts", + "id": 628 + }, + { + "name": "minecraft:nether_star", + "id": 525 + }, + { + "name": "minecraft:nether_wart", + "id": 294 + }, + { + "name": "minecraft:nether_wart_block", + "id": 214 + }, + { + "name": "minecraft:netherbrick", + "id": 530 + }, + { + "name": "minecraft:netherite_axe", + "id": 613 + }, + { + "name": "minecraft:netherite_block", + "id": -270 + }, + { + "name": "minecraft:netherite_boots", + "id": 619 + }, + { + "name": "minecraft:netherite_chestplate", + "id": 617 + }, + { + "name": "minecraft:netherite_helmet", + "id": 616 + }, + { + "name": "minecraft:netherite_hoe", + "id": 614 + }, + { + "name": "minecraft:netherite_ingot", + "id": 615 + }, + { + "name": "minecraft:netherite_leggings", + "id": 618 + }, + { + "name": "minecraft:netherite_pickaxe", + "id": 612 + }, + { + "name": "minecraft:netherite_scrap", + "id": 620 + }, + { + "name": "minecraft:netherite_shovel", + "id": 611 + }, + { + "name": "minecraft:netherite_sword", + "id": 610 + }, + { + "name": "minecraft:netherite_upgrade_smithing_template", + "id": 684 + }, + { + "name": "minecraft:netherrack", + "id": 87 + }, + { + "name": "minecraft:netherreactor", + "id": 247 + }, + { + "name": "minecraft:normal_stone_stairs", + "id": -180 + }, + { + "name": "minecraft:noteblock", + "id": 25 + }, + { + "name": "minecraft:npc_spawn_egg", + "id": 472 + }, + { + "name": "minecraft:oak_boat", + "id": 377 + }, + { + "name": "minecraft:oak_chest_boat", + "id": 645 + }, + { + "name": "minecraft:oak_fence", + "id": 85 + }, + { + "name": "minecraft:oak_hanging_sign", + "id": -500 + }, + { + "name": "minecraft:oak_log", + "id": 17 + }, + { + "name": "minecraft:oak_sign", + "id": 360 + }, + { + "name": "minecraft:oak_stairs", + "id": 53 + }, + { + "name": "minecraft:observer", + "id": 251 + }, + { + "name": "minecraft:obsidian", + "id": 49 + }, + { + "name": "minecraft:ocelot_spawn_egg", + "id": 453 + }, + { + "name": "minecraft:ochre_froglight", + "id": -471 + }, + { + "name": "minecraft:orange_candle", + "id": -414 + }, + { + "name": "minecraft:orange_candle_cake", + "id": -431 + }, + { + "name": "minecraft:orange_carpet", + "id": -597 + }, + { + "name": "minecraft:orange_concrete", + "id": -628 + }, + { + "name": "minecraft:orange_concrete_powder", + "id": -709 + }, + { + "name": "minecraft:orange_dye", + "id": 411 + }, + { + "name": "minecraft:orange_glazed_terracotta", + "id": 221 + }, + { + "name": "minecraft:orange_shulker_box", + "id": -613 + }, + { + "name": "minecraft:orange_stained_glass", + "id": -673 + }, + { + "name": "minecraft:orange_stained_glass_pane", + "id": -643 + }, + { + "name": "minecraft:orange_terracotta", + "id": -724 + }, + { + "name": "minecraft:orange_wool", + "id": -557 + }, + { + "name": "minecraft:oxidized_copper", + "id": -343 + }, + { + "name": "minecraft:oxidized_cut_copper", + "id": -350 + }, + { + "name": "minecraft:oxidized_cut_copper_slab", + "id": -364 + }, + { + "name": "minecraft:oxidized_cut_copper_stairs", + "id": -357 + }, + { + "name": "minecraft:oxidized_double_cut_copper_slab", + "id": -371 + }, + { + "name": "minecraft:packed_ice", + "id": 174 + }, + { + "name": "minecraft:packed_mud", + "id": -477 + }, + { + "name": "minecraft:painting", + "id": 359 + }, + { + "name": "minecraft:panda_spawn_egg", + "id": 491 + }, + { + "name": "minecraft:paper", + "id": 388 + }, + { + "name": "minecraft:parrot_spawn_egg", + "id": 480 + }, + { + "name": "minecraft:pearlescent_froglight", + "id": -469 + }, + { + "name": "minecraft:phantom_membrane", + "id": 581 + }, + { + "name": "minecraft:phantom_spawn_egg", + "id": 488 + }, + { + "name": "minecraft:pig_spawn_egg", + "id": 439 + }, + { + "name": "minecraft:piglin_banner_pattern", + "id": 594 + }, + { + "name": "minecraft:piglin_brute_spawn_egg", + "id": 501 + }, + { + "name": "minecraft:piglin_spawn_egg", + "id": 499 + }, + { + "name": "minecraft:pillager_spawn_egg", + "id": 493 + }, + { + "name": "minecraft:pink_candle", + "id": -419 + }, + { + "name": "minecraft:pink_candle_cake", + "id": -436 + }, + { + "name": "minecraft:pink_carpet", + "id": -602 + }, + { + "name": "minecraft:pink_concrete", + "id": -633 + }, + { + "name": "minecraft:pink_concrete_powder", + "id": -714 + }, + { + "name": "minecraft:pink_dye", + "id": 406 + }, + { + "name": "minecraft:pink_glazed_terracotta", + "id": 226 + }, + { + "name": "minecraft:pink_petals", + "id": -549 + }, + { + "name": "minecraft:pink_shulker_box", + "id": -618 + }, + { + "name": "minecraft:pink_stained_glass", + "id": -678 + }, + { + "name": "minecraft:pink_stained_glass_pane", + "id": -648 + }, + { + "name": "minecraft:pink_terracotta", + "id": -729 + }, + { + "name": "minecraft:pink_wool", + "id": -566 + }, + { + "name": "minecraft:piston", + "id": 33 + }, + { + "name": "minecraft:piston_arm_collision", + "id": 34 + }, + { + "name": "minecraft:pitcher_crop", + "id": -574 + }, + { + "name": "minecraft:pitcher_plant", + "id": -612 + }, + { + "name": "minecraft:pitcher_pod", + "id": 297 + }, + { + "name": "minecraft:planks", + "id": 5 + }, + { + "name": "minecraft:plenty_pottery_sherd", + "id": 677 + }, + { + "name": "minecraft:podzol", + "id": 243 + }, + { + "name": "minecraft:pointed_dripstone", + "id": -308 + }, + { + "name": "minecraft:poisonous_potato", + "id": 282 + }, + { + "name": "minecraft:polar_bear_spawn_egg", + "id": 474 + }, + { + "name": "minecraft:polished_andesite_stairs", + "id": -174 + }, + { + "name": "minecraft:polished_basalt", + "id": -235 + }, + { + "name": "minecraft:polished_blackstone", + "id": -291 + }, + { + "name": "minecraft:polished_blackstone_brick_double_slab", + "id": -285 + }, + { + "name": "minecraft:polished_blackstone_brick_slab", + "id": -284 + }, + { + "name": "minecraft:polished_blackstone_brick_stairs", + "id": -275 + }, + { + "name": "minecraft:polished_blackstone_brick_wall", + "id": -278 + }, + { + "name": "minecraft:polished_blackstone_bricks", + "id": -274 + }, + { + "name": "minecraft:polished_blackstone_button", + "id": -296 + }, + { + "name": "minecraft:polished_blackstone_double_slab", + "id": -294 + }, + { + "name": "minecraft:polished_blackstone_pressure_plate", + "id": -295 + }, + { + "name": "minecraft:polished_blackstone_slab", + "id": -293 + }, + { + "name": "minecraft:polished_blackstone_stairs", + "id": -292 + }, + { + "name": "minecraft:polished_blackstone_wall", + "id": -297 + }, + { + "name": "minecraft:polished_deepslate", + "id": -383 + }, + { + "name": "minecraft:polished_deepslate_double_slab", + "id": -397 + }, + { + "name": "minecraft:polished_deepslate_slab", + "id": -384 + }, + { + "name": "minecraft:polished_deepslate_stairs", + "id": -385 + }, + { + "name": "minecraft:polished_deepslate_wall", + "id": -386 + }, + { + "name": "minecraft:polished_diorite_stairs", + "id": -173 + }, + { + "name": "minecraft:polished_granite_stairs", + "id": -172 + }, + { + "name": "minecraft:popped_chorus_fruit", + "id": 566 + }, + { + "name": "minecraft:porkchop", + "id": 262 + }, + { + "name": "minecraft:portal", + "id": 90 + }, + { + "name": "minecraft:potato", + "id": 280 + }, + { + "name": "minecraft:potatoes", + "id": 142 + }, + { + "name": "minecraft:potion", + "id": 428 + }, + { + "name": "minecraft:powder_snow", + "id": -306 + }, + { + "name": "minecraft:powder_snow_bucket", + "id": 370 + }, + { + "name": "minecraft:powered_comparator", + "id": 150 + }, + { + "name": "minecraft:powered_repeater", + "id": 94 + }, + { + "name": "minecraft:prismarine", + "id": 168 + }, + { + "name": "minecraft:prismarine_bricks_stairs", + "id": -4 + }, + { + "name": "minecraft:prismarine_crystals", + "id": 556 + }, + { + "name": "minecraft:prismarine_shard", + "id": 572 + }, + { + "name": "minecraft:prismarine_stairs", + "id": -2 + }, + { + "name": "minecraft:prize_pottery_sherd", + "id": 678 + }, + { + "name": "minecraft:pufferfish", + "id": 267 + }, + { + "name": "minecraft:pufferfish_bucket", + "id": 369 + }, + { + "name": "minecraft:pufferfish_spawn_egg", + "id": 483 + }, + { + "name": "minecraft:pumpkin", + "id": 86 + }, + { + "name": "minecraft:pumpkin_pie", + "id": 284 + }, + { + "name": "minecraft:pumpkin_seeds", + "id": 292 + }, + { + "name": "minecraft:pumpkin_stem", + "id": 104 + }, + { + "name": "minecraft:purple_candle", + "id": -423 + }, + { + "name": "minecraft:purple_candle_cake", + "id": -440 + }, + { + "name": "minecraft:purple_carpet", + "id": -606 + }, + { + "name": "minecraft:purple_concrete", + "id": -637 + }, + { + "name": "minecraft:purple_concrete_powder", + "id": -718 + }, + { + "name": "minecraft:purple_dye", + "id": 402 + }, + { + "name": "minecraft:purple_glazed_terracotta", + "id": 219 + }, + { + "name": "minecraft:purple_shulker_box", + "id": -622 + }, + { + "name": "minecraft:purple_stained_glass", + "id": -682 + }, + { + "name": "minecraft:purple_stained_glass_pane", + "id": -652 + }, + { + "name": "minecraft:purple_terracotta", + "id": -733 + }, + { + "name": "minecraft:purple_wool", + "id": -564 + }, + { + "name": "minecraft:purpur_block", + "id": 201 + }, + { + "name": "minecraft:purpur_stairs", + "id": 203 + }, + { + "name": "minecraft:quartz", + "id": 531 + }, + { + "name": "minecraft:quartz_block", + "id": 155 + }, + { + "name": "minecraft:quartz_bricks", + "id": -304 + }, + { + "name": "minecraft:quartz_ore", + "id": 153 + }, + { + "name": "minecraft:quartz_stairs", + "id": 156 + }, + { + "name": "minecraft:rabbit", + "id": 288 + }, + { + "name": "minecraft:rabbit_foot", + "id": 535 + }, + { + "name": "minecraft:rabbit_hide", + "id": 536 + }, + { + "name": "minecraft:rabbit_spawn_egg", + "id": 461 + }, + { + "name": "minecraft:rabbit_stew", + "id": 290 + }, + { + "name": "minecraft:rail", + "id": 66 + }, + { + "name": "minecraft:raiser_armor_trim_smithing_template", + "id": 698 + }, + { + "name": "minecraft:rapid_fertilizer", + "id": 604 + }, + { + "name": "minecraft:ravager_spawn_egg", + "id": 495 + }, + { + "name": "minecraft:raw_copper", + "id": 514 + }, + { + "name": "minecraft:raw_copper_block", + "id": -452 + }, + { + "name": "minecraft:raw_gold", + "id": 513 + }, + { + "name": "minecraft:raw_gold_block", + "id": -453 + }, + { + "name": "minecraft:raw_iron", + "id": 512 + }, + { + "name": "minecraft:raw_iron_block", + "id": -451 + }, + { + "name": "minecraft:recovery_compass", + "id": 653 + }, + { + "name": "minecraft:red_candle", + "id": -427 + }, + { + "name": "minecraft:red_candle_cake", + "id": -444 + }, + { + "name": "minecraft:red_carpet", + "id": -610 + }, + { + "name": "minecraft:red_concrete", + "id": -641 + }, + { + "name": "minecraft:red_concrete_powder", + "id": -722 + }, + { + "name": "minecraft:red_dye", + "id": 398 + }, + { + "name": "minecraft:red_flower", + "id": 38 + }, + { + "name": "minecraft:red_glazed_terracotta", + "id": 234 + }, + { + "name": "minecraft:red_mushroom", + "id": 40 + }, + { + "name": "minecraft:red_mushroom_block", + "id": 100 + }, + { + "name": "minecraft:red_nether_brick", + "id": 215 + }, + { + "name": "minecraft:red_nether_brick_stairs", + "id": -184 + }, + { + "name": "minecraft:red_sandstone", + "id": 179 + }, + { + "name": "minecraft:red_sandstone_stairs", + "id": 180 + }, + { + "name": "minecraft:red_shulker_box", + "id": -626 + }, + { + "name": "minecraft:red_stained_glass", + "id": -686 + }, + { + "name": "minecraft:red_stained_glass_pane", + "id": -656 + }, + { + "name": "minecraft:red_terracotta", + "id": -737 + }, + { + "name": "minecraft:red_wool", + "id": -556 + }, + { + "name": "minecraft:redstone", + "id": 375 + }, + { + "name": "minecraft:redstone_block", + "id": 152 + }, + { + "name": "minecraft:redstone_lamp", + "id": 123 + }, + { + "name": "minecraft:redstone_ore", + "id": 73 + }, + { + "name": "minecraft:redstone_torch", + "id": 76 + }, + { + "name": "minecraft:redstone_wire", + "id": 55 + }, + { + "name": "minecraft:reinforced_deepslate", + "id": -466 + }, + { + "name": "minecraft:repeater", + "id": 421 + }, + { + "name": "minecraft:repeating_command_block", + "id": 188 + }, + { + "name": "minecraft:reserved6", + "id": 255 + }, + { + "name": "minecraft:respawn_anchor", + "id": -272 + }, + { + "name": "minecraft:rib_armor_trim_smithing_template", + "id": 694 + }, + { + "name": "minecraft:rotten_flesh", + "id": 277 + }, + { + "name": "minecraft:saddle", + "id": 373 + }, + { + "name": "minecraft:salmon", + "id": 265 + }, + { + "name": "minecraft:salmon_bucket", + "id": 367 + }, + { + "name": "minecraft:salmon_spawn_egg", + "id": 484 + }, + { + "name": "minecraft:sand", + "id": 12 + }, + { + "name": "minecraft:sandstone", + "id": 24 + }, + { + "name": "minecraft:sandstone_stairs", + "id": 128 + }, + { + "name": "minecraft:sapling", + "id": 6 + }, + { + "name": "minecraft:scaffolding", + "id": -165 + }, + { + "name": "minecraft:sculk", + "id": -458 + }, + { + "name": "minecraft:sculk_catalyst", + "id": -460 + }, + { + "name": "minecraft:sculk_sensor", + "id": -307 + }, + { + "name": "minecraft:sculk_shrieker", + "id": -461 + }, + { + "name": "minecraft:sculk_vein", + "id": -459 + }, + { + "name": "minecraft:scute", + "id": 579 + }, + { + "name": "minecraft:sea_lantern", + "id": 169 + }, + { + "name": "minecraft:sea_pickle", + "id": -156 + }, + { + "name": "minecraft:seagrass", + "id": -130 + }, + { + "name": "minecraft:sentry_armor_trim_smithing_template", + "id": 685 + }, + { + "name": "minecraft:shaper_armor_trim_smithing_template", + "id": 699 + }, + { + "name": "minecraft:sheaf_pottery_sherd", + "id": 679 + }, + { + "name": "minecraft:shears", + "id": 423 + }, + { + "name": "minecraft:sheep_spawn_egg", + "id": 440 + }, + { + "name": "minecraft:shelter_pottery_sherd", + "id": 680 + }, + { + "name": "minecraft:shield", + "id": 357 + }, + { + "name": "minecraft:shroomlight", + "id": -230 + }, + { + "name": "minecraft:shulker_box", + "id": 713 + }, + { + "name": "minecraft:shulker_shell", + "id": 573 + }, + { + "name": "minecraft:shulker_spawn_egg", + "id": 471 + }, + { + "name": "minecraft:silence_armor_trim_smithing_template", + "id": 696 + }, + { + "name": "minecraft:silver_glazed_terracotta", + "id": 228 + }, + { + "name": "minecraft:silverfish_spawn_egg", + "id": 445 + }, + { + "name": "minecraft:skeleton_horse_spawn_egg", + "id": 469 + }, + { + "name": "minecraft:skeleton_spawn_egg", + "id": 446 + }, + { + "name": "minecraft:skull", + "id": 523 + }, + { + "name": "minecraft:skull_banner_pattern", + "id": 590 + }, + { + "name": "minecraft:skull_pottery_sherd", + "id": 681 + }, + { + "name": "minecraft:slime", + "id": 165 + }, + { + "name": "minecraft:slime_ball", + "id": 390 + }, + { + "name": "minecraft:slime_spawn_egg", + "id": 447 + }, + { + "name": "minecraft:small_amethyst_bud", + "id": -332 + }, + { + "name": "minecraft:small_dripleaf_block", + "id": -336 + }, + { + "name": "minecraft:smithing_table", + "id": -202 + }, + { + "name": "minecraft:smoker", + "id": -198 + }, + { + "name": "minecraft:smooth_basalt", + "id": -377 + }, + { + "name": "minecraft:smooth_quartz_stairs", + "id": -185 + }, + { + "name": "minecraft:smooth_red_sandstone_stairs", + "id": -176 + }, + { + "name": "minecraft:smooth_sandstone_stairs", + "id": -177 + }, + { + "name": "minecraft:smooth_stone", + "id": -183 + }, + { + "name": "minecraft:sniffer_egg", + "id": -596 + }, + { + "name": "minecraft:sniffer_spawn_egg", + "id": 502 + }, + { + "name": "minecraft:snort_pottery_sherd", + "id": 682 + }, + { + "name": "minecraft:snout_armor_trim_smithing_template", + "id": 693 + }, + { + "name": "minecraft:snow", + "id": 80 + }, + { + "name": "minecraft:snow_golem_spawn_egg", + "id": 507 + }, + { + "name": "minecraft:snow_layer", + "id": 78 + }, + { + "name": "minecraft:snowball", + "id": 376 + }, + { + "name": "minecraft:soul_campfire", + "id": 629 + }, + { + "name": "minecraft:soul_fire", + "id": -237 + }, + { + "name": "minecraft:soul_lantern", + "id": -269 + }, + { + "name": "minecraft:soul_sand", + "id": 88 + }, + { + "name": "minecraft:soul_soil", + "id": -236 + }, + { + "name": "minecraft:soul_torch", + "id": -268 + }, + { + "name": "minecraft:sparkler", + "id": 607 + }, + { + "name": "minecraft:spawn_egg", + "id": 717 + }, + { + "name": "minecraft:spider_eye", + "id": 278 + }, + { + "name": "minecraft:spider_spawn_egg", + "id": 448 + }, + { + "name": "minecraft:spire_armor_trim_smithing_template", + "id": 695 + }, + { + "name": "minecraft:splash_potion", + "id": 568 + }, + { + "name": "minecraft:sponge", + "id": 19 + }, + { + "name": "minecraft:spore_blossom", + "id": -321 + }, + { + "name": "minecraft:spruce_boat", + "id": 380 + }, + { + "name": "minecraft:spruce_button", + "id": -144 + }, + { + "name": "minecraft:spruce_chest_boat", + "id": 648 + }, + { + "name": "minecraft:spruce_door", + "id": 560 + }, + { + "name": "minecraft:spruce_fence", + "id": -579 + }, + { + "name": "minecraft:spruce_fence_gate", + "id": 183 + }, + { + "name": "minecraft:spruce_hanging_sign", + "id": -501 + }, + { + "name": "minecraft:spruce_log", + "id": -569 + }, + { + "name": "minecraft:spruce_pressure_plate", + "id": -154 + }, + { + "name": "minecraft:spruce_sign", + "id": 583 + }, + { + "name": "minecraft:spruce_stairs", + "id": 134 + }, + { + "name": "minecraft:spruce_standing_sign", + "id": -181 + }, + { + "name": "minecraft:spruce_trapdoor", + "id": -149 + }, + { + "name": "minecraft:spruce_wall_sign", + "id": -182 + }, + { + "name": "minecraft:spyglass", + "id": 632 + }, + { + "name": "minecraft:squid_spawn_egg", + "id": 452 + }, + { + "name": "minecraft:stained_glass", + "id": 711 + }, + { + "name": "minecraft:stained_glass_pane", + "id": 712 + }, + { + "name": "minecraft:stained_hardened_clay", + "id": 702 + }, + { + "name": "minecraft:standing_banner", + "id": 176 + }, + { + "name": "minecraft:standing_sign", + "id": 63 + }, + { + "name": "minecraft:stick", + "id": 322 + }, + { + "name": "minecraft:sticky_piston", + "id": 29 + }, + { + "name": "minecraft:sticky_piston_arm_collision", + "id": -217 + }, + { + "name": "minecraft:stone", + "id": 1 + }, + { + "name": "minecraft:stone_axe", + "id": 317 + }, + { + "name": "minecraft:stone_block_slab", + "id": 44 + }, + { + "name": "minecraft:stone_block_slab2", + "id": 182 + }, + { + "name": "minecraft:stone_block_slab3", + "id": -162 + }, + { + "name": "minecraft:stone_block_slab4", + "id": -166 + }, + { + "name": "minecraft:stone_brick_stairs", + "id": 109 + }, + { + "name": "minecraft:stone_button", + "id": 77 + }, + { + "name": "minecraft:stone_hoe", + "id": 332 + }, + { + "name": "minecraft:stone_pickaxe", + "id": 316 + }, + { + "name": "minecraft:stone_pressure_plate", + "id": 70 + }, + { + "name": "minecraft:stone_shovel", + "id": 315 + }, + { + "name": "minecraft:stone_stairs", + "id": 67 + }, + { + "name": "minecraft:stone_sword", + "id": 314 + }, + { + "name": "minecraft:stonebrick", + "id": 98 + }, + { + "name": "minecraft:stonecutter", + "id": 245 + }, + { + "name": "minecraft:stonecutter_block", + "id": -197 + }, + { + "name": "minecraft:stray_spawn_egg", + "id": 464 + }, + { + "name": "minecraft:strider_spawn_egg", + "id": 497 + }, + { + "name": "minecraft:string", + "id": 328 + }, + { + "name": "minecraft:stripped_acacia_log", + "id": -8 + }, + { + "name": "minecraft:stripped_bamboo_block", + "id": -528 + }, + { + "name": "minecraft:stripped_birch_log", + "id": -6 + }, + { + "name": "minecraft:stripped_cherry_log", + "id": -535 + }, + { + "name": "minecraft:stripped_cherry_wood", + "id": -545 + }, + { + "name": "minecraft:stripped_crimson_hyphae", + "id": -300 + }, + { + "name": "minecraft:stripped_crimson_stem", + "id": -240 + }, + { + "name": "minecraft:stripped_dark_oak_log", + "id": -9 + }, + { + "name": "minecraft:stripped_jungle_log", + "id": -7 + }, + { + "name": "minecraft:stripped_mangrove_log", + "id": -485 + }, + { + "name": "minecraft:stripped_mangrove_wood", + "id": -498 + }, + { + "name": "minecraft:stripped_oak_log", + "id": -10 + }, + { + "name": "minecraft:stripped_spruce_log", + "id": -5 + }, + { + "name": "minecraft:stripped_warped_hyphae", + "id": -301 + }, + { + "name": "minecraft:stripped_warped_stem", + "id": -241 + }, + { + "name": "minecraft:structure_block", + "id": 252 + }, + { + "name": "minecraft:structure_void", + "id": 217 + }, + { + "name": "minecraft:sugar", + "id": 418 + }, + { + "name": "minecraft:sugar_cane", + "id": 387 + }, + { + "name": "minecraft:suspicious_gravel", + "id": -573 + }, + { + "name": "minecraft:suspicious_sand", + "id": -529 + }, + { + "name": "minecraft:suspicious_stew", + "id": 597 + }, + { + "name": "minecraft:sweet_berries", + "id": 287 + }, + { + "name": "minecraft:sweet_berry_bush", + "id": -207 + }, + { + "name": "minecraft:tadpole_bucket", + "id": 637 + }, + { + "name": "minecraft:tadpole_spawn_egg", + "id": 636 + }, + { + "name": "minecraft:tallgrass", + "id": 31 + }, + { + "name": "minecraft:target", + "id": -239 + }, + { + "name": "minecraft:tide_armor_trim_smithing_template", + "id": 692 + }, + { + "name": "minecraft:tinted_glass", + "id": -334 + }, + { + "name": "minecraft:tnt", + "id": 46 + }, + { + "name": "minecraft:tnt_minecart", + "id": 532 + }, + { + "name": "minecraft:torch", + "id": 50 + }, + { + "name": "minecraft:torchflower", + "id": -568 + }, + { + "name": "minecraft:torchflower_crop", + "id": -567 + }, + { + "name": "minecraft:torchflower_seeds", + "id": 296 + }, + { + "name": "minecraft:totem_of_undying", + "id": 575 + }, + { + "name": "minecraft:trader_llama_spawn_egg", + "id": 655 + }, + { + "name": "minecraft:trapdoor", + "id": 96 + }, + { + "name": "minecraft:trapped_chest", + "id": 146 + }, + { + "name": "minecraft:trident", + "id": 553 + }, + { + "name": "minecraft:trip_wire", + "id": 132 + }, + { + "name": "minecraft:tripwire_hook", + "id": 131 + }, + { + "name": "minecraft:tropical_fish", + "id": 266 + }, + { + "name": "minecraft:tropical_fish_bucket", + "id": 368 + }, + { + "name": "minecraft:tropical_fish_spawn_egg", + "id": 481 + }, + { + "name": "minecraft:tube_coral", + "id": -131 + }, + { + "name": "minecraft:tuff", + "id": -333 + }, + { + "name": "minecraft:turtle_egg", + "id": -159 + }, + { + "name": "minecraft:turtle_helmet", + "id": 580 + }, + { + "name": "minecraft:turtle_spawn_egg", + "id": 487 + }, + { + "name": "minecraft:twisting_vines", + "id": -287 + }, + { + "name": "minecraft:underwater_torch", + "id": 239 + }, + { + "name": "minecraft:undyed_shulker_box", + "id": 205 + }, + { + "name": "minecraft:unknown", + "id": -305 + }, + { + "name": "minecraft:unlit_redstone_torch", + "id": 75 + }, + { + "name": "minecraft:unpowered_comparator", + "id": 149 + }, + { + "name": "minecraft:unpowered_repeater", + "id": 93 + }, + { + "name": "minecraft:verdant_froglight", + "id": -470 + }, + { + "name": "minecraft:vex_armor_trim_smithing_template", + "id": 691 + }, + { + "name": "minecraft:vex_spawn_egg", + "id": 478 + }, + { + "name": "minecraft:villager_spawn_egg", + "id": 451 + }, + { + "name": "minecraft:vindicator_spawn_egg", + "id": 476 + }, + { + "name": "minecraft:vine", + "id": 106 + }, + { + "name": "minecraft:wall_banner", + "id": 177 + }, + { + "name": "minecraft:wall_sign", + "id": 68 + }, + { + "name": "minecraft:wandering_trader_spawn_egg", + "id": 494 + }, + { + "name": "minecraft:ward_armor_trim_smithing_template", + "id": 689 + }, + { + "name": "minecraft:warden_spawn_egg", + "id": 639 + }, + { + "name": "minecraft:warped_button", + "id": -261 + }, + { + "name": "minecraft:warped_door", + "id": 624 + }, + { + "name": "minecraft:warped_double_slab", + "id": -267 + }, + { + "name": "minecraft:warped_fence", + "id": -257 + }, + { + "name": "minecraft:warped_fence_gate", + "id": -259 + }, + { + "name": "minecraft:warped_fungus", + "id": -229 + }, + { + "name": "minecraft:warped_fungus_on_a_stick", + "id": 625 + }, + { + "name": "minecraft:warped_hanging_sign", + "id": -507 + }, + { + "name": "minecraft:warped_hyphae", + "id": -298 + }, + { + "name": "minecraft:warped_nylium", + "id": -233 + }, + { + "name": "minecraft:warped_planks", + "id": -243 + }, + { + "name": "minecraft:warped_pressure_plate", + "id": -263 + }, + { + "name": "minecraft:warped_roots", + "id": -224 + }, + { + "name": "minecraft:warped_sign", + "id": 622 + }, + { + "name": "minecraft:warped_slab", + "id": -265 + }, + { + "name": "minecraft:warped_stairs", + "id": -255 + }, + { + "name": "minecraft:warped_standing_sign", + "id": -251 + }, + { + "name": "minecraft:warped_stem", + "id": -226 + }, + { + "name": "minecraft:warped_trapdoor", + "id": -247 + }, + { + "name": "minecraft:warped_wall_sign", + "id": -253 + }, + { + "name": "minecraft:warped_wart_block", + "id": -227 + }, + { + "name": "minecraft:water", + "id": 9 + }, + { + "name": "minecraft:water_bucket", + "id": 364 + }, + { + "name": "minecraft:waterlily", + "id": 111 + }, + { + "name": "minecraft:waxed_copper", + "id": -344 + }, + { + "name": "minecraft:waxed_cut_copper", + "id": -351 + }, + { + "name": "minecraft:waxed_cut_copper_slab", + "id": -365 + }, + { + "name": "minecraft:waxed_cut_copper_stairs", + "id": -358 + }, + { + "name": "minecraft:waxed_double_cut_copper_slab", + "id": -372 + }, + { + "name": "minecraft:waxed_exposed_copper", + "id": -345 + }, + { + "name": "minecraft:waxed_exposed_cut_copper", + "id": -352 + }, + { + "name": "minecraft:waxed_exposed_cut_copper_slab", + "id": -366 + }, + { + "name": "minecraft:waxed_exposed_cut_copper_stairs", + "id": -359 + }, + { + "name": "minecraft:waxed_exposed_double_cut_copper_slab", + "id": -373 + }, + { + "name": "minecraft:waxed_oxidized_copper", + "id": -446 + }, + { + "name": "minecraft:waxed_oxidized_cut_copper", + "id": -447 + }, + { + "name": "minecraft:waxed_oxidized_cut_copper_slab", + "id": -449 + }, + { + "name": "minecraft:waxed_oxidized_cut_copper_stairs", + "id": -448 + }, + { + "name": "minecraft:waxed_oxidized_double_cut_copper_slab", + "id": -450 + }, + { + "name": "minecraft:waxed_weathered_copper", + "id": -346 + }, + { + "name": "minecraft:waxed_weathered_cut_copper", + "id": -353 + }, + { + "name": "minecraft:waxed_weathered_cut_copper_slab", + "id": -367 + }, + { + "name": "minecraft:waxed_weathered_cut_copper_stairs", + "id": -360 + }, + { + "name": "minecraft:waxed_weathered_double_cut_copper_slab", + "id": -374 + }, + { + "name": "minecraft:wayfinder_armor_trim_smithing_template", + "id": 697 + }, + { + "name": "minecraft:weathered_copper", + "id": -342 + }, + { + "name": "minecraft:weathered_cut_copper", + "id": -349 + }, + { + "name": "minecraft:weathered_cut_copper_slab", + "id": -363 + }, + { + "name": "minecraft:weathered_cut_copper_stairs", + "id": -356 + }, + { + "name": "minecraft:weathered_double_cut_copper_slab", + "id": -370 + }, + { + "name": "minecraft:web", + "id": 30 + }, + { + "name": "minecraft:weeping_vines", + "id": -231 + }, + { + "name": "minecraft:wheat", + "id": 336 + }, + { + "name": "minecraft:wheat_seeds", + "id": 291 + }, + { + "name": "minecraft:white_candle", + "id": -413 + }, + { + "name": "minecraft:white_candle_cake", + "id": -430 + }, + { + "name": "minecraft:white_carpet", + "id": 171 + }, + { + "name": "minecraft:white_concrete", + "id": 236 + }, + { + "name": "minecraft:white_concrete_powder", + "id": 237 + }, + { + "name": "minecraft:white_dye", + "id": 412 + }, + { + "name": "minecraft:white_glazed_terracotta", + "id": 220 + }, + { + "name": "minecraft:white_shulker_box", + "id": 218 + }, + { + "name": "minecraft:white_stained_glass", + "id": 241 + }, + { + "name": "minecraft:white_stained_glass_pane", + "id": 160 + }, + { + "name": "minecraft:white_terracotta", + "id": 159 + }, + { + "name": "minecraft:white_wool", + "id": 35 + }, + { + "name": "minecraft:wild_armor_trim_smithing_template", + "id": 688 + }, + { + "name": "minecraft:witch_spawn_egg", + "id": 454 + }, + { + "name": "minecraft:wither_rose", + "id": -216 + }, + { + "name": "minecraft:wither_skeleton_spawn_egg", + "id": 466 + }, + { + "name": "minecraft:wither_spawn_egg", + "id": 509 + }, + { + "name": "minecraft:wolf_spawn_egg", + "id": 441 + }, + { + "name": "minecraft:wood", + "id": -212 + }, + { + "name": "minecraft:wooden_axe", + "id": 313 + }, + { + "name": "minecraft:wooden_button", + "id": 143 + }, + { + "name": "minecraft:wooden_door", + "id": 361 + }, + { + "name": "minecraft:wooden_hoe", + "id": 331 + }, + { + "name": "minecraft:wooden_pickaxe", + "id": 312 + }, + { + "name": "minecraft:wooden_pressure_plate", + "id": 72 + }, + { + "name": "minecraft:wooden_shovel", + "id": 311 + }, + { + "name": "minecraft:wooden_slab", + "id": 158 + }, + { + "name": "minecraft:wooden_sword", + "id": 310 + }, + { + "name": "minecraft:wool", + "id": 703 + }, + { + "name": "minecraft:writable_book", + "id": 517 + }, + { + "name": "minecraft:written_book", + "id": 518 + }, + { + "name": "minecraft:yellow_candle", + "id": -417 + }, + { + "name": "minecraft:yellow_candle_cake", + "id": -434 + }, + { + "name": "minecraft:yellow_carpet", + "id": -600 + }, + { + "name": "minecraft:yellow_concrete", + "id": -631 + }, + { + "name": "minecraft:yellow_concrete_powder", + "id": -712 + }, + { + "name": "minecraft:yellow_dye", + "id": 408 + }, + { + "name": "minecraft:yellow_flower", + "id": 37 + }, + { + "name": "minecraft:yellow_glazed_terracotta", + "id": 224 + }, + { + "name": "minecraft:yellow_shulker_box", + "id": -616 + }, + { + "name": "minecraft:yellow_stained_glass", + "id": -676 + }, + { + "name": "minecraft:yellow_stained_glass_pane", + "id": -646 + }, + { + "name": "minecraft:yellow_terracotta", + "id": -727 + }, + { + "name": "minecraft:yellow_wool", + "id": -558 + }, + { + "name": "minecraft:zoglin_spawn_egg", + "id": 500 + }, + { + "name": "minecraft:zombie_horse_spawn_egg", + "id": 470 + }, + { + "name": "minecraft:zombie_pigman_spawn_egg", + "id": 450 + }, + { + "name": "minecraft:zombie_spawn_egg", + "id": 449 + }, + { + "name": "minecraft:zombie_villager_spawn_egg", + "id": 479 + } +] \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 579f9de31..9488ae3b6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,10 +9,10 @@ netty = "4.1.80.Final" guava = "29.0-jre" gson = "2.3.1" # Provided by Spigot 1.8.8 websocket = "1.5.1" -protocol = "3.0.0.Beta1-20230908.171156-106" -protocol-connection = "3.0.0.Beta1-20230908.171156-105" +protocol = "3.0.0.Beta1-20231016.115644-107" +protocol-connection = "3.0.0.Beta1-20231016.115644-106" raknet = "1.0.0.CR1-20230703.195238-9" -blockstateupdater="1.20.30-20230918.203831-4" +blockstateupdater="1.20.40-20231016.111746-1" mcauthlib = "d9d773e" mcprotocollib = "1.20.2-1-20231003.141424-6" adventure = "4.14.0" From 53960c9d46641644868ec3c1be5ae63a6aa0a97d Mon Sep 17 00:00:00 2001 From: Hasan <52300558+hasankayra04@users.noreply.github.com> Date: Fri, 20 Oct 2023 08:02:10 +0300 Subject: [PATCH 104/344] update readme version for 1.20.40 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8a1f456c7..07fb34209 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,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.20.0 - 1.20.32 and Minecraft Java 1.20.2 +### Currently supporting Minecraft Bedrock 1.20.0 - 1.20.40 and Minecraft Java 1.20.2 ## Setting Up Take a look [here](https://wiki.geysermc.org/geyser/setup/) for how to set up Geyser. From 450e3b61fe4591359003f037d7207d7e69ba3b8d Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 20 Oct 2023 20:14:16 +0200 Subject: [PATCH 105/344] Bring back accidentally removed MTU option (#4229) --- .../java/org/geysermc/geyser/network/netty/GeyserServer.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java b/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java index 6fbb29157..c89da0bdd 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java @@ -171,10 +171,12 @@ public final class GeyserServer { GeyserServerInitializer serverInitializer = new GeyserServerInitializer(this.geyser); playerGroup = serverInitializer.getEventLoopGroup(); + this.geyser.getLogger().debug("Setting MTU to " + this.geyser.getConfig().getMtu()); return new ServerBootstrap() .channelFactory(RakChannelFactory.server(TRANSPORT.datagramChannel())) .group(group) .option(RakChannelOption.RAK_HANDLE_PING, true) + .option(RakChannelOption.RAK_MAX_MTU, this.geyser.getConfig().getMtu()) .childHandler(serverInitializer); } From 51236f7a5997f6405427838932c072c73e49c0b5 Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 20 Oct 2023 22:17:43 +0200 Subject: [PATCH 106/344] Let the fabric module really use Java 17 (#4231) * Let the fabric module really use java 17 * Remove unnecessary target/source compat; handled by indra instead --- bootstrap/fabric/build.gradle.kts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/bootstrap/fabric/build.gradle.kts b/bootstrap/fabric/build.gradle.kts index e392a4ef9..07de70f60 100644 --- a/bootstrap/fabric/build.gradle.kts +++ b/bootstrap/fabric/build.gradle.kts @@ -5,9 +5,10 @@ plugins { id("com.modrinth.minotaur") version "2.+" } -java { - targetCompatibility = JavaVersion.VERSION_17 - sourceCompatibility = JavaVersion.VERSION_17 +indra { + javaVersions { + target(17) + } } dependencies { From b4290d5be462b8352fd0a2dd8b30ac61c98b8041 Mon Sep 17 00:00:00 2001 From: chris Date: Tue, 24 Oct 2023 01:41:02 +0200 Subject: [PATCH 107/344] Versioned potion mappings (#4239) --- .../geyser/registry/loader/PotionMixRegistryLoader.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/PotionMixRegistryLoader.java b/core/src/main/java/org/geysermc/geyser/registry/loader/PotionMixRegistryLoader.java index 88d2ef29d..7d5061382 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/loader/PotionMixRegistryLoader.java +++ b/core/src/main/java/org/geysermc/geyser/registry/loader/PotionMixRegistryLoader.java @@ -31,7 +31,6 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.PotionMixData; import org.geysermc.geyser.inventory.item.Potion; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.Item; -import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; @@ -115,7 +114,7 @@ public class PotionMixRegistryLoader implements RegistryLoader Date: Thu, 26 Oct 2023 08:16:24 -0700 Subject: [PATCH 108/344] Reduce Frequency of Crashes Due to Dispensers, Droppers, and Chiseled Bookshelves (#4248) * Revert to subchunk v8; reduces freq of #4240 * Full resolution --- .../geyser/level/chunk/GeyserChunkSection.java | 18 ++++++++---------- .../JavaLevelChunkWithLightTranslator.java | 12 ++++++------ .../org/geysermc/geyser/util/ChunkUtils.java | 2 +- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/level/chunk/GeyserChunkSection.java b/core/src/main/java/org/geysermc/geyser/level/chunk/GeyserChunkSection.java index 58f61fb4a..f3e6b8399 100644 --- a/core/src/main/java/org/geysermc/geyser/level/chunk/GeyserChunkSection.java +++ b/core/src/main/java/org/geysermc/geyser/level/chunk/GeyserChunkSection.java @@ -30,19 +30,18 @@ import org.cloudburstmc.protocol.common.util.Preconditions; public class GeyserChunkSection { - // As of at least 1.19.80 - private static final int CHUNK_SECTION_VERSION = 9; + // Temporary reversion to v8 as it reduces the frequnecy of https://github.com/GeyserMC/Geyser/issues/4240 + // This does not fully resolve the issue so a better solution is still needed + private static final int CHUNK_SECTION_VERSION = 8; private final BlockStorage[] storage; - private final int sectionY; - public GeyserChunkSection(int airBlockId, int sectionY) { - this(new BlockStorage[]{new BlockStorage(airBlockId), new BlockStorage(airBlockId)}, sectionY); + public GeyserChunkSection(int airBlockId) { + this(new BlockStorage[]{new BlockStorage(airBlockId), new BlockStorage(airBlockId)}); } - public GeyserChunkSection(BlockStorage[] storage, int sectionY) { + public GeyserChunkSection(BlockStorage[] storage) { this.storage = storage; - this.sectionY = sectionY; } public int getFullBlock(int x, int y, int z, int layer) { @@ -61,7 +60,6 @@ public class GeyserChunkSection { buffer.writeByte(CHUNK_SECTION_VERSION); buffer.writeByte(this.storage.length); // Required for chunk version 9+ - buffer.writeByte(this.sectionY); for (BlockStorage blockStorage : this.storage) { blockStorage.writeToNetwork(buffer); } @@ -88,12 +86,12 @@ public class GeyserChunkSection { return true; } - public GeyserChunkSection copy(int sectionY) { + public GeyserChunkSection copy() { BlockStorage[] storage = new BlockStorage[this.storage.length]; for (int i = 0; i < storage.length; i++) { storage[i] = this.storage[i].copy(); } - return new GeyserChunkSection(storage, sectionY); + return new GeyserChunkSection(storage); } public static int blockPosition(int x, int y, int z) { 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 080d5df8e..85eec40e0 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 @@ -154,7 +154,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator Date: Fri, 3 Nov 2023 16:58:02 +0100 Subject: [PATCH 109/344] Fix text displays on 1.20.2 It seems like 1.20.2 added one more field to base displays (https://wiki.vg/Entity_metadata#Display), and a few more to text displays: https://wiki.vg/Entity_metadata#Text_Display (#4268) --- .../org/geysermc/geyser/entity/EntityDefinitions.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java index a88eff111..e9d49fbd8 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java +++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java @@ -299,8 +299,9 @@ public final class EntityDefinitions { .build(); EntityDefinition displayBase = EntityDefinition.inherited(entityBase.factory(), entityBase) - .addTranslator(null) // Interpolation start ticks - .addTranslator(null) // Interpolation duration ID + .addTranslator(null) // Interpolation delay + .addTranslator(null) // Transformation interpolation duration + .addTranslator(null) // Position/Rotation interpolation duration .addTranslator(null) // Translation .addTranslator(null) // Scale .addTranslator(null) // Left rotation @@ -318,6 +319,10 @@ public final class EntityDefinitions { .type(EntityType.TEXT_DISPLAY) .identifier("minecraft:armor_stand") .addTranslator(MetadataType.CHAT, TextDisplayEntity::setText) + .addTranslator(null) // Line width + .addTranslator(null) // Background color + .addTranslator(null) // Text opacity + .addTranslator(null) // Bit mask .build(); INTERACTION = EntityDefinition.inherited(InteractionEntity::new, entityBase) From 4ff8b7bff44436f55248465eeb51c2f12c46814e Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 3 Nov 2023 17:09:34 +0100 Subject: [PATCH 110/344] Bump mcpl to fix issues with the ClientboundLoginDisconnectPacket (#4264) --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9488ae3b6..a5b1a79c3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,7 +14,7 @@ protocol-connection = "3.0.0.Beta1-20231016.115644-106" raknet = "1.0.0.CR1-20230703.195238-9" blockstateupdater="1.20.40-20231016.111746-1" mcauthlib = "d9d773e" -mcprotocollib = "1.20.2-1-20231003.141424-6" +mcprotocollib = "1.20.2-1-20231101.141901-7" adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" From 644082ae84111e07923ab86d73fd0445cd9b3594 Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 3 Nov 2023 17:16:09 +0100 Subject: [PATCH 111/344] Fix `/geyser reload` on Velocity (#4258) * Fix /geyser reload on Velocity * No need to create/init a new injector on Velocity * No need to warn about "abnormally long startup" on Bungee when we're reloading. And, as on velocity, no need to re-inject --- .../bungeecord/GeyserBungeePlugin.java | 17 ++++++++++++++--- .../velocity/GeyserVelocityPlugin.java | 18 ++++++++++++++++-- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java index 86f283329..e58abc3b4 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java @@ -70,6 +70,8 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { private GeyserImpl geyser; + private static boolean INITIALIZED = false; + @Override public void onLoad() { GeyserLocale.init(this); @@ -133,7 +135,12 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { // Big hack - Bungee does not provide us an event to listen to, so schedule a repeating // task that waits for a field to be filled which is set after the plugin enable // process is complete - this.awaitStartupCompletion(0); + if (!INITIALIZED) { + this.awaitStartupCompletion(0); + } else { + // No need to "wait" for startup completion, just start Geyser - we're reloading. + this.postStartup(); + } } @SuppressWarnings("unchecked") @@ -166,8 +173,10 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { private void postStartup() { GeyserImpl.start(); - this.geyserInjector = new GeyserBungeeInjector(this); - this.geyserInjector.initializeLocalChannel(this); + if (!INITIALIZED) { + this.geyserInjector = new GeyserBungeeInjector(this); + this.geyserInjector.initializeLocalChannel(this); + } this.geyserCommandManager = new GeyserCommandManager(geyser); this.geyserCommandManager.init(); @@ -187,6 +196,8 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { } else { this.geyserBungeePingPassthrough = new GeyserBungeePingPassthrough(getProxy()); } + + INITIALIZED = true; } @Override diff --git a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java index dbbd30c41..93b57d712 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java @@ -64,6 +64,11 @@ import java.util.UUID; @Plugin(id = "geyser", name = GeyserImpl.NAME + "-Velocity", version = GeyserImpl.VERSION, url = "https://geysermc.org", authors = "GeyserMC") public class GeyserVelocityPlugin implements GeyserBootstrap { + /** + * Determines if the plugin has been ran once before, including before /geyser reload. + */ + private static boolean INITIALIZED = false; + @Inject private Logger logger; @@ -114,13 +119,20 @@ public class GeyserVelocityPlugin implements GeyserBootstrap { GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); this.geyser = GeyserImpl.load(PlatformType.VELOCITY, this); + + // Hack: Normally triggered by ListenerBoundEvent, but that doesn't fire on /geyser reload + if (INITIALIZED) { + this.postStartup(); + } } private void postStartup() { GeyserImpl.start(); - this.geyserInjector = new GeyserVelocityInjector(proxyServer); - // Will be initialized after the proxy has been bound + if (!INITIALIZED) { + this.geyserInjector = new GeyserVelocityInjector(proxyServer); + // Will be initialized after the proxy has been bound + } this.geyserCommandManager = new GeyserCommandManager(geyser); this.geyserCommandManager.init(); @@ -195,6 +207,8 @@ public class GeyserVelocityPlugin implements GeyserBootstrap { geyserInjector.initializeLocalChannel(this); } } + + INITIALIZED = true; } @Override From ec526a798d3a4325a77f07373a55323e8118b43e Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 3 Nov 2023 17:22:55 +0100 Subject: [PATCH 112/344] Send cooldown when punching air (#4257) --- .../bedrock/entity/player/BedrockActionTranslator.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java index bff097248..611ca5824 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java @@ -55,6 +55,7 @@ import org.geysermc.geyser.translator.inventory.item.CustomItemTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.util.BlockUtils; +import org.geysermc.geyser.util.CooldownUtils; @Translator(packet = PlayerActionPacket.class) public class BedrockActionTranslator extends PacketTranslator { @@ -281,6 +282,10 @@ public class BedrockActionTranslator extends PacketTranslator Date: Sat, 4 Nov 2023 16:06:23 +0100 Subject: [PATCH 113/344] Move "unknown entity definition" spam to debug level (#4270) --- .../protocol/java/entity/spawn/JavaAddEntityTranslator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/spawn/JavaAddEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/spawn/JavaAddEntityTranslator.java index c17c9955d..ab7163650 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/spawn/JavaAddEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/spawn/JavaAddEntityTranslator.java @@ -49,7 +49,7 @@ public class JavaAddEntityTranslator extends PacketTranslator definition = Registries.ENTITY_DEFINITIONS.get(packet.getType()); if (definition == null) { - session.getGeyser().getLogger().warning("Could not find an entity definition with type " + packet.getType()); + session.getGeyser().getLogger().debug("Could not find an entity definition with type " + packet.getType()); return; } From 574dad015d11c072d9fc7c5989d94f9689078b77 Mon Sep 17 00:00:00 2001 From: chris Date: Sat, 4 Nov 2023 18:59:02 +0100 Subject: [PATCH 114/344] Fix: Display entities only being visible when directly looked at (#4271) --- .../org/geysermc/geyser/entity/type/TextDisplayEntity.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/TextDisplayEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/TextDisplayEntity.java index f2671f7a9..703d5210b 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/TextDisplayEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/TextDisplayEntity.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.entity.type; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import net.kyori.adventure.text.Component; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; @@ -49,6 +50,12 @@ public class TextDisplayEntity extends Entity { this.dirtyMetadata.put(EntityDataTypes.NAMETAG_ALWAYS_SHOW, (byte) 1); } + @Override + public void setDisplayNameVisible(BooleanEntityMetadata entityMetadata) { + // Don't allow the display name to be hidden - messes with our armor stand. + // On JE: Hiding the display name still shows the display entity text. + } + public void setText(EntityMetadata entityMetadata) { this.dirtyMetadata.put(EntityDataTypes.NAME, MessageTranslator.convertMessage(entityMetadata.getValue())); } From 06663bcafd8ac19f4072b813fe091e5dbbf4d3de Mon Sep 17 00:00:00 2001 From: chris Date: Mon, 6 Nov 2023 16:17:41 +0100 Subject: [PATCH 115/344] Fix: Don't mistakingly assume that Geyser-Velocity initialized (#4276) * Fix: ListenerBoundEvent could set `INITIALIZED` to true, even if we did not initialize yet - move that to postStartup() instead. * only assign INITIALIZED once, and only after the correct listenertype bound. --- .../geyser/platform/velocity/GeyserVelocityPlugin.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java index 93b57d712..d7c6c588e 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java @@ -206,9 +206,9 @@ public class GeyserVelocityPlugin implements GeyserBootstrap { // After this bound, we know that the channel initializer cannot change without it being ineffective for Velocity, too geyserInjector.initializeLocalChannel(this); } - } - INITIALIZED = true; + INITIALIZED = true; + } } @Override From aa899af90812af4f726dc971ef30a81bd10786d4 Mon Sep 17 00:00:00 2001 From: chris Date: Wed, 8 Nov 2023 00:23:56 +0100 Subject: [PATCH 116/344] Clear bossbars & entity attributes on server switching (#4278) * This ensures bossbars are cleared on server switch. Additionally, this clears the EntityCache - which should resolve issues around air supply/hearts persisting visually. * - Also reset attributes on server switch, aswell as air --- .../entity/type/player/SessionPlayerEntity.java | 13 +++++++++++++ .../geysermc/geyser/session/cache/EntityCache.java | 5 +++++ .../protocol/java/JavaLoginTranslator.java | 13 ++++++++----- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java index bcd32253f..58b7ffddb 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java @@ -254,4 +254,17 @@ public class SessionPlayerEntity extends PlayerEntity { public UUID getTabListUuid() { return session.getAuthData().uuid(); } + + public void resetMetadata() { + // Reset all metadata to their default values + // This is used when a player respawns + this.initializeMetadata(); + + // Reset air + this.resetAir(); + } + + public void resetAir() { + this.setAirSupply(getMaxAir()); + } } diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/EntityCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/EntityCache.java index 9dc89215a..8a4b9cb6c 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/EntityCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/EntityCache.java @@ -162,4 +162,9 @@ public class EntityCache { public List getTickableEntities() { return tickableEntities; } + + public void removeAllBossBars() { + bossBars.values().forEach(BossBar::removeBossBar); + bossBars.clear(); + } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java index 3b9f29b89..e7539bd0f 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java @@ -64,12 +64,17 @@ public class JavaLoginTranslator extends PacketTranslator Date: Thu, 9 Nov 2023 08:44:13 +0100 Subject: [PATCH 117/344] Add ability to set molang tags for custom items (#4041) * Start on custom molang tags with custom items * geyser_custom instead of geyser item tag * Address reviews, add custom namespace ("geyser_custom") to tags * use isBlank() instead of isEmpty() * More efficient item tag setting Co-authored-by: Konicai <71294714+konicai@users.noreply.github.com> * tags instead of temp * Merge in master, adapt to changes in the MappingsReader, delete unused ToolBreakSpeedsUtils class * oops * clean diff * Change namespace from `geyser_custom` to just `geyser` * Don't force a namespace at all; just like blocks don't * Tags for items are now, as blocks, NonNull. Additionally, calling the .tags() builder multiple times will not add both sets of tags, but replace the existing tag set * Remove @NotNull usage in favor of @NonNull * Allow setting null for tags, but ensure that .tags() is always non-null * Fix nullable annotation on tags method in the builder interface --- .../component/CustomBlockComponents.java | 2 +- .../api/item/custom/CustomItemData.java | 12 ++ .../item/custom/NonVanillaCustomItemData.java | 3 + .../geyser/item/GeyserCustomItemData.java | 31 +++- .../item/GeyserNonVanillaCustomItemData.java | 7 +- .../item/components/ToolBreakSpeedsUtils.java | 174 ------------------ .../block/GeyserCustomBlockComponents.java | 13 +- .../mappings/versions/MappingsReader_v1.java | 6 + .../CustomItemRegistryPopulator.java | 28 ++- 9 files changed, 85 insertions(+), 191 deletions(-) delete mode 100644 core/src/main/java/org/geysermc/geyser/item/components/ToolBreakSpeedsUtils.java diff --git a/api/src/main/java/org/geysermc/geyser/api/block/custom/component/CustomBlockComponents.java b/api/src/main/java/org/geysermc/geyser/api/block/custom/component/CustomBlockComponents.java index 036723092..63788df8e 100644 --- a/api/src/main/java/org/geysermc/geyser/api/block/custom/component/CustomBlockComponents.java +++ b/api/src/main/java/org/geysermc/geyser/api/block/custom/component/CustomBlockComponents.java @@ -185,7 +185,7 @@ public interface CustomBlockComponents { Builder placeAir(boolean placeAir); - Builder tags(Set tags); + Builder tags(@Nullable Set tags); CustomBlockComponents build(); } diff --git a/api/src/main/java/org/geysermc/geyser/api/item/custom/CustomItemData.java b/api/src/main/java/org/geysermc/geyser/api/item/custom/CustomItemData.java index d256b9ac0..404679e60 100644 --- a/api/src/main/java/org/geysermc/geyser/api/item/custom/CustomItemData.java +++ b/api/src/main/java/org/geysermc/geyser/api/item/custom/CustomItemData.java @@ -29,6 +29,8 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.api.GeyserApi; +import java.util.Set; + /** * This is used to store data for a custom item. */ @@ -89,6 +91,14 @@ public interface CustomItemData { */ @Nullable CustomRenderOffsets renderOffsets(); + /** + * Gets the item's set of tags that can be used in Molang. + * Equivalent to "tag:some_tag" + * + * @return the item's tags, if they exist + */ + @NonNull Set tags(); + static CustomItemData.Builder builder() { return GeyserApi.api().provider(CustomItemData.Builder.class); } @@ -113,6 +123,8 @@ public interface CustomItemData { Builder renderOffsets(@Nullable CustomRenderOffsets renderOffsets); + Builder tags(@Nullable Set tags); + CustomItemData build(); } } diff --git a/api/src/main/java/org/geysermc/geyser/api/item/custom/NonVanillaCustomItemData.java b/api/src/main/java/org/geysermc/geyser/api/item/custom/NonVanillaCustomItemData.java index 0a09f6958..616a5bba6 100644 --- a/api/src/main/java/org/geysermc/geyser/api/item/custom/NonVanillaCustomItemData.java +++ b/api/src/main/java/org/geysermc/geyser/api/item/custom/NonVanillaCustomItemData.java @@ -239,6 +239,9 @@ public interface NonVanillaCustomItemData extends CustomItemData { @Override Builder renderOffsets(@Nullable CustomRenderOffsets renderOffsets); + @Override + Builder tags(@Nullable Set tags); + NonVanillaCustomItemData build(); } } diff --git a/core/src/main/java/org/geysermc/geyser/item/GeyserCustomItemData.java b/core/src/main/java/org/geysermc/geyser/item/GeyserCustomItemData.java index 3535eaf4d..c86c370bb 100644 --- a/core/src/main/java/org/geysermc/geyser/item/GeyserCustomItemData.java +++ b/core/src/main/java/org/geysermc/geyser/item/GeyserCustomItemData.java @@ -28,10 +28,14 @@ package org.geysermc.geyser.item; import lombok.EqualsAndHashCode; import lombok.ToString; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.api.item.custom.CustomItemData; import org.geysermc.geyser.api.item.custom.CustomItemOptions; import org.geysermc.geyser.api.item.custom.CustomRenderOffsets; -import org.jetbrains.annotations.NotNull; + +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; @EqualsAndHashCode @ToString @@ -44,6 +48,7 @@ public class GeyserCustomItemData implements CustomItemData { private final boolean displayHandheld; private final int textureSize; private final CustomRenderOffsets renderOffsets; + private final Set tags; public GeyserCustomItemData(String name, CustomItemOptions customItemOptions, @@ -52,7 +57,8 @@ public class GeyserCustomItemData implements CustomItemData { boolean allowOffhand, boolean displayHandheld, int textureSize, - CustomRenderOffsets renderOffsets) { + CustomRenderOffsets renderOffsets, + Set tags) { this.name = name; this.customItemOptions = customItemOptions; this.displayName = displayName; @@ -61,10 +67,11 @@ public class GeyserCustomItemData implements CustomItemData { this.displayHandheld = displayHandheld; this.textureSize = textureSize; this.renderOffsets = renderOffsets; + this.tags = tags; } @Override - public @NotNull String name() { + public @NonNull String name() { return name; } @@ -74,12 +81,12 @@ public class GeyserCustomItemData implements CustomItemData { } @Override - public @NotNull String displayName() { + public @NonNull String displayName() { return displayName; } @Override - public @NotNull String icon() { + public @NonNull String icon() { return icon; } @@ -103,6 +110,11 @@ public class GeyserCustomItemData implements CustomItemData { return renderOffsets; } + @Override + public @NonNull Set tags() { + return tags; + } + public static class CustomItemDataBuilder implements Builder { protected String name = null; protected CustomItemOptions customItemOptions = null; @@ -113,6 +125,7 @@ public class GeyserCustomItemData implements CustomItemData { protected boolean displayHandheld = false; protected int textureSize = 16; protected CustomRenderOffsets renderOffsets = null; + protected Set tags = new HashSet<>(); @Override public Builder name(@NonNull String name) { @@ -162,6 +175,12 @@ public class GeyserCustomItemData implements CustomItemData { return this; } + @Override + public Builder tags(@Nullable Set tags) { + this.tags = Objects.requireNonNullElseGet(tags, Set::of); + return this; + } + @Override public CustomItemData build() { if (this.name == null || this.customItemOptions == null) { @@ -174,7 +193,7 @@ public class GeyserCustomItemData implements CustomItemData { if (this.icon == null) { this.icon = this.name; } - return new GeyserCustomItemData(this.name, this.customItemOptions, this.displayName, this.icon, this.allowOffhand, this.displayHandheld, this.textureSize, this.renderOffsets); + return new GeyserCustomItemData(this.name, this.customItemOptions, this.displayName, this.icon, this.allowOffhand, this.displayHandheld, this.textureSize, this.renderOffsets, this.tags); } } } diff --git a/core/src/main/java/org/geysermc/geyser/item/GeyserNonVanillaCustomItemData.java b/core/src/main/java/org/geysermc/geyser/item/GeyserNonVanillaCustomItemData.java index d6731e3b8..47b5aed33 100644 --- a/core/src/main/java/org/geysermc/geyser/item/GeyserNonVanillaCustomItemData.java +++ b/core/src/main/java/org/geysermc/geyser/item/GeyserNonVanillaCustomItemData.java @@ -61,7 +61,7 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i public GeyserNonVanillaCustomItemData(NonVanillaCustomItemDataBuilder builder) { super(builder.name, builder.customItemOptions, builder.displayName, builder.icon, builder.allowOffhand, - builder.displayHandheld, builder.textureSize, builder.renderOffsets); + builder.displayHandheld, builder.textureSize, builder.renderOffsets, builder.tags); this.identifier = builder.identifier; this.javaId = builder.javaId; @@ -237,6 +237,11 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i return (NonVanillaCustomItemData.Builder) super.renderOffsets(renderOffsets); } + @Override + public NonVanillaCustomItemData.Builder tags(@Nullable Set tags) { + return (NonVanillaCustomItemData.Builder) super.tags(tags); + } + @Override public NonVanillaCustomItemData.Builder identifier(@NonNull String identifier) { this.identifier = identifier; diff --git a/core/src/main/java/org/geysermc/geyser/item/components/ToolBreakSpeedsUtils.java b/core/src/main/java/org/geysermc/geyser/item/components/ToolBreakSpeedsUtils.java deleted file mode 100644 index efefee946..000000000 --- a/core/src/main/java/org/geysermc/geyser/item/components/ToolBreakSpeedsUtils.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * 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.item.components; - -import org.cloudburstmc.nbt.NbtMap; -import org.cloudburstmc.nbt.NbtType; - -import java.util.ArrayList; -import java.util.List; - -public class ToolBreakSpeedsUtils { - public static int toolTierToSpeed(String toolTier) { - ToolTier tier = ToolTier.getByName(toolTier); - if (tier != null) { - return tier.getSpeed(); - } - - return 0; - } - - private static NbtMap createTagBreakSpeed(int speed, String... tags) { - StringBuilder builder = new StringBuilder("query.any_tag('"); - builder.append(tags[0]); - for (int i = 1; i < tags.length; i++) { - builder.append("', '").append(tags[i]); - } - builder.append("')"); - - return NbtMap.builder() - .putCompound("block", NbtMap.builder() - .putString("tags", builder.toString()) - .build()) - .putCompound("on_dig", NbtMap.builder() - .putCompound("condition", NbtMap.builder() - .putString("expression", "") - .putInt("version", -1) - .build()) - .putString("event", "tool_durability") - .putString("target", "self") - .build()) - .putInt("speed", speed) - .build(); - } - - private static NbtMap createBreakSpeed(int speed, String block) { - return NbtMap.builder() - .putCompound("block", NbtMap.builder() - .putString("name", block).build()) - .putCompound("on_dig", NbtMap.builder() - .putCompound("condition", NbtMap.builder() - .putString("expression", "") - .putInt("version", -1) - .build()) - .putString("event", "tool_durability") - .putString("target", "self") - .build()) - .putInt("speed", speed) - .build(); - } - - private static NbtMap createDigger(List speeds) { - return NbtMap.builder() - .putList("destroy_speeds", NbtType.COMPOUND, speeds) - .putCompound("on_dig", NbtMap.builder() - .putCompound("condition", NbtMap.builder() - .putString("expression", "") - .putInt("version", -1) - .build()) - .putString("event", "tool_durability") - .putString("target", "self") - .build()) - .putBoolean("use_efficiency", true) - .build(); - } - - public static NbtMap getAxeDigger(int speed) { - List speeds = new ArrayList<>(); - speeds.add(createTagBreakSpeed(speed, "wood", "pumpkin", "plant")); - - return createDigger(speeds); - } - - public static NbtMap getPickaxeDigger(int speed, String toolTier) { - List speeds = new ArrayList<>(); - if (toolTier.equals(ToolTier.DIAMOND.toString()) || toolTier.equals(ToolTier.NETHERITE.toString())) { - speeds.add(createTagBreakSpeed(speed, "iron_pick_diggable", "diamond_pick_diggable")); - } else { - speeds.add(createTagBreakSpeed(speed, "iron_pick_diggable")); - } - speeds.add(createTagBreakSpeed(speed, "stone", "metal", "rail", "mob_spawner")); - - return createDigger(speeds); - } - - public static NbtMap getShovelDigger(int speed) { - List speeds = new ArrayList<>(); - speeds.add(createTagBreakSpeed(speed, "dirt", "sand", "gravel", "grass", "snow")); - - return createDigger(speeds); - } - - public static NbtMap getSwordDigger(int speed) { - List speeds = new ArrayList<>(); - speeds.add(createBreakSpeed(speed, "minecraft:web")); - speeds.add(createBreakSpeed(speed, "minecraft:bamboo")); - - return createDigger(speeds); - } - - public static NbtMap getHoeDigger(int speed) { - List speeds = new ArrayList<>(); - speeds.add(createBreakSpeed(speed, "minecraft:leaves")); - speeds.add(createBreakSpeed(speed, "minecraft:leaves2")); - speeds.add(createBreakSpeed(speed, "minecraft:azalea_leaves")); - speeds.add(createBreakSpeed(speed, "minecraft:azalea_leaves_flowered")); - - speeds.add(createBreakSpeed(speed, "minecraft:sculk")); - speeds.add(createBreakSpeed(speed, "minecraft:sculk_catalyst")); - speeds.add(createBreakSpeed(speed, "minecraft:sculk_sensor")); - speeds.add(createBreakSpeed(speed, "minecraft:sculk_shrieker")); - speeds.add(createBreakSpeed(speed, "minecraft:sculk_vein")); - - speeds.add(createBreakSpeed(speed, "minecraft:nether_wart_block")); - speeds.add(createBreakSpeed(speed, "minecraft:warped_wart_block")); - - speeds.add(createBreakSpeed(speed, "minecraft:hay_block")); - speeds.add(createBreakSpeed(speed, "minecraft:moss_block")); - speeds.add(createBreakSpeed(speed, "minecraft:shroomlight")); - speeds.add(createBreakSpeed(speed, "minecraft:sponge")); - speeds.add(createBreakSpeed(speed, "minecraft:target")); - - return createDigger(speeds); - } - - public static NbtMap getShearsDigger(int speed) { - List speeds = new ArrayList<>(); - speeds.add(createBreakSpeed(speed, "minecraft:web")); - - speeds.add(createBreakSpeed(speed, "minecraft:leaves")); - speeds.add(createBreakSpeed(speed, "minecraft:leaves2")); - speeds.add(createBreakSpeed(speed, "minecraft:azalea_leaves")); - speeds.add(createBreakSpeed(speed, "minecraft:azalea_leaves_flowered")); - - speeds.add(createBreakSpeed(speed, "minecraft:wool")); - - speeds.add(createBreakSpeed(speed, "minecraft:glow_lichen")); - speeds.add(createBreakSpeed(speed, "minecraft:vine")); - - return createDigger(speeds); - } -} diff --git a/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockComponents.java b/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockComponents.java index e43e168ee..e401567e2 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockComponents.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockComponents.java @@ -31,18 +31,19 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectMaps; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import lombok.Value; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.api.block.custom.component.BoxComponent; import org.geysermc.geyser.api.block.custom.component.CustomBlockComponents; import org.geysermc.geyser.api.block.custom.component.GeometryComponent; import org.geysermc.geyser.api.block.custom.component.MaterialInstance; import org.geysermc.geyser.api.block.custom.component.PlacementConditions; import org.geysermc.geyser.api.block.custom.component.TransformationComponent; -import org.jetbrains.annotations.NotNull; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.Objects; @Value public class GeyserCustomBlockComponents implements CustomBlockComponents { @@ -152,7 +153,7 @@ public class GeyserCustomBlockComponents implements CustomBlockComponents { } @Override - public @NotNull Set tags() { + public @NonNull Set tags() { return tags; } @@ -170,7 +171,7 @@ public class GeyserCustomBlockComponents implements CustomBlockComponents { protected TransformationComponent transformation; protected boolean unitCube = false; protected boolean placeAir = false; - protected final Set tags = new HashSet<>(); + protected Set tags = new HashSet<>(); private void validateBox(BoxComponent box) { if (box == null) { @@ -217,7 +218,7 @@ public class GeyserCustomBlockComponents implements CustomBlockComponents { } @Override - public Builder materialInstance(@NotNull String name, @NotNull MaterialInstance materialInstance) { + public Builder materialInstance(@NonNull String name, @NonNull MaterialInstance materialInstance) { this.materialInstances.put(name, materialInstance); return this; } @@ -292,8 +293,8 @@ public class GeyserCustomBlockComponents implements CustomBlockComponents { } @Override - public Builder tags(Set tags) { - this.tags.addAll(tags); + public Builder tags(@Nullable Set tags) { + this.tags = Objects.requireNonNullElseGet(tags, Set::of); return this; } diff --git a/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java b/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java index e63bf6bf9..fb4a6acbe 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java +++ b/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java @@ -198,6 +198,12 @@ public class MappingsReader_v1 extends MappingsReader { customItemData.renderOffsets(fromJsonNode(tmpNode)); } + if (node.get("tags") instanceof ArrayNode tags) { + Set tagsSet = new ObjectOpenHashSet<>(); + tags.forEach(tag -> tagsSet.add(tag.asText())); + customItemData.tags(tagsSet); + } + return customItemData.build(); } 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 3f3f5a4ba..638e41a5e 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 @@ -270,6 +270,17 @@ public class CustomItemRegistryPopulator { .build()); componentBuilder.putCompound("minecraft:display_name", NbtMap.builder().putString("value", customItemData.displayName()).build()); + // Add a Geyser tag to the item, allowing Molang queries + addItemTag(componentBuilder, "geyser:is_custom"); + + // Add other defined tags to the item + Set tags = customItemData.tags(); + for (String tag : tags) { + if (tag != null && !tag.isBlank()) { + addItemTag(componentBuilder, tag); + } + } + itemProperties.putBoolean("allow_off_hand", customItemData.allowOffhand()); itemProperties.putBoolean("hand_equipped", displayHandheld); itemProperties.putInt("max_stack_size", stackSize); @@ -313,7 +324,7 @@ public class CustomItemRegistryPopulator { .build() )); - componentBuilder.putCompound("minecraft:digger", + componentBuilder.putCompound("minecraft:digger", NbtMap.builder() .putList("destroy_speeds", NbtType.COMPOUND, speed) .putCompound("on_dig", NbtMap.builder() @@ -506,8 +517,19 @@ public class CustomItemRegistryPopulator { return List.of(xyz.x(), xyz.y(), xyz.z()); } - private static void setItemTag(NbtMapBuilder builder, String tag) { - builder.putList("item_tags", NbtType.STRING, List.of("minecraft:is_" + tag)); + @SuppressWarnings("unchecked") + private static void addItemTag(NbtMapBuilder builder, String tag) { + List tagList = (List) builder.get("item_tags"); + if (tagList == null) { + builder.putList("item_tags", NbtType.STRING, tag); + } else { + // NbtList is immutable + if (!tagList.contains(tag)) { + tagList = new ArrayList<>(tagList); + tagList.add(tag); + builder.putList("item_tags", NbtType.STRING, tagList); + } + } } private static NbtMap xyzToScaleList(float x, float y, float z) { From 9dad1acfe5a87130b39224f1706ab78176922057 Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 10 Nov 2023 20:45:15 +0100 Subject: [PATCH 118/344] Feature: Add recipe unlocking on Bedrock edition (#4016) * Start on 1.20.10+ recipe unlocking system * Keeping track of multiple Bedrock recipes to unlock for a single Java recipe * Unlock stonecutter recipes * Stonecutter recipes * Unlock tipped arrows/shulker box recipes even when Java doesnt (why..?), and dont send trims if Java doesn't * Translate FurnaceDataRecipes * Revert FurnaceRecipe translation, revert stone cutter recipe identifier caching - Bedrock does not need the smelting recipe, and doesn't (un)lock stonecutter recipes (yet...?) * Remove debug message * Make decorated pot crafting just a little bit smoother :p * formatting * Use itemTag descriptors to fix https://github.com/GeyserMC/Geyser/issues/3784 * Use hashmap instead to store item tag overrides * remove unnecessary comment * Address review by @Konicai * Support for 1.20.30 * undo add whitespace * Merge upstream, use FastUtil maps, rename a few methods * Address Camotoy's review * Fix formatting --- .../geysermc/geyser/network/GameProtocol.java | 8 ++ .../geyser/session/GeyserSession.java | 17 ++++ .../JavaClientboundRecipesTranslator.java | 79 +++++++++++++++++ .../java/JavaUpdateRecipesTranslator.java | 85 +++++++++++++++++-- 4 files changed, 181 insertions(+), 8 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaClientboundRecipesTranslator.java diff --git a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java index bf40ea2f9..5555375cd 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java @@ -93,6 +93,14 @@ public final class GameProtocol { return session.getUpstream().getProtocolVersion() < Bedrock_v594.CODEC.getProtocolVersion(); } + /** + * @param session the session to check + * @return true if the session needs an experiment for recipe unlocking + */ + public static boolean isUsingExperimentalRecipeUnlocking(GeyserSession session) { + return session.getUpstream().getProtocolVersion() == Bedrock_v594.CODEC.getProtocolVersion(); + } + /** * Gets the {@link PacketCodec} for Minecraft: Java Edition. * diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 35b532905..4d4b2a5ba 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -128,6 +128,7 @@ import org.geysermc.geyser.item.Items; import org.geysermc.geyser.level.JavaDimension; import org.geysermc.geyser.level.WorldManager; import org.geysermc.geyser.level.physics.CollisionManager; +import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.network.netty.LocalSession; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.type.BlockMappings; @@ -391,6 +392,13 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { @Setter private Entity mouseoverEntity; + /** + * Stores all Java recipes by recipe identifier, and matches them to all possible Bedrock recipe identifiers. + * They are not 1:1, since Bedrock can have multiple recipes for the same Java recipe. + */ + @Setter + private Map> javaToBedrockRecipeIds; + @Setter private Int2ObjectMap craftingRecipes; private final AtomicInteger lastRecipeNetId; @@ -611,6 +619,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { this.playerInventory = new PlayerInventory(); this.openInventory = null; this.craftingRecipes = new Int2ObjectOpenHashMap<>(); + this.javaToBedrockRecipeIds = new Object2ObjectOpenHashMap<>(); this.lastRecipeNetId = new AtomicInteger(1); this.spawned = false; @@ -690,6 +699,10 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { gamerulePacket.getGameRules().add(new GameRuleData<>("keepinventory", true)); // Ensure client doesn't try and do anything funky; the server handles this for us gamerulePacket.getGameRules().add(new GameRuleData<>("spawnradius", 0)); + // Recipe unlocking - only needs to be added if 1. it isn't already on via an experiment, or 2. the client is on pre 1.20.10 + if (!GameProtocol.isPre1_20_10(this) && !GameProtocol.isUsingExperimentalRecipeUnlocking(this)) { + gamerulePacket.getGameRules().add(new GameRuleData<>("recipesunlock", true)); + } upstream.sendPacket(gamerulePacket); } @@ -1527,6 +1540,10 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { startGamePacket.setRewindHistorySize(0); startGamePacket.setServerAuthoritativeBlockBreaking(false); + if (GameProtocol.isUsingExperimentalRecipeUnlocking(this)) { + startGamePacket.getExperiments().add(new ExperimentData("recipe_unlocking", true)); + } + upstream.sendPacket(startGamePacket); } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaClientboundRecipesTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaClientboundRecipesTranslator.java new file mode 100644 index 000000000..1ccbcfdec --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaClientboundRecipesTranslator.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2019-2023 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.translator.protocol.java; + +import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundRecipePacket; +import org.cloudburstmc.protocol.bedrock.packet.UnlockedRecipesPacket; +import org.geysermc.geyser.network.GameProtocol; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.protocol.PacketTranslator; +import org.geysermc.geyser.translator.protocol.Translator; + +import java.util.ArrayList; +import java.util.List; + +@Translator(packet = ClientboundRecipePacket.class) +public class JavaClientboundRecipesTranslator extends PacketTranslator { + + @Override + public void translate(GeyserSession session, ClientboundRecipePacket packet) { + // recipe unlocking does not exist pre 1.20.10 + if (GameProtocol.isPre1_20_10(session)) { + return; + } + + UnlockedRecipesPacket recipesPacket = new UnlockedRecipesPacket(); + switch (packet.getAction()) { + case INIT -> { + recipesPacket.setAction(UnlockedRecipesPacket.ActionType.INITIALLY_UNLOCKED); + recipesPacket.getUnlockedRecipes().addAll(getBedrockRecipes(session, packet.getAlreadyKnownRecipes())); + } + case ADD -> { + recipesPacket.setAction(UnlockedRecipesPacket.ActionType.NEWLY_UNLOCKED); + recipesPacket.getUnlockedRecipes().addAll(getBedrockRecipes(session, packet.getRecipes())); + } + case REMOVE -> { + recipesPacket.setAction(UnlockedRecipesPacket.ActionType.REMOVE_UNLOCKED); + recipesPacket.getUnlockedRecipes().addAll(getBedrockRecipes(session, packet.getRecipes())); + } + } + session.sendUpstreamPacket(recipesPacket); + } + + private List getBedrockRecipes(GeyserSession session, String[] javaRecipeIdentifiers) { + List recipes = new ArrayList<>(); + for (String javaIdentifier : javaRecipeIdentifiers) { + List bedrockRecipes = session.getJavaToBedrockRecipeIds().get(javaIdentifier); + // Some recipes are not (un)lockable on Bedrock edition, like furnace or stonecutter recipes. + // So we don't store/send these. + if (bedrockRecipes != null) { + recipes.addAll(bedrockRecipes); + } + } + return recipes; + } +} + diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java index 7a14cebcb..5beb1a201 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java @@ -44,6 +44,7 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.RecipeDa import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.SmithingTrimRecipeData; import org.cloudburstmc.protocol.bedrock.data.inventory.descriptor.DefaultDescriptor; import org.cloudburstmc.protocol.bedrock.data.inventory.descriptor.ItemDescriptorWithCount; +import org.cloudburstmc.protocol.bedrock.data.inventory.descriptor.ItemTagDescriptor; import org.cloudburstmc.protocol.bedrock.packet.CraftingDataPacket; import org.cloudburstmc.protocol.bedrock.packet.TrimDataPacket; import org.geysermc.geyser.GeyserImpl; @@ -67,7 +68,6 @@ import static org.geysermc.geyser.util.InventoryUtils.LAST_RECIPE_NET_ID; /** * Used to send all valid recipes from Java to Bedrock. - * * Bedrock REQUIRES a CraftingDataPacket to be sent in order to craft anything. */ @Translator(packet = ClientboundUpdateRecipesPacket.class) @@ -94,17 +94,27 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator RECIPE_TAGS = Map.of( + "minecraft:wood", "minecraft:logs", + "minecraft:wooden_slab", "minecraft:wooden_slabs", + "minecraft:planks", "minecraft:planks"); + @Override public void translate(GeyserSession session, ClientboundUpdateRecipesPacket packet) { Map> recipeTypes = Registries.CRAFTING_DATA.forVersion(session.getUpstream().getProtocolVersion()); // Get the last known network ID (first used for the pregenerated recipes) and increment from there. int netId = InventoryUtils.LAST_RECIPE_NET_ID + 1; boolean sendTrimRecipes = false; - + Map> recipeIDs = session.getJavaToBedrockRecipeIds(); Int2ObjectMap recipeMap = new Int2ObjectOpenHashMap<>(Registries.RECIPES.forVersion(session.getUpstream().getProtocolVersion())); Int2ObjectMap> unsortedStonecutterData = new Int2ObjectOpenHashMap<>(); CraftingDataPacket craftingDataPacket = new CraftingDataPacket(); craftingDataPacket.setCleanRecipes(true); + for (Recipe recipe : packet.getRecipes()) { switch (recipe.getType()) { case CRAFTING_SHAPELESS -> { @@ -121,12 +131,15 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator bedrockRecipeIDs = new ArrayList<>(); for (ItemDescriptorWithCount[] inputs : inputCombinations) { UUID uuid = UUID.randomUUID(); + bedrockRecipeIDs.add(uuid.toString()); craftingDataPacket.getCraftingData().add(org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.ShapelessRecipeData.shapeless(uuid.toString(), Arrays.asList(inputs), Collections.singletonList(output), uuid, "crafting_table", 0, netId)); recipeMap.put(netId++, new GeyserShapelessRecipe(shapelessRecipeData)); } + addRecipeIdentifier(session, recipe.getIdentifier(), bedrockRecipeIDs); } case CRAFTING_SHAPED -> { ShapedRecipeData shapedRecipeData = (ShapedRecipeData) recipe.getData(); @@ -141,13 +154,17 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator bedrockRecipeIDs = new ArrayList<>(); for (ItemDescriptorWithCount[] inputs : inputCombinations) { UUID uuid = UUID.randomUUID(); + bedrockRecipeIDs.add(uuid.toString()); craftingDataPacket.getCraftingData().add(org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.ShapedRecipeData.shaped(uuid.toString(), shapedRecipeData.getWidth(), shapedRecipeData.getHeight(), Arrays.asList(inputs), Collections.singletonList(output), uuid, "crafting_table", 0, netId)); recipeMap.put(netId++, new GeyserShapedRecipe(shapedRecipeData)); } + addRecipeIdentifier(session, recipe.getIdentifier(), bedrockRecipeIDs); } case STONECUTTING -> { StoneCuttingRecipeData stoneCuttingData = (StoneCuttingRecipeData) recipe.getData(); @@ -157,8 +174,8 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator(); unsortedStonecutterData.put(ingredient.getId(), data); } - data.add(stoneCuttingData); // Save for processing after all recipes have been received + data.add(stoneCuttingData); } case SMITHING_TRANSFORM -> { SmithingTransformRecipeData data = (SmithingTransformRecipeData) recipe.getData(); @@ -173,21 +190,29 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator(Collections.singletonList(id))); } } } - } case SMITHING_TRIM -> { sendTrimRecipes = true; // ignored currently - see below } + case CRAFTING_DECORATED_POT -> { + // Paper 1.20 seems to send only one recipe, which seems to be hardcoded to include all recipes. + // We can send the equivalent Bedrock MultiRecipe! :) + craftingDataPacket.getCraftingData().add(MultiRecipeData.of(UUID.fromString("685a742a-c42e-4a4e-88ea-5eb83fc98e5b"), netId++)); + } default -> { List craftingData = recipeTypes.get(recipe.getType()); if (craftingData != null) { + addSpecialRecipesIdentifiers(session, recipe, craftingData); craftingDataPacket.getCraftingData().addAll(craftingData); } } @@ -218,14 +243,15 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator craftingData) { + String javaRecipeID = recipe.getIdentifier(); + + switch (recipe.getType()) { + case CRAFTING_SPECIAL_BOOKCLONING, CRAFTING_SPECIAL_REPAIRITEM, CRAFTING_SPECIAL_MAPEXTENDING, CRAFTING_SPECIAL_MAPCLONING: + // We do not want to (un)lock these, since BDS does not do it for MultiRecipes + return; + case CRAFTING_SPECIAL_SHULKERBOXCOLORING: + // BDS (un)locks the dyeing with the shulker box recipe, Java never - we want BDS behavior for ease of use + javaRecipeID = "minecraft:shulker_box"; + break; + case CRAFTING_SPECIAL_TIPPEDARROW: + // similar as above + javaRecipeID = "minecraft:arrow"; + break; + } + List bedrockRecipeIDs = new ArrayList<>(); + + // defined in the recipes.json mappings file: Only tipped arrows use shaped recipes, we need the cast for the identifier + if (recipe.getType() == RecipeType.CRAFTING_SPECIAL_TIPPEDARROW) { + for (RecipeData data : craftingData) { + bedrockRecipeIDs.add(((org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.ShapedRecipeData) data).getId()); + } + } else { + for (RecipeData data : craftingData) { + bedrockRecipeIDs.add(((org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.ShapelessRecipeData) data).getId()); + } + } + addRecipeIdentifier(session, javaRecipeID, bedrockRecipeIDs); } //TODO: rewrite @@ -277,6 +335,13 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator> entry : groupedByIds.entrySet()) { if (entry.getValue().size() > 1) { GroupedItem groupedItem = entry.getKey(); + + String recipeTag = RECIPE_TAGS.get(groupedItem.id.getIdentifier()); + if (recipeTag != null) { + optionSet.add(new ItemDescriptorWithCount(new ItemTagDescriptor(recipeTag), groupedItem.count)); + continue; + } + int idCount = 0; //not optimal for (ItemMapping mapping : session.getItemMappings().getItems()) { @@ -337,6 +402,10 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator bedrockIdentifiers) { + session.getJavaToBedrockRecipeIds().computeIfAbsent(javaIdentifier, k -> new ArrayList<>()).addAll(bedrockIdentifiers); + } + @EqualsAndHashCode @AllArgsConstructor private static class GroupedItem { From 0ebb7232f97721392ed3115ab752650cf42aa2d5 Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 10 Nov 2023 23:44:38 +0100 Subject: [PATCH 119/344] Add SessionDisconnectEvent (#4052) * Add SessionDisconnectEvent * Move disconnect event calling to UpstreamSession, debug double calling issues * Prevent duplicate disconnect calling * Tidy up disconnection logic, ensure SessionDisconnectEvent is always fired - but only once. Fix /geyser reload command --- .../event/bedrock/SessionDisconnectEvent.java | 61 +++++++++++++++++++ .../command/defaults/ReloadCommand.java | 5 +- .../geyser/session/GeyserSession.java | 28 +++++++-- .../geyser/session/UpstreamSession.java | 2 +- 4 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionDisconnectEvent.java diff --git a/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionDisconnectEvent.java b/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionDisconnectEvent.java new file mode 100644 index 000000000..05e3415a0 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionDisconnectEvent.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2019-2023 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.api.event.bedrock; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.api.connection.GeyserConnection; +import org.geysermc.geyser.api.event.connection.ConnectionEvent; + +/** + * Called when a Geyser session disconnects. + */ +public class SessionDisconnectEvent extends ConnectionEvent { + private String disconnectReason; + + public SessionDisconnectEvent(@NonNull GeyserConnection connection, @NonNull String reason) { + super(connection); + this.disconnectReason = reason; + } + + /** + * Gets the disconnect reason. + * + * @return the reason for the disconnect + */ + public @NonNull String disconnectReason() { + return disconnectReason; + } + + /** + * Sets the disconnect reason, thereby overriding th original reason. + * + * @param disconnectReason the reason for the disconnect + */ + public void disconnectReason(@NonNull String disconnectReason) { + this.disconnectReason = disconnectReason; + } +} + diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/ReloadCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/ReloadCommand.java index 8f147cdab..a3cd8fa4c 100644 --- a/core/src/main/java/org/geysermc/geyser/command/defaults/ReloadCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/ReloadCommand.java @@ -32,6 +32,8 @@ import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.GeyserLocale; +import java.util.concurrent.TimeUnit; + public class ReloadCommand extends GeyserCommand { private final GeyserImpl geyser; @@ -52,7 +54,8 @@ public class ReloadCommand extends GeyserCommand { sender.sendMessage(message); geyser.getSessionManager().disconnectAll("geyser.commands.reload.kick"); - geyser.reload(); + //FIXME Without the tiny wait, players do not get kicked - same happens when Geyser tries to disconnect all sessions on shutdown + geyser.getScheduledThread().schedule(geyser::reload, 10, TimeUnit.MILLISECONDS); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 4d4b2a5ba..ebb0025da 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -105,6 +105,7 @@ import org.geysermc.geyser.api.bedrock.camera.CameraShake; import org.geysermc.geyser.api.connection.GeyserConnection; import org.geysermc.geyser.api.entity.type.GeyserEntity; import org.geysermc.geyser.api.entity.type.player.GeyserPlayerEntity; +import org.geysermc.geyser.api.event.bedrock.SessionDisconnectEvent; import org.geysermc.geyser.api.event.bedrock.SessionLoginEvent; import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.api.network.RemoteServer; @@ -1038,10 +1039,14 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { geyser.getLogger().info(GeyserLocale.getLocaleStringLog("geyser.network.remote.disconnect", authData.name(), remoteServer.address(), disconnectMessage)); } if (cause != null) { - cause.printStackTrace(); + GeyserImpl.getInstance().getLogger().error(cause.getMessage()); + // GeyserSession is disconnected via session.disconnect() called indirectly be the server + // This only needs to be "initiated" here when there is an exception, hence the cause clause + GeyserSession.this.disconnect(disconnectMessage); + if (geyser.getConfig().isDebugMode()) { + cause.printStackTrace(); + } } - - upstream.disconnect(disconnectMessage); } @Override @@ -1068,17 +1073,30 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { public void disconnect(String reason) { if (!closed) { loggedIn = false; + + // Fire SessionDisconnectEvent + SessionDisconnectEvent disconnectEvent = new SessionDisconnectEvent(this, reason); + geyser.getEventBus().fire(disconnectEvent); + + // Disconnect downstream if necessary if (downstream != null) { - downstream.disconnect(reason); + // No need to disconnect if already closed + if (!downstream.isClosed()) { + downstream.disconnect(reason); + } } else { // Downstream's disconnect will fire an event that prints a log message // Otherwise, we print a message here String address = geyser.getConfig().isLogPlayerIpAddresses() ? upstream.getAddress().getAddress().toString() : ""; geyser.getLogger().info(GeyserLocale.getLocaleStringLog("geyser.network.disconnect", address, reason)); } + + // Disconnect upstream if necessary if (!upstream.isClosed()) { - upstream.disconnect(reason); + upstream.disconnect(disconnectEvent.disconnectReason()); } + + // Remove from session manager geyser.getSessionManager().removeSession(this); if (authData != null) { PendingMicrosoftAuthentication.AuthenticationTask task = geyser.getPendingMicrosoftAuthentication().getTask(authData.xuid()); diff --git a/core/src/main/java/org/geysermc/geyser/session/UpstreamSession.java b/core/src/main/java/org/geysermc/geyser/session/UpstreamSession.java index ef462a3e3..35ede56a1 100644 --- a/core/src/main/java/org/geysermc/geyser/session/UpstreamSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/UpstreamSession.java @@ -58,7 +58,7 @@ public class UpstreamSession { } public void disconnect(String reason) { - session.disconnect(reason); + this.session.disconnect(reason); } /** From 81178ba2a070aa41a133c3817759c7b43e262d12 Mon Sep 17 00:00:00 2001 From: chris Date: Sat, 11 Nov 2023 02:25:02 +0100 Subject: [PATCH 120/344] Reset weather on dimension switch (#4283) --- .../protocol/java/JavaLoginTranslator.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java index e7539bd0f..377f1d2cf 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java @@ -28,8 +28,11 @@ package org.geysermc.geyser.translator.protocol.java; import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerSpawnInfo; import com.github.steveice10.mc.protocol.packet.common.serverbound.ServerboundCustomPayloadPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundLoginPacket; +import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.GameRuleData; +import org.cloudburstmc.protocol.bedrock.data.LevelEvent; import org.cloudburstmc.protocol.bedrock.packet.GameRulesChangedPacket; +import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket; import org.cloudburstmc.protocol.bedrock.packet.SetPlayerGameTypePacket; import org.geysermc.floodgate.pluginmessage.PluginMessageChannels; import org.geysermc.geyser.api.network.AuthType; @@ -70,6 +73,25 @@ public class JavaLoginTranslator extends PacketTranslator Date: Sat, 11 Nov 2023 13:26:28 -0500 Subject: [PATCH 121/344] Address #4281 --- .../bungeecord/GeyserBungeeCompressionDisabler.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeCompressionDisabler.java b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeCompressionDisabler.java index 084e1d2dc..485079a05 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeCompressionDisabler.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeCompressionDisabler.java @@ -32,18 +32,26 @@ import net.md_5.bungee.protocol.packet.LoginSuccess; import net.md_5.bungee.protocol.packet.SetCompression; public class GeyserBungeeCompressionDisabler extends ChannelOutboundHandlerAdapter { + private boolean compressionDisabled = false; @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { if (!(msg instanceof SetCompression)) { - if (msg instanceof LoginSuccess) { - // We're past the point that compression can be enabled + // Fixes https://github.com/GeyserMC/Geyser/issues/4281 + // The server may send a LoginDisconnect packet after compression is set. + if (!compressionDisabled) { if (ctx.pipeline().get("compress") != null) { ctx.pipeline().remove("compress"); + compressionDisabled = true; } if (ctx.pipeline().get("decompress") != null) { ctx.pipeline().remove("decompress"); + compressionDisabled = true; } + } + + if (msg instanceof LoginSuccess) { + // We're past the point that compression can be enabled ctx.pipeline().remove(this); } super.write(ctx, msg, promise); From 13339f1ed1273050fafd553ea6210c635d24e4a7 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sat, 11 Nov 2023 17:14:15 -0500 Subject: [PATCH 122/344] Dragon and piglin heads now animate on 1.20.2 servers --- .../geyser/level/block/BlockStateValues.java | 19 +++++++++++++++++++ .../entity/SkullBlockEntityTranslator.java | 3 +++ 2 files changed, 22 insertions(+) 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 97ab18c6b..11702e78a 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 @@ -62,6 +62,7 @@ public final class BlockStateValues { private static final IntSet ALL_PISTON_HEADS = new IntOpenHashSet(); private static final IntSet MOVING_PISTONS = new IntOpenHashSet(); private static final Int2ByteMap SKULL_VARIANTS = new FixedInt2ByteMap(); + private static final IntSet SKULL_POWERED = new IntOpenHashSet(); 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(); @@ -172,6 +173,13 @@ public final class BlockStateValues { SKULL_ROTATIONS.put(javaBlockState, (byte) skullRotation.intValue()); } + if (javaId.startsWith("minecraft:dragon_head[") || javaId.startsWith("minecraft:piglin_head[") + || javaId.startsWith("minecraft:dragon_wall_head[") || javaId.startsWith("minecraft:piglin_wall_head[")) { + if (javaId.contains("powered=true")) { + SKULL_POWERED.add(javaBlockState); + } + } + if (javaId.contains("wall_skull") || javaId.contains("wall_head")) { String direction = javaId.substring(javaId.lastIndexOf("facing=") + 7, javaId.lastIndexOf("powered=") - 1); int rotation = switch (direction) { @@ -448,6 +456,17 @@ public final class BlockStateValues { return SKULL_ROTATIONS.getOrDefault(state, (byte) -1); } + /** + * As of Java 1.20.2: + * Skull powered states are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock. + * + * @param state BlockState of the block + * @return true if this skull is currently being powered. + */ + public static boolean isSkullPowered(int state) { + return SKULL_POWERED.contains(state); + } + /** * Skull rotations are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock. * This gives a integer rotation that Bedrock can use. diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java index 76cdbb5a4..7f87f9465 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java @@ -60,6 +60,9 @@ public class SkullBlockEntityTranslator extends BlockEntityTranslator implements } builder.put("Rotation", rotation); builder.put("SkullType", skullVariant); + if (BlockStateValues.isSkullPowered(blockState)) { + builder.putBoolean("MouthMoving", true); + } } private static UUID getUUID(CompoundTag owner) { From bb6a1ec40ab42c8b57ee4a427683410302b43774 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Mon, 13 Nov 2023 18:17:40 -0500 Subject: [PATCH 123/344] Simply pingpassthrough logic, add fabric ping passthrough (#3930) * Check if PingPassthrough is null * Remove QueryPacketHandler * Fabric ping passthrough --- .../GeyserBungeePingPassthrough.java | 12 +- .../platform/fabric/GeyserFabricMod.java | 6 +- .../platform/fabric/ModPingPassthrough.java | 110 +++++++ .../spigot/GeyserPaperPingPassthrough.java | 12 +- .../spigot/GeyserSpigotPingPassthrough.java | 8 +- .../GeyserVelocityPingPassthrough.java | 14 +- .../org/geysermc/geyser/GeyserBootstrap.java | 9 +- .../configuration/GeyserConfiguration.java | 3 - .../GeyserJacksonConfiguration.java | 3 - .../geyser/network/QueryPacketHandler.java | 303 ------------------ .../geyser/network/netty/GeyserServer.java | 21 +- .../geysermc/geyser/ping/GeyserPingInfo.java | 39 +-- .../geyser/ping/IGeyserPingPassthrough.java | 11 - core/src/main/resources/config.yml | 3 - 14 files changed, 160 insertions(+), 394 deletions(-) create mode 100644 bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/ModPingPassthrough.java delete mode 100644 core/src/main/java/org/geysermc/geyser/network/QueryPacketHandler.java diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePingPassthrough.java b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePingPassthrough.java index 39fb9e134..e14e8ff66 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePingPassthrough.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePingPassthrough.java @@ -40,7 +40,6 @@ import org.geysermc.geyser.ping.IGeyserPingPassthrough; import java.net.InetSocketAddress; import java.net.SocketAddress; -import java.util.Arrays; import java.util.UUID; import java.util.concurrent.CompletableFuture; @@ -61,16 +60,11 @@ public class GeyserBungeePingPassthrough implements IGeyserPingPassthrough, List })); ProxyPingEvent event = future.join(); ServerPing response = event.getResponse(); - GeyserPingInfo geyserPingInfo = new GeyserPingInfo( + return new GeyserPingInfo( response.getDescriptionComponent().toLegacyText(), - new GeyserPingInfo.Players(response.getPlayers().getMax(), response.getPlayers().getOnline()), - new GeyserPingInfo.Version(response.getVersion().getName(), response.getVersion().getProtocol()) + response.getPlayers().getMax(), + response.getPlayers().getOnline() ); - if (event.getResponse().getPlayers().getSample() != null) { - Arrays.stream(event.getResponse().getPlayers().getSample()).forEach(proxiedPlayer -> - geyserPingInfo.getPlayerList().add(proxiedPlayer.getName())); - } - return geyserPingInfo; } // This is static so pending connection can use it diff --git a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMod.java b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMod.java index 0bbe73f16..af0c9efca 100644 --- a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMod.java +++ b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMod.java @@ -144,7 +144,11 @@ public class GeyserFabricMod implements ModInitializer, GeyserBootstrap { GeyserImpl.start(); - this.geyserPingPassthrough = GeyserLegacyPingPassthrough.init(geyser); + if (geyserConfig.isLegacyPingPassthrough()) { + this.geyserPingPassthrough = GeyserLegacyPingPassthrough.init(geyser); + } else { + this.geyserPingPassthrough = new ModPingPassthrough(server, geyserLogger); + } this.geyserCommandManager = new GeyserCommandManager(geyser); this.geyserCommandManager.init(); diff --git a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/ModPingPassthrough.java b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/ModPingPassthrough.java new file mode 100644 index 000000000..e74be7fb7 --- /dev/null +++ b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/ModPingPassthrough.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2019-2023 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.platform.fabric; + +import lombok.AllArgsConstructor; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import net.minecraft.network.Connection; +import net.minecraft.network.PacketSendListener; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.PacketFlow; +import net.minecraft.network.protocol.status.ClientboundStatusResponsePacket; +import net.minecraft.network.protocol.status.ServerStatus; +import net.minecraft.network.protocol.status.ServerStatusPacketListener; +import net.minecraft.network.protocol.status.ServerboundStatusRequestPacket; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerStatusPacketListenerImpl; +import org.geysermc.geyser.GeyserLogger; +import org.geysermc.geyser.ping.GeyserPingInfo; +import org.geysermc.geyser.ping.IGeyserPingPassthrough; +import org.jetbrains.annotations.Nullable; + +import java.net.InetSocketAddress; +import java.util.Objects; + +@AllArgsConstructor +public class ModPingPassthrough implements IGeyserPingPassthrough { + + private static final GsonComponentSerializer GSON_SERIALIZER = GsonComponentSerializer.gson(); + private static final LegacyComponentSerializer LEGACY_SERIALIZER = LegacyComponentSerializer.legacySection(); + + private final MinecraftServer server; + private final GeyserLogger logger; + + @Nullable + @Override + public GeyserPingInfo getPingInformation(InetSocketAddress inetSocketAddress) { + ServerStatus status = server.getStatus(); + if (status == null) { + return null; + } + + try { + StatusInterceptor connection = new StatusInterceptor(); + ServerStatusPacketListener statusPacketListener = new ServerStatusPacketListenerImpl(status, connection); + + statusPacketListener.handleStatusRequest(new ServerboundStatusRequestPacket()); + // mods like MiniMOTD (that inject into the above method) have now processed the response + status = Objects.requireNonNull(connection.status, "status response"); + } catch (Exception e) { + if (logger.isDebug()) { + logger.debug("Failed to listen for modified ServerStatus: " + e.getMessage()); + e.printStackTrace(); + } + } + + String jsonDescription = net.minecraft.network.chat.Component.Serializer.toJson(status.description()); + String legacyDescription = LEGACY_SERIALIZER.serialize(GSON_SERIALIZER.deserializeOr(jsonDescription, Component.empty())); + + return new GeyserPingInfo( + legacyDescription, + status.players().map(ServerStatus.Players::max).orElse(1), + status.players().map(ServerStatus.Players::online).orElse(0) + ); + } + + /** + * Custom Connection that intercepts the status response right before it is sent + */ + private static class StatusInterceptor extends Connection { + + ServerStatus status; + + StatusInterceptor() { + super(PacketFlow.SERVERBOUND); // we are the server. + } + + @Override + public void send(Packet packet, @Nullable PacketSendListener packetSendListener, boolean bl) { + if (packet instanceof ClientboundStatusResponsePacket statusResponse) { + status = statusResponse.status(); + } + super.send(packet, packetSendListener, bl); + } + } +} diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserPaperPingPassthrough.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserPaperPingPassthrough.java index bb0f30e70..60e0ae519 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserPaperPingPassthrough.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserPaperPingPassthrough.java @@ -27,7 +27,6 @@ package org.geysermc.geyser.platform.spigot; import com.destroystokyo.paper.event.server.PaperServerListPingEvent; import com.destroystokyo.paper.network.StatusClient; -import com.destroystokyo.paper.profile.PlayerProfile; import org.bukkit.Bukkit; import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.ping.GeyserPingInfo; @@ -81,16 +80,7 @@ public final class GeyserPaperPingPassthrough implements IGeyserPingPassthrough players = new GeyserPingInfo.Players(event.getMaxPlayers(), event.getNumPlayers()); } - GeyserPingInfo geyserPingInfo = new GeyserPingInfo(event.getMotd(), players, - new GeyserPingInfo.Version(Bukkit.getVersion(), GameProtocol.getJavaProtocolVersion())); - - if (!event.shouldHidePlayers()) { - for (PlayerProfile profile : event.getPlayerSample()) { - geyserPingInfo.getPlayerList().add(profile.getName()); - } - } - - return geyserPingInfo; + return new GeyserPingInfo(event.getMotd(), players); } catch (Exception | LinkageError e) { // LinkageError in the event that method/constructor signatures change logger.debug("Error while getting Paper ping passthrough: " + e); return null; diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPingPassthrough.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPingPassthrough.java index 1e6a0ad6c..df197f137 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPingPassthrough.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPingPassthrough.java @@ -30,7 +30,6 @@ import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.server.ServerListPingEvent; import org.bukkit.util.CachedServerIcon; -import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.ping.GeyserPingInfo; import org.geysermc.geyser.ping.IGeyserPingPassthrough; @@ -50,12 +49,7 @@ public class GeyserSpigotPingPassthrough implements IGeyserPingPassthrough { try { ServerListPingEvent event = new GeyserPingEvent(inetSocketAddress.getAddress(), Bukkit.getMotd(), Bukkit.getOnlinePlayers().size(), Bukkit.getMaxPlayers()); Bukkit.getPluginManager().callEvent(event); - GeyserPingInfo geyserPingInfo = new GeyserPingInfo(event.getMotd(), - new GeyserPingInfo.Players(event.getMaxPlayers(), event.getNumPlayers()), - new GeyserPingInfo.Version(Bukkit.getVersion(), GameProtocol.getJavaProtocolVersion()) // thanks Spigot for not exposing this, just default to latest - ); - Bukkit.getOnlinePlayers().stream().map(Player::getName).forEach(geyserPingInfo.getPlayerList()::add); - return geyserPingInfo; + return new GeyserPingInfo(event.getMotd(), event.getMaxPlayers(), event.getNumPlayers()); } catch (Exception | LinkageError e) { // LinkageError in the event that method/constructor signatures change logger.debug("Error while getting Bukkit ping passthrough: " + e); return null; diff --git a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPingPassthrough.java b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPingPassthrough.java index 1a9b9bf26..8944ea134 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPingPassthrough.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPingPassthrough.java @@ -54,19 +54,11 @@ public class GeyserVelocityPingPassthrough implements IGeyserPingPassthrough { } catch (ExecutionException | InterruptedException e) { throw new RuntimeException(e); } - GeyserPingInfo geyserPingInfo = new GeyserPingInfo( + return new GeyserPingInfo( LegacyComponentSerializer.legacy('§').serialize(event.getPing().getDescriptionComponent()), - new GeyserPingInfo.Players( - event.getPing().getPlayers().orElseThrow(IllegalStateException::new).getMax(), - event.getPing().getPlayers().orElseThrow(IllegalStateException::new).getOnline() - ), - new GeyserPingInfo.Version( - event.getPing().getVersion().getName(), - event.getPing().getVersion().getProtocol() - ) + event.getPing().getPlayers().map(ServerPing.Players::getMax).orElse(1), + event.getPing().getPlayers().map(ServerPing.Players::getOnline).orElse(0) ); - event.getPing().getPlayers().get().getSample().stream().map(ServerPing.SamplePlayer::getName).forEach(geyserPingInfo.getPlayerList()::add); - return geyserPingInfo; } private static class GeyserInboundConnection implements InboundConnection { diff --git a/core/src/main/java/org/geysermc/geyser/GeyserBootstrap.java b/core/src/main/java/org/geysermc/geyser/GeyserBootstrap.java index e4baeebb5..1827cfb36 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserBootstrap.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserBootstrap.java @@ -25,6 +25,8 @@ package org.geysermc.geyser; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.command.GeyserCommandManager; import org.geysermc.geyser.configuration.GeyserConfiguration; import org.geysermc.geyser.dump.BootstrapDumpInfo; @@ -32,8 +34,6 @@ import org.geysermc.geyser.level.GeyserWorldManager; import org.geysermc.geyser.level.WorldManager; import org.geysermc.geyser.ping.IGeyserPingPassthrough; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.io.InputStream; import java.net.SocketAddress; import java.nio.file.Path; @@ -79,6 +79,7 @@ public interface GeyserBootstrap { * * @return The current PingPassthrough manager */ + @Nullable IGeyserPingPassthrough getGeyserPingPassthrough(); /** @@ -151,7 +152,7 @@ public interface GeyserBootstrap { * @param resource Resource to get * @return InputStream of the given resource */ - default @Nonnull InputStream getResource(String resource) { + default @NonNull InputStream getResource(String resource) { InputStream stream = getResourceOrNull(resource); if (stream == null) { throw new AssertionError("Unable to find resource: " + resource); @@ -162,7 +163,7 @@ public interface GeyserBootstrap { /** * @return the bind address being used by the Java server. */ - @Nonnull + @NonNull String getServerBindAddress(); /** diff --git a/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java b/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java index e36ec819b..51cd7d4ae 100644 --- a/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java +++ b/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java @@ -57,9 +57,6 @@ public interface GeyserConfiguration { @JsonIgnore boolean isPassthroughMotd(); - @JsonIgnore - boolean isPassthroughProtocolName(); - @JsonIgnore boolean isPassthroughPlayerCounts(); diff --git a/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java b/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java index 268304844..95ac7b1de 100644 --- a/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java +++ b/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java @@ -75,9 +75,6 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration @JsonProperty("passthrough-player-counts") private boolean isPassthroughPlayerCounts = false; - @JsonProperty("passthrough-protocol-name") - private boolean isPassthroughProtocolName = false; - @JsonProperty("legacy-ping-passthrough") private boolean isLegacyPingPassthrough = false; diff --git a/core/src/main/java/org/geysermc/geyser/network/QueryPacketHandler.java b/core/src/main/java/org/geysermc/geyser/network/QueryPacketHandler.java deleted file mode 100644 index 74e1430a2..000000000 --- a/core/src/main/java/org/geysermc/geyser/network/QueryPacketHandler.java +++ /dev/null @@ -1,303 +0,0 @@ -/* - * 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.network; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import org.geysermc.geyser.GeyserImpl; -import org.geysermc.geyser.ping.GeyserPingInfo; -import org.geysermc.geyser.translator.text.MessageTranslator; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ThreadLocalRandom; - -public class QueryPacketHandler { - public static final byte HANDSHAKE = 0x09; - public static final byte STATISTICS = 0x00; - - private final GeyserImpl geyser; - private final InetSocketAddress sender; - private final byte type; - private final int sessionId; - private byte[] token; - - /** - * The Query packet handler instance. The unsigned short magic handshake should already be read at this point, - * and the packet should be verified to have enough buffer space to be a qualified query packet. - * - * @param geyser Geyser - * @param sender The Sender IP/Port for the Query - * @param buffer The Query data - */ - public QueryPacketHandler(GeyserImpl geyser, InetSocketAddress sender, ByteBuf buffer) { - this.geyser = geyser; - this.sender = sender; - this.type = buffer.readByte(); - this.sessionId = buffer.readInt(); - - regenerateToken(); - handle(); - } - - /** - * Checks the packet is in fact a query packet - * - * @param buffer Query data - * @return if the packet is a query packet - */ - public static boolean isQueryPacket(ByteBuf buffer) { - // 2 for magic short, 1 for type byte and 4 for session ID int - return buffer.readableBytes() >= (2 + 1 + 4) && buffer.readUnsignedShort() == 0xFEFD; - } - - /** - * Handles the query - */ - private void handle() { - switch (type) { - case HANDSHAKE: - sendToken(); - break; - case STATISTICS: - sendQueryData(); - break; - } - } - - /** - * Sends the token to the sender - */ - private void sendToken() { - ByteBuf reply = ByteBufAllocator.DEFAULT.ioBuffer(10); - reply.writeByte(HANDSHAKE); - reply.writeInt(sessionId); - reply.writeBytes(getTokenString(this.token, this.sender.getAddress())); - reply.writeByte(0); - - sendPacket(reply); - } - - /** - * Sends the query data to the sender - */ - private void sendQueryData() { - byte[] gameData = getGameData(); - byte[] playerData = getPlayers(); - - ByteBuf reply = ByteBufAllocator.DEFAULT.ioBuffer(1 + 4 + gameData.length + playerData.length); - reply.writeByte(STATISTICS); - reply.writeInt(sessionId); - - // Game Info - reply.writeBytes(gameData); - - // Players - reply.writeBytes(playerData); - - sendPacket(reply); - } - - /** - * Gets the game data for the query - * - * @return the game data for the query - */ - private byte[] getGameData() { - ByteArrayOutputStream query = new ByteArrayOutputStream(); - - GeyserPingInfo pingInfo = null; - String motd; - String currentPlayerCount; - String maxPlayerCount; - String map; - - if (geyser.getConfig().isPassthroughMotd() || geyser.getConfig().isPassthroughPlayerCounts()) { - pingInfo = geyser.getBootstrap().getGeyserPingPassthrough().getPingInformation(); - } - - if (geyser.getConfig().isPassthroughMotd() && pingInfo != null) { - String[] javaMotd = MessageTranslator.convertMessageLenient(pingInfo.getDescription()).split("\n"); - motd = javaMotd[0].trim(); // First line of the motd. - } else { - motd = geyser.getConfig().getBedrock().primaryMotd(); - } - - // If passthrough player counts is enabled lets get players from the server - if (geyser.getConfig().isPassthroughPlayerCounts() && pingInfo != null) { - currentPlayerCount = String.valueOf(pingInfo.getPlayers().getOnline()); - maxPlayerCount = String.valueOf(pingInfo.getPlayers().getMax()); - } else { - currentPlayerCount = String.valueOf(geyser.getSessionManager().getSessions().size()); - maxPlayerCount = String.valueOf(geyser.getConfig().getMaxPlayers()); - } - - // If passthrough protocol name is enabled let's get the protocol name from the ping response. - if (geyser.getConfig().isPassthroughProtocolName() && pingInfo != null) { - map = pingInfo.getVersion().getName(); - } else { - map = GeyserImpl.NAME; - } - - // Create a hashmap of all game data needed in the query - Map gameData = new HashMap<>(); - gameData.put("hostname", motd); - gameData.put("gametype", "SMP"); - gameData.put("game_id", "MINECRAFT"); - gameData.put("version", GeyserImpl.NAME + " (" + GeyserImpl.GIT_VERSION + ") " + GameProtocol.DEFAULT_BEDROCK_CODEC.getMinecraftVersion()); - gameData.put("plugins", ""); - gameData.put("map", map); - gameData.put("numplayers", currentPlayerCount); - gameData.put("maxplayers", maxPlayerCount); - gameData.put("hostport", String.valueOf(geyser.getConfig().getBedrock().port())); - gameData.put("hostip", geyser.getConfig().getBedrock().address()); - - try { - writeString(query, "GeyserMC"); - query.write((byte) 0x80); - query.write((byte) 0x00); - - // Fills the game data - for (Map.Entry entry : gameData.entrySet()) { - writeString(query, entry.getKey()); - writeString(query, entry.getValue()); - } - - // Final byte to show the end of the game data - query.write(new byte[] { 0x00, 0x01 }); - return query.toByteArray(); - } catch (IOException e) { - e.printStackTrace(); - return new byte[0]; - } - } - - /** - * Generate a byte[] storing the player names - * - * @return The byte[] representation of players - */ - private byte[] getPlayers() { - ByteArrayOutputStream query = new ByteArrayOutputStream(); - - GeyserPingInfo pingInfo = null; - if (geyser.getConfig().isPassthroughMotd() || geyser.getConfig().isPassthroughPlayerCounts()) { - pingInfo = geyser.getBootstrap().getGeyserPingPassthrough().getPingInformation(); - } - - try { - // Start the player section - writeString(query, "player_"); - query.write((byte) 0x00); - - // Fill player names - if (pingInfo != null) { - for (String username : pingInfo.getPlayerList()) { - writeString(query, username); - } - } - - // Final byte to show the end of the player data - query.write((byte) 0x00); - return query.toByteArray(); - } catch (IOException e) { - e.printStackTrace(); - return new byte[0]; - } - } - - /** - * Partially mimics {@link java.io.DataOutputStream#writeBytes(String)} which is what the Minecraft server uses as of 1.17.1. - */ - private void writeString(OutputStream stream, String value) throws IOException { - int length = value.length(); - for (int i = 0; i < length; i++) { - stream.write((byte) value.charAt(i)); - } - // Padding to indicate the end of the string - stream.write((byte) 0x00); - } - - /** - * Sends a packet to the sender - * - * @param data packet data - */ - private void sendPacket(ByteBuf data) { - // geyser.getBedrockServer().getRakNet().send(sender, data); - } - - /** - * Regenerates a token - */ - public void regenerateToken() { - byte[] token = new byte[16]; - for (int i = 0; i < 16; i++) { - token[i] = (byte) ThreadLocalRandom.current().nextInt(255); - } - - this.token = token; - } - - /** - * Gets an MD5 token for the current IP/Port. - * This should reset every 30 seconds but a new one is generated per instance - * Seems wasteful to code something in to clear it when it has no use. - * - * @param token the token - * @param address the address - * @return an MD5 token for the current IP/Port - */ - public static byte[] getTokenString(byte[] token, InetAddress address) { - try { - // Generate an MD5 hash from the address - MessageDigest digest = MessageDigest.getInstance("MD5"); - digest.update(address.toString().getBytes(StandardCharsets.UTF_8)); - digest.update(token); - - // Get the first 4 bytes of the digest - byte[] digestBytes = Arrays.copyOf(digest.digest(), 4); - - // Convert the bytes to a buffer - ByteBuffer byteBuffer = ByteBuffer.wrap(digestBytes); - - // Turn the number into a null terminated string - return (byteBuffer.getInt() + "\0").getBytes(); - } catch (NoSuchAlgorithmException e) { - return (ByteBuffer.allocate(4).putInt(ThreadLocalRandom.current().nextInt()).getInt() + "\0").getBytes(); - } - } -} diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java b/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java index c89da0bdd..a811d8437 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java @@ -69,6 +69,7 @@ import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.function.IntFunction; +import java.util.function.Supplier; public final class GeyserServer { private static final boolean PRINT_DEBUG_PINGS = Boolean.parseBoolean(System.getProperty("Geyser.PrintPingsInDebugMode", "true")); @@ -163,8 +164,9 @@ public final class GeyserServer { if (System.getProperties().contains("disableNativeEventLoop")) { this.geyser.getLogger().debug("EventLoop type is NIO because native event loops are disabled."); } else { - this.geyser.getLogger().debug("Reason for no Epoll: " + Epoll.unavailabilityCause().toString()); - this.geyser.getLogger().debug("Reason for no KQueue: " + KQueue.unavailabilityCause().toString()); + // Use lambda here, not method reference, or else NoClassDefFoundError for Epoll/KQueue will not be caught + this.geyser.getLogger().debug("Reason for no Epoll: " + throwableOrCaught(() -> Epoll.unavailabilityCause())); + this.geyser.getLogger().debug("Reason for no KQueue: " + throwableOrCaught(() -> KQueue.unavailabilityCause())); } } } @@ -230,7 +232,9 @@ public final class GeyserServer { GeyserPingInfo pingInfo = null; if (config.isPassthroughMotd() || config.isPassthroughPlayerCounts()) { IGeyserPingPassthrough pingPassthrough = geyser.getBootstrap().getGeyserPingPassthrough(); - pingInfo = pingPassthrough.getPingInformation(inetSocketAddress); + if (pingPassthrough != null) { + pingInfo = pingPassthrough.getPingInformation(inetSocketAddress); + } } BedrockPong pong = new BedrockPong() @@ -312,6 +316,17 @@ public final class GeyserServer { return pong; } + /** + * @return the throwable from the given supplier, or the throwable caught while calling the supplier. + */ + private static Throwable throwableOrCaught(Supplier supplier) { + try { + return supplier.get(); + } catch (Throwable throwable) { + return throwable; + } + } + private static Transport compatibleTransport() { TransportHelper.TransportMethod transportMethod = TransportHelper.determineTransportMethod(); if (transportMethod == TransportHelper.TransportMethod.EPOLL) { diff --git a/core/src/main/java/org/geysermc/geyser/ping/GeyserPingInfo.java b/core/src/main/java/org/geysermc/geyser/ping/GeyserPingInfo.java index d444e554c..9d8da114d 100644 --- a/core/src/main/java/org/geysermc/geyser/ping/GeyserPingInfo.java +++ b/core/src/main/java/org/geysermc/geyser/ping/GeyserPingInfo.java @@ -25,34 +25,37 @@ package org.geysermc.geyser.ping; -import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.databind.JsonNode; import lombok.Data; +import org.checkerframework.checker.nullness.qual.Nullable; -import java.util.ArrayList; -import java.util.Collection; - +/** + * The structure of this class and its nested classes are specifically + * designed for the format received by {@link GeyserLegacyPingPassthrough}. + */ @Data @JsonIgnoreProperties(ignoreUnknown = true) public class GeyserPingInfo { + @Nullable private String description; private Players players; - private Version version; - - @JsonIgnore - private Collection playerList = new ArrayList<>(); public GeyserPingInfo() { + // for json mapping } - public GeyserPingInfo(String description, Players players, Version version) { + public GeyserPingInfo(@Nullable String description, Players players) { this.description = description; this.players = players; - this.version = version; + } + + public GeyserPingInfo(@Nullable String description, int maxPlayers, int onlinePlayers) { + this.description = description; + this.players = new Players(maxPlayers, onlinePlayers); } @JsonSetter("description") @@ -68,6 +71,7 @@ public class GeyserPingInfo { private int online; public Players() { + // for json mapping } public Players(int max, int online) { @@ -75,19 +79,4 @@ public class GeyserPingInfo { this.online = online; } } - - @Data - public static class Version { - - private String name; - private int protocol; - - public Version() { - } - - public Version(String name, int protocol) { - this.name = name; - this.protocol = protocol; - } - } } diff --git a/core/src/main/java/org/geysermc/geyser/ping/IGeyserPingPassthrough.java b/core/src/main/java/org/geysermc/geyser/ping/IGeyserPingPassthrough.java index d414b7fa8..b6095cce2 100644 --- a/core/src/main/java/org/geysermc/geyser/ping/IGeyserPingPassthrough.java +++ b/core/src/main/java/org/geysermc/geyser/ping/IGeyserPingPassthrough.java @@ -26,7 +26,6 @@ package org.geysermc.geyser.ping; import javax.annotation.Nullable; -import java.net.Inet4Address; import java.net.InetSocketAddress; /** @@ -34,16 +33,6 @@ import java.net.InetSocketAddress; */ public interface IGeyserPingPassthrough { - /** - * Get the MOTD of the server displayed on the multiplayer screen. It uses a fake remote, as the remote isn't important in this context. - * - * @return string of the MOTD - */ - @Nullable - default GeyserPingInfo getPingInformation() { - return this.getPingInformation(new InetSocketAddress(Inet4Address.getLoopbackAddress(), 69)); - } - /** * Get the MOTD of the server displayed on the multiplayer screen * diff --git a/core/src/main/resources/config.yml b/core/src/main/resources/config.yml index 8e4db5e38..218e13833 100644 --- a/core/src/main/resources/config.yml +++ b/core/src/main/resources/config.yml @@ -91,9 +91,6 @@ command-suggestions: true # The following three options enable "ping passthrough" - the MOTD, player count and/or protocol name gets retrieved from the Java server. # Relay the MOTD from the remote server to Bedrock players. passthrough-motd: false -# Relay the protocol name (e.g. BungeeCord [X.X], Paper 1.X) - only really useful when using a custom protocol name! -# This will also show up on sites like MCSrvStatus. -passthrough-protocol-name: false # Relay the player count and max players from the remote server to Bedrock players. passthrough-player-counts: false # Enable LEGACY ping passthrough. There is no need to enable this unless your MOTD or player count does not appear properly. From 118e7699767e07f24304155843ede2d0cfc79dd5 Mon Sep 17 00:00:00 2001 From: chris Date: Tue, 14 Nov 2023 00:33:34 +0100 Subject: [PATCH 124/344] Fix issues with empty MOTDs - fallback to configured MOTD (#4259) * Fix issues with empty MOTDs - fallback to configured MOTD --------- Co-authored-by: Konicai <71294714+Konicai@users.noreply.github.com> --- .../java/org/geysermc/geyser/network/netty/GeyserServer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java b/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java index a811d8437..20340826f 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java @@ -249,8 +249,8 @@ public final class GeyserServer { if (config.isPassthroughMotd() && pingInfo != null && pingInfo.getDescription() != null) { String[] motd = MessageTranslator.convertMessageLenient(pingInfo.getDescription()).split("\n"); - String mainMotd = motd[0]; // First line of the motd. - String subMotd = (motd.length != 1) ? motd[1] : GeyserImpl.NAME; // Second line of the motd if present, otherwise default. + String mainMotd = (motd.length > 0) ? motd[0] : config.getBedrock().primaryMotd(); // First line of the motd. + String subMotd = (motd.length > 1) ? motd[1] : config.getBedrock().secondaryMotd(); // Second line of the motd if present, otherwise default. pong.motd(mainMotd.trim()); pong.subMotd(subMotd.trim()); // Trimmed to shift it to the left, prevents the universe from collapsing on us just because we went 2 characters over the text box's limit. From dec0d13d8e2e29fb62bb470fdf5ca8e753618e94 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Fri, 17 Nov 2023 11:59:40 +0000 Subject: [PATCH 125/344] Delete Jenkinsfile (#4181) --- Jenkinsfile | 28 ---------------------------- 1 file changed, 28 deletions(-) delete mode 100644 Jenkinsfile diff --git a/Jenkinsfile b/Jenkinsfile deleted file mode 100644 index fceed8498..000000000 --- a/Jenkinsfile +++ /dev/null @@ -1,28 +0,0 @@ -pipeline { - agent any - tools { - gradle 'Gradle 7' - jdk 'Java 17' - } - options { - buildDiscarder(logRotator(artifactNumToKeepStr: '20')) - } - stages { - stage ('Build') { - steps { - sh 'git submodule update --init --recursive' - rtGradleRun( - usesPlugin: true, - tool: 'Gradle 7', - buildFile: 'build.gradle.kts', - tasks: 'clean build', - ) - } - post { - success { - archiveArtifacts artifacts: 'bootstrap/**/build/libs/Geyser-*.jar', fingerprint: true - } - } - } - } -} From 44174fdc0482e6d28dedd92db38785a41213c13a Mon Sep 17 00:00:00 2001 From: chris Date: Tue, 21 Nov 2023 23:31:56 +0100 Subject: [PATCH 126/344] Add 1.20.50 Bedrock support (#4296) * Start on 1.20.50 * Add 1.20.50 block_palette.1_20_50.nbt, creative_items.1_20_50.json and runtime_item_states.1_20_50.json * fix stone and planks mappings * add and do something with the new SetPlayerInventoryOptionsPacket * Add readme version bump * Cleanup/Explain the new BedrockSetPlayerInventoryOptionsTranslator --- README.md | 2 +- .../geysermc/geyser/network/GameProtocol.java | 6 +- .../geyser/network/LoggingPacketHandler.java | 22 +- .../populator/BlockRegistryPopulator.java | 9 +- .../populator/ItemRegistryPopulator.java | 15 + ...ckSetPlayerInventoryOptionsTranslator.java | 63 + .../bedrock/block_palette.1_20_50.nbt | Bin 0 -> 170466 bytes .../bedrock/creative_items.1_20_50.json | 5787 ++++++++++++++++ .../bedrock/runtime_item_states.1_20_50.json | 5846 +++++++++++++++++ gradle/libs.versions.toml | 6 +- 10 files changed, 11734 insertions(+), 22 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetPlayerInventoryOptionsTranslator.java create mode 100644 core/src/main/resources/bedrock/block_palette.1_20_50.nbt create mode 100644 core/src/main/resources/bedrock/creative_items.1_20_50.json create mode 100644 core/src/main/resources/bedrock/runtime_item_states.1_20_50.json diff --git a/README.md b/README.md index 07fb34209..b878db64d 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,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.20.0 - 1.20.40 and Minecraft Java 1.20.2 +### Currently supporting Minecraft Bedrock 1.20.0 - 1.20.50 and Minecraft Java 1.20.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/GameProtocol.java b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java index 5555375cd..4ffdbcf48 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java @@ -32,6 +32,7 @@ import org.cloudburstmc.protocol.bedrock.codec.v589.Bedrock_v589; import org.cloudburstmc.protocol.bedrock.codec.v594.Bedrock_v594; import org.cloudburstmc.protocol.bedrock.codec.v618.Bedrock_v618; import org.cloudburstmc.protocol.bedrock.codec.v622.Bedrock_v622; +import org.cloudburstmc.protocol.bedrock.codec.v630.Bedrock_v630; import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec; import org.geysermc.geyser.session.GeyserSession; @@ -47,7 +48,7 @@ public final class GameProtocol { * Default Bedrock codec that should act as a fallback. Should represent the latest available * release of the game that Geyser supports. */ - public static final BedrockCodec DEFAULT_BEDROCK_CODEC = Bedrock_v622.CODEC; + public static final BedrockCodec DEFAULT_BEDROCK_CODEC = Bedrock_v630.CODEC; /** * A list of all supported Bedrock versions that can join Geyser @@ -70,6 +71,9 @@ public final class GameProtocol { SUPPORTED_BEDROCK_CODECS.add(Bedrock_v618.CODEC.toBuilder() .minecraftVersion("1.20.30/1.20.32") .build()); + SUPPORTED_BEDROCK_CODECS.add(Bedrock_v622.CODEC.toBuilder() + .minecraftVersion("1.20.40/1.20.41") + .build()); SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC); } diff --git a/core/src/main/java/org/geysermc/geyser/network/LoggingPacketHandler.java b/core/src/main/java/org/geysermc/geyser/network/LoggingPacketHandler.java index 61c8dbe3d..ec1bef1df 100644 --- a/core/src/main/java/org/geysermc/geyser/network/LoggingPacketHandler.java +++ b/core/src/main/java/org/geysermc/geyser/network/LoggingPacketHandler.java @@ -32,7 +32,7 @@ import org.geysermc.geyser.session.GeyserSession; /** * Bare bones implementation of BedrockPacketHandler suitable for extension. - * + *

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 diff --git a/core/src/main/resources/bedrock/creative_items.1_19_80.json b/core/src/main/resources/bedrock/creative_items.1_19_80.json deleted file mode 100644 index 0cfc591f8..000000000 --- a/core/src/main/resources/bedrock/creative_items.1_19_80.json +++ /dev/null @@ -1,6183 +0,0 @@ -{ - "items": [ - { - "id": "minecraft:planks", - "blockRuntimeId": 10437 - }, - { - "id": "minecraft:planks", - "blockRuntimeId": 10438 - }, - { - "id": "minecraft:planks", - "blockRuntimeId": 10439 - }, - { - "id": "minecraft:planks", - "blockRuntimeId": 10440 - }, - { - "id": "minecraft:planks", - "blockRuntimeId": 10441 - }, - { - "id": "minecraft:planks", - "blockRuntimeId": 10442 - }, - { - "id": "minecraft:mangrove_planks", - "blockRuntimeId": 2067 - }, - { - "id": "minecraft:crimson_planks", - "blockRuntimeId": 7984 - }, - { - "id": "minecraft:warped_planks", - "blockRuntimeId": 2039 - }, - { - "id": "minecraft:cobblestone_wall", - "blockRuntimeId": 2311 - }, - { - "id": "minecraft:cobblestone_wall", - "blockRuntimeId": 2312 - }, - { - "id": "minecraft:cobblestone_wall", - "blockRuntimeId": 2313 - }, - { - "id": "minecraft:cobblestone_wall", - "blockRuntimeId": 2314 - }, - { - "id": "minecraft:cobblestone_wall", - "blockRuntimeId": 2315 - }, - { - "id": "minecraft:cobblestone_wall", - "blockRuntimeId": 2316 - }, - { - "id": "minecraft:cobblestone_wall", - "blockRuntimeId": 2323 - }, - { - "id": "minecraft:cobblestone_wall", - "blockRuntimeId": 2318 - }, - { - "id": "minecraft:cobblestone_wall", - "blockRuntimeId": 2319 - }, - { - "id": "minecraft:cobblestone_wall", - "blockRuntimeId": 2317 - }, - { - "id": "minecraft:cobblestone_wall", - "blockRuntimeId": 2320 - }, - { - "id": "minecraft:cobblestone_wall", - "blockRuntimeId": 2324 - }, - { - "id": "minecraft:cobblestone_wall", - "blockRuntimeId": 2321 - }, - { - "id": "minecraft:cobblestone_wall", - "blockRuntimeId": 2322 - }, - { - "id": "minecraft:blackstone_wall", - "blockRuntimeId": 6199 - }, - { - "id": "minecraft:polished_blackstone_wall", - "blockRuntimeId": 11122 - }, - { - "id": "minecraft:polished_blackstone_brick_wall", - "blockRuntimeId": 2092 - }, - { - "id": "minecraft:cobbled_deepslate_wall", - "blockRuntimeId": 12911 - }, - { - "id": "minecraft:deepslate_tile_wall", - "blockRuntimeId": 8224 - }, - { - "id": "minecraft:polished_deepslate_wall", - "blockRuntimeId": 12643 - }, - { - "id": "minecraft:deepslate_brick_wall", - "blockRuntimeId": 1135 - }, - { - "id": "minecraft:mud_brick_wall", - "blockRuntimeId": 1833 - }, - { - "id": "minecraft:oak_fence", - "blockRuntimeId": 8922 - }, - { - "id": "minecraft:spruce_fence", - "blockRuntimeId": 1097 - }, - { - "id": "minecraft:birch_fence", - "blockRuntimeId": 12906 - }, - { - "id": "minecraft:jungle_fence", - "blockRuntimeId": 1090 - }, - { - "id": "minecraft:acacia_fence", - "blockRuntimeId": 12909 - }, - { - "id": "minecraft:dark_oak_fence", - "blockRuntimeId": 11488 - }, - { - "id": "minecraft:mangrove_fence", - "blockRuntimeId": 11039 - }, - { - "id": "minecraft:nether_brick_fence", - "blockRuntimeId": 6566 - }, - { - "id": "minecraft:crimson_fence", - "blockRuntimeId": 12822 - }, - { - "id": "minecraft:warped_fence", - "blockRuntimeId": 9423 - }, - { - "id": "minecraft:fence_gate", - "blockRuntimeId": 79 - }, - { - "id": "minecraft:spruce_fence_gate", - "blockRuntimeId": 10990 - }, - { - "id": "minecraft:birch_fence_gate", - "blockRuntimeId": 5668 - }, - { - "id": "minecraft:jungle_fence_gate", - "blockRuntimeId": 8535 - }, - { - "id": "minecraft:acacia_fence_gate", - "blockRuntimeId": 12405 - }, - { - "id": "minecraft:dark_oak_fence_gate", - "blockRuntimeId": 6442 - }, - { - "id": "minecraft:mangrove_fence_gate", - "blockRuntimeId": 6951 - }, - { - "id": "minecraft:crimson_fence_gate", - "blockRuntimeId": 7403 - }, - { - "id": "minecraft:warped_fence_gate", - "blockRuntimeId": 8570 - }, - { - "id": "minecraft:normal_stone_stairs", - "blockRuntimeId": 1340 - }, - { - "id": "minecraft:stone_stairs", - "blockRuntimeId": 5597 - }, - { - "id": "minecraft:mossy_cobblestone_stairs", - "blockRuntimeId": 6361 - }, - { - "id": "minecraft:oak_stairs", - "blockRuntimeId": 683 - }, - { - "id": "minecraft:spruce_stairs", - "blockRuntimeId": 132 - }, - { - "id": "minecraft:birch_stairs", - "blockRuntimeId": 11407 - }, - { - "id": "minecraft:jungle_stairs", - "blockRuntimeId": 11371 - }, - { - "id": "minecraft:acacia_stairs", - "blockRuntimeId": 10582 - }, - { - "id": "minecraft:dark_oak_stairs", - "blockRuntimeId": 8216 - }, - { - "id": "minecraft:mangrove_stairs", - "blockRuntimeId": 6909 - }, - { - "id": "minecraft:stone_brick_stairs", - "blockRuntimeId": 2050 - }, - { - "id": "minecraft:mossy_stone_brick_stairs", - "blockRuntimeId": 9853 - }, - { - "id": "minecraft:sandstone_stairs", - "blockRuntimeId": 5473 - }, - { - "id": "minecraft:smooth_sandstone_stairs", - "blockRuntimeId": 5516 - }, - { - "id": "minecraft:red_sandstone_stairs", - "blockRuntimeId": 8520 - }, - { - "id": "minecraft:smooth_red_sandstone_stairs", - "blockRuntimeId": 8718 - }, - { - "id": "minecraft:granite_stairs", - "blockRuntimeId": 5039 - }, - { - "id": "minecraft:polished_granite_stairs", - "blockRuntimeId": 6419 - }, - { - "id": "minecraft:diorite_stairs", - "blockRuntimeId": 6702 - }, - { - "id": "minecraft:polished_diorite_stairs", - "blockRuntimeId": 11108 - }, - { - "id": "minecraft:andesite_stairs", - "blockRuntimeId": 8477 - }, - { - "id": "minecraft:polished_andesite_stairs", - "blockRuntimeId": 11432 - }, - { - "id": "minecraft:brick_stairs", - "blockRuntimeId": 10936 - }, - { - "id": "minecraft:nether_brick_stairs", - "blockRuntimeId": 109 - }, - { - "id": "minecraft:red_nether_brick_stairs", - "blockRuntimeId": 11008 - }, - { - "id": "minecraft:end_brick_stairs", - "blockRuntimeId": 10774 - }, - { - "id": "minecraft:quartz_stairs", - "blockRuntimeId": 7517 - }, - { - "id": "minecraft:smooth_quartz_stairs", - "blockRuntimeId": 12519 - }, - { - "id": "minecraft:purpur_stairs", - "blockRuntimeId": 12581 - }, - { - "id": "minecraft:prismarine_stairs", - "blockRuntimeId": 12088 - }, - { - "id": "minecraft:dark_prismarine_stairs", - "blockRuntimeId": 12249 - }, - { - "id": "minecraft:prismarine_bricks_stairs", - "blockRuntimeId": 611 - }, - { - "id": "minecraft:crimson_stairs", - "blockRuntimeId": 10672 - }, - { - "id": "minecraft:warped_stairs", - "blockRuntimeId": 5607 - }, - { - "id": "minecraft:blackstone_stairs", - "blockRuntimeId": 11423 - }, - { - "id": "minecraft:polished_blackstone_stairs", - "blockRuntimeId": 6605 - }, - { - "id": "minecraft:polished_blackstone_brick_stairs", - "blockRuntimeId": 6791 - }, - { - "id": "minecraft:cut_copper_stairs", - "blockRuntimeId": 6918 - }, - { - "id": "minecraft:exposed_cut_copper_stairs", - "blockRuntimeId": 6901 - }, - { - "id": "minecraft:weathered_cut_copper_stairs", - "blockRuntimeId": 6613 - }, - { - "id": "minecraft:oxidized_cut_copper_stairs", - "blockRuntimeId": 1054 - }, - { - "id": "minecraft:waxed_cut_copper_stairs", - "blockRuntimeId": 1099 - }, - { - "id": "minecraft:waxed_exposed_cut_copper_stairs", - "blockRuntimeId": 6171 - }, - { - "id": "minecraft:waxed_weathered_cut_copper_stairs", - "blockRuntimeId": 10549 - }, - { - "id": "minecraft:waxed_oxidized_cut_copper_stairs", - "blockRuntimeId": 9402 - }, - { - "id": "minecraft:cobbled_deepslate_stairs", - "blockRuntimeId": 552 - }, - { - "id": "minecraft:deepslate_tile_stairs", - "blockRuntimeId": 7395 - }, - { - "id": "minecraft:polished_deepslate_stairs", - "blockRuntimeId": 995 - }, - { - "id": "minecraft:deepslate_brick_stairs", - "blockRuntimeId": 12241 - }, - { - "id": "minecraft:mud_brick_stairs", - "blockRuntimeId": 8694 - }, - { - "id": "minecraft:wooden_door", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:spruce_door", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:birch_door", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:jungle_door", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:acacia_door", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:dark_oak_door", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:mangrove_door", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:iron_door", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:crimson_door", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:warped_door", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:trapdoor", - "blockRuntimeId": 638 - }, - { - "id": "minecraft:spruce_trapdoor", - "blockRuntimeId": 10958 - }, - { - "id": "minecraft:birch_trapdoor", - "blockRuntimeId": 11056 - }, - { - "id": "minecraft:jungle_trapdoor", - "blockRuntimeId": 8551 - }, - { - "id": "minecraft:acacia_trapdoor", - "blockRuntimeId": 8761 - }, - { - "id": "minecraft:dark_oak_trapdoor", - "blockRuntimeId": 12321 - }, - { - "id": "minecraft:mangrove_trapdoor", - "blockRuntimeId": 6799 - }, - { - "id": "minecraft:iron_trapdoor", - "blockRuntimeId": 1022 - }, - { - "id": "minecraft:crimson_trapdoor", - "blockRuntimeId": 6644 - }, - { - "id": "minecraft:warped_trapdoor", - "blockRuntimeId": 7483 - }, - { - "id": "minecraft:iron_bars", - "blockRuntimeId": 7551 - }, - { - "id": "minecraft:glass", - "blockRuntimeId": 10546 - }, - { - "id": "minecraft:stained_glass", - "blockRuntimeId": 2254 - }, - { - "id": "minecraft:stained_glass", - "blockRuntimeId": 2262 - }, - { - "id": "minecraft:stained_glass", - "blockRuntimeId": 2261 - }, - { - "id": "minecraft:stained_glass", - "blockRuntimeId": 2269 - }, - { - "id": "minecraft:stained_glass", - "blockRuntimeId": 2266 - }, - { - "id": "minecraft:stained_glass", - "blockRuntimeId": 2268 - }, - { - "id": "minecraft:stained_glass", - "blockRuntimeId": 2255 - }, - { - "id": "minecraft:stained_glass", - "blockRuntimeId": 2258 - }, - { - "id": "minecraft:stained_glass", - "blockRuntimeId": 2259 - }, - { - "id": "minecraft:stained_glass", - "blockRuntimeId": 2267 - }, - { - "id": "minecraft:stained_glass", - "blockRuntimeId": 2263 - }, - { - "id": "minecraft:stained_glass", - "blockRuntimeId": 2257 - }, - { - "id": "minecraft:stained_glass", - "blockRuntimeId": 2265 - }, - { - "id": "minecraft:stained_glass", - "blockRuntimeId": 2264 - }, - { - "id": "minecraft:stained_glass", - "blockRuntimeId": 2256 - }, - { - "id": "minecraft:stained_glass", - "blockRuntimeId": 2260 - }, - { - "id": "minecraft:tinted_glass", - "blockRuntimeId": 9945 - }, - { - "id": "minecraft:glass_pane", - "blockRuntimeId": 8386 - }, - { - "id": "minecraft:stained_glass_pane", - "blockRuntimeId": 7986 - }, - { - "id": "minecraft:stained_glass_pane", - "blockRuntimeId": 7994 - }, - { - "id": "minecraft:stained_glass_pane", - "blockRuntimeId": 7993 - }, - { - "id": "minecraft:stained_glass_pane", - "blockRuntimeId": 8001 - }, - { - "id": "minecraft:stained_glass_pane", - "blockRuntimeId": 7998 - }, - { - "id": "minecraft:stained_glass_pane", - "blockRuntimeId": 8000 - }, - { - "id": "minecraft:stained_glass_pane", - "blockRuntimeId": 7987 - }, - { - "id": "minecraft:stained_glass_pane", - "blockRuntimeId": 7990 - }, - { - "id": "minecraft:stained_glass_pane", - "blockRuntimeId": 7991 - }, - { - "id": "minecraft:stained_glass_pane", - "blockRuntimeId": 7999 - }, - { - "id": "minecraft:stained_glass_pane", - "blockRuntimeId": 7995 - }, - { - "id": "minecraft:stained_glass_pane", - "blockRuntimeId": 7989 - }, - { - "id": "minecraft:stained_glass_pane", - "blockRuntimeId": 7997 - }, - { - "id": "minecraft:stained_glass_pane", - "blockRuntimeId": 7996 - }, - { - "id": "minecraft:stained_glass_pane", - "blockRuntimeId": 7988 - }, - { - "id": "minecraft:stained_glass_pane", - "blockRuntimeId": 7992 - }, - { - "id": "minecraft:ladder", - "blockRuntimeId": 13109 - }, - { - "id": "minecraft:scaffolding", - "blockRuntimeId": 5457 - }, - { - "id": "minecraft:stone_block_slab", - "blockRuntimeId": 6544 - }, - { - "id": "minecraft:stone_block_slab4", - "blockRuntimeId": 8996 - }, - { - "id": "minecraft:stone_block_slab", - "blockRuntimeId": 6547 - }, - { - "id": "minecraft:stone_block_slab2", - "blockRuntimeId": 8967 - }, - { - "id": "minecraft:wooden_slab", - "blockRuntimeId": 8439 - }, - { - "id": "minecraft:wooden_slab", - "blockRuntimeId": 8440 - }, - { - "id": "minecraft:wooden_slab", - "blockRuntimeId": 8441 - }, - { - "id": "minecraft:wooden_slab", - "blockRuntimeId": 8442 - }, - { - "id": "minecraft:wooden_slab", - "blockRuntimeId": 8443 - }, - { - "id": "minecraft:wooden_slab", - "blockRuntimeId": 8444 - }, - { - "id": "minecraft:mangrove_slab", - "blockRuntimeId": 2270 - }, - { - "id": "minecraft:stone_block_slab", - "blockRuntimeId": 6549 - }, - { - "id": "minecraft:stone_block_slab4", - "blockRuntimeId": 8994 - }, - { - "id": "minecraft:stone_block_slab", - "blockRuntimeId": 6545 - }, - { - "id": "minecraft:stone_block_slab4", - "blockRuntimeId": 8997 - }, - { - "id": "minecraft:stone_block_slab2", - "blockRuntimeId": 8968 - }, - { - "id": "minecraft:stone_block_slab2", - "blockRuntimeId": 8962 - }, - { - "id": "minecraft:stone_block_slab4", - "blockRuntimeId": 8998 - }, - { - "id": "minecraft:stone_block_slab3", - "blockRuntimeId": 8979 - }, - { - "id": "minecraft:stone_block_slab3", - "blockRuntimeId": 8984 - }, - { - "id": "minecraft:stone_block_slab3", - "blockRuntimeId": 8985 - }, - { - "id": "minecraft:stone_block_slab3", - "blockRuntimeId": 8982 - }, - { - "id": "minecraft:stone_block_slab3", - "blockRuntimeId": 8983 - }, - { - "id": "minecraft:stone_block_slab3", - "blockRuntimeId": 8981 - }, - { - "id": "minecraft:stone_block_slab3", - "blockRuntimeId": 8980 - }, - { - "id": "minecraft:stone_block_slab", - "blockRuntimeId": 6548 - }, - { - "id": "minecraft:stone_block_slab", - "blockRuntimeId": 6551 - }, - { - "id": "minecraft:stone_block_slab2", - "blockRuntimeId": 8969 - }, - { - "id": "minecraft:stone_block_slab3", - "blockRuntimeId": 8978 - }, - { - "id": "minecraft:stone_block_slab", - "blockRuntimeId": 6550 - }, - { - "id": "minecraft:stone_block_slab4", - "blockRuntimeId": 8995 - }, - { - "id": "minecraft:stone_block_slab2", - "blockRuntimeId": 8963 - }, - { - "id": "minecraft:stone_block_slab2", - "blockRuntimeId": 8964 - }, - { - "id": "minecraft:stone_block_slab2", - "blockRuntimeId": 8965 - }, - { - "id": "minecraft:stone_block_slab2", - "blockRuntimeId": 8966 - }, - { - "id": "minecraft:crimson_slab", - "blockRuntimeId": 9870 - }, - { - "id": "minecraft:warped_slab", - "blockRuntimeId": 10888 - }, - { - "id": "minecraft:blackstone_slab", - "blockRuntimeId": 2029 - }, - { - "id": "minecraft:polished_blackstone_slab", - "blockRuntimeId": 10373 - }, - { - "id": "minecraft:polished_blackstone_brick_slab", - "blockRuntimeId": 6463 - }, - { - "id": "minecraft:cut_copper_slab", - "blockRuntimeId": 8388 - }, - { - "id": "minecraft:exposed_cut_copper_slab", - "blockRuntimeId": 11006 - }, - { - "id": "minecraft:weathered_cut_copper_slab", - "blockRuntimeId": 10418 - }, - { - "id": "minecraft:oxidized_cut_copper_slab", - "blockRuntimeId": 8451 - }, - { - "id": "minecraft:waxed_cut_copper_slab", - "blockRuntimeId": 12641 - }, - { - "id": "minecraft:waxed_exposed_cut_copper_slab", - "blockRuntimeId": 658 - }, - { - "id": "minecraft:waxed_weathered_cut_copper_slab", - "blockRuntimeId": 10951 - }, - { - "id": "minecraft:waxed_oxidized_cut_copper_slab", - "blockRuntimeId": 1803 - }, - { - "id": "minecraft:cobbled_deepslate_slab", - "blockRuntimeId": 12135 - }, - { - "id": "minecraft:polished_deepslate_slab", - "blockRuntimeId": 701 - }, - { - "id": "minecraft:deepslate_tile_slab", - "blockRuntimeId": 6567 - }, - { - "id": "minecraft:deepslate_brick_slab", - "blockRuntimeId": 5605 - }, - { - "id": "minecraft:mud_brick_slab", - "blockRuntimeId": 6179 - }, - { - "id": "minecraft:brick_block", - "blockRuntimeId": 7515 - }, - { - "id": "minecraft:chiseled_nether_bricks", - "blockRuntimeId": 12069 - }, - { - "id": "minecraft:cracked_nether_bricks", - "blockRuntimeId": 6866 - }, - { - "id": "minecraft:quartz_bricks", - "blockRuntimeId": 10743 - }, - { - "id": "minecraft:stonebrick", - "blockRuntimeId": 10953 - }, - { - "id": "minecraft:stonebrick", - "blockRuntimeId": 10954 - }, - { - "id": "minecraft:stonebrick", - "blockRuntimeId": 10955 - }, - { - "id": "minecraft:stonebrick", - "blockRuntimeId": 10956 - }, - { - "id": "minecraft:end_bricks", - "blockRuntimeId": 694 - }, - { - "id": "minecraft:prismarine", - "blockRuntimeId": 10469 - }, - { - "id": "minecraft:polished_blackstone_bricks", - "blockRuntimeId": 7422 - }, - { - "id": "minecraft:cracked_polished_blackstone_bricks", - "blockRuntimeId": 12018 - }, - { - "id": "minecraft:gilded_blackstone", - "blockRuntimeId": 6900 - }, - { - "id": "minecraft:chiseled_polished_blackstone", - "blockRuntimeId": 8215 - }, - { - "id": "minecraft:deepslate_tiles", - "blockRuntimeId": 6895 - }, - { - "id": "minecraft:cracked_deepslate_tiles", - "blockRuntimeId": 6429 - }, - { - "id": "minecraft:deepslate_bricks", - "blockRuntimeId": 8635 - }, - { - "id": "minecraft:cracked_deepslate_bricks", - "blockRuntimeId": 8534 - }, - { - "id": "minecraft:chiseled_deepslate", - "blockRuntimeId": 8387 - }, - { - "id": "minecraft:cobblestone", - "blockRuntimeId": 5504 - }, - { - "id": "minecraft:mossy_cobblestone", - "blockRuntimeId": 661 - }, - { - "id": "minecraft:cobbled_deepslate", - "blockRuntimeId": 11076 - }, - { - "id": "minecraft:smooth_stone", - "blockRuntimeId": 6896 - }, - { - "id": "minecraft:sandstone", - "blockRuntimeId": 5542 - }, - { - "id": "minecraft:sandstone", - "blockRuntimeId": 5543 - }, - { - "id": "minecraft:sandstone", - "blockRuntimeId": 5544 - }, - { - "id": "minecraft:sandstone", - "blockRuntimeId": 5545 - }, - { - "id": "minecraft:red_sandstone", - "blockRuntimeId": 10986 - }, - { - "id": "minecraft:red_sandstone", - "blockRuntimeId": 10987 - }, - { - "id": "minecraft:red_sandstone", - "blockRuntimeId": 10988 - }, - { - "id": "minecraft:red_sandstone", - "blockRuntimeId": 10989 - }, - { - "id": "minecraft:coal_block", - "blockRuntimeId": 8568 - }, - { - "id": "minecraft:dried_kelp_block", - "blockRuntimeId": 12805 - }, - { - "id": "minecraft:gold_block", - "blockRuntimeId": 736 - }, - { - "id": "minecraft:iron_block", - "blockRuntimeId": 13108 - }, - { - "id": "minecraft:copper_block", - "blockRuntimeId": 7393 - }, - { - "id": "minecraft:exposed_copper", - "blockRuntimeId": 1299 - }, - { - "id": "minecraft:weathered_copper", - "blockRuntimeId": 13075 - }, - { - "id": "minecraft:oxidized_copper", - "blockRuntimeId": 5439 - }, - { - "id": "minecraft:waxed_copper", - "blockRuntimeId": 12559 - }, - { - "id": "minecraft:waxed_exposed_copper", - "blockRuntimeId": 1789 - }, - { - "id": "minecraft:waxed_weathered_copper", - "blockRuntimeId": 1802 - }, - { - "id": "minecraft:waxed_oxidized_copper", - "blockRuntimeId": 12361 - }, - { - "id": "minecraft:cut_copper", - "blockRuntimeId": 7431 - }, - { - "id": "minecraft:exposed_cut_copper", - "blockRuntimeId": 10548 - }, - { - "id": "minecraft:weathered_cut_copper", - "blockRuntimeId": 12001 - }, - { - "id": "minecraft:oxidized_cut_copper", - "blockRuntimeId": 8649 - }, - { - "id": "minecraft:waxed_cut_copper", - "blockRuntimeId": 12118 - }, - { - "id": "minecraft:waxed_exposed_cut_copper", - "blockRuntimeId": 5700 - }, - { - "id": "minecraft:waxed_weathered_cut_copper", - "blockRuntimeId": 7985 - }, - { - "id": "minecraft:waxed_oxidized_cut_copper", - "blockRuntimeId": 619 - }, - { - "id": "minecraft:emerald_block", - "blockRuntimeId": 2280 - }, - { - "id": "minecraft:diamond_block", - "blockRuntimeId": 682 - }, - { - "id": "minecraft:lapis_block", - "blockRuntimeId": 6560 - }, - { - "id": "minecraft:raw_iron_block", - "blockRuntimeId": 13106 - }, - { - "id": "minecraft:raw_copper_block", - "blockRuntimeId": 8438 - }, - { - "id": "minecraft:raw_gold_block", - "blockRuntimeId": 1064 - }, - { - "id": "minecraft:quartz_block", - "blockRuntimeId": 5585 - }, - { - "id": "minecraft:quartz_block", - "blockRuntimeId": 5587 - }, - { - "id": "minecraft:quartz_block", - "blockRuntimeId": 5586 - }, - { - "id": "minecraft:quartz_block", - "blockRuntimeId": 5588 - }, - { - "id": "minecraft:prismarine", - "blockRuntimeId": 10467 - }, - { - "id": "minecraft:prismarine", - "blockRuntimeId": 10468 - }, - { - "id": "minecraft:slime", - "blockRuntimeId": 6504 - }, - { - "id": "minecraft:honey_block", - "blockRuntimeId": 1995 - }, - { - "id": "minecraft:honeycomb_block", - "blockRuntimeId": 6790 - }, - { - "id": "minecraft:hay_block", - "blockRuntimeId": 1790 - }, - { - "id": "minecraft:bone_block", - "blockRuntimeId": 6505 - }, - { - "id": "minecraft:nether_brick", - "blockRuntimeId": 12097 - }, - { - "id": "minecraft:red_nether_brick", - "blockRuntimeId": 551 - }, - { - "id": "minecraft:netherite_block", - "blockRuntimeId": 5665 - }, - { - "id": "minecraft:lodestone", - "blockRuntimeId": 13104 - }, - { - "id": "minecraft:white_wool", - "blockRuntimeId": 8569 - }, - { - "id": "minecraft:light_gray_wool", - "blockRuntimeId": 12881 - }, - { - "id": "minecraft:gray_wool", - "blockRuntimeId": 631 - }, - { - "id": "minecraft:black_wool", - "blockRuntimeId": 1065 - }, - { - "id": "minecraft:brown_wool", - "blockRuntimeId": 665 - }, - { - "id": "minecraft:red_wool", - "blockRuntimeId": 119 - }, - { - "id": "minecraft:orange_wool", - "blockRuntimeId": 1771 - }, - { - "id": "minecraft:yellow_wool", - "blockRuntimeId": 542 - }, - { - "id": "minecraft:lime_wool", - "blockRuntimeId": 10362 - }, - { - "id": "minecraft:green_wool", - "blockRuntimeId": 5616 - }, - { - "id": "minecraft:cyan_wool", - "blockRuntimeId": 8513 - }, - { - "id": "minecraft:light_blue_wool", - "blockRuntimeId": 11486 - }, - { - "id": "minecraft:blue_wool", - "blockRuntimeId": 8650 - }, - { - "id": "minecraft:purple_wool", - "blockRuntimeId": 13107 - }, - { - "id": "minecraft:magenta_wool", - "blockRuntimeId": 2085 - }, - { - "id": "minecraft:pink_wool", - "blockRuntimeId": 5666 - }, - { - "id": "minecraft:carpet", - "blockRuntimeId": 2069 - }, - { - "id": "minecraft:carpet", - "blockRuntimeId": 2077 - }, - { - "id": "minecraft:carpet", - "blockRuntimeId": 2076 - }, - { - "id": "minecraft:carpet", - "blockRuntimeId": 2084 - }, - { - "id": "minecraft:carpet", - "blockRuntimeId": 2081 - }, - { - "id": "minecraft:carpet", - "blockRuntimeId": 2083 - }, - { - "id": "minecraft:carpet", - "blockRuntimeId": 2070 - }, - { - "id": "minecraft:carpet", - "blockRuntimeId": 2073 - }, - { - "id": "minecraft:carpet", - "blockRuntimeId": 2074 - }, - { - "id": "minecraft:carpet", - "blockRuntimeId": 2082 - }, - { - "id": "minecraft:carpet", - "blockRuntimeId": 2078 - }, - { - "id": "minecraft:carpet", - "blockRuntimeId": 2072 - }, - { - "id": "minecraft:carpet", - "blockRuntimeId": 2080 - }, - { - "id": "minecraft:carpet", - "blockRuntimeId": 2079 - }, - { - "id": "minecraft:carpet", - "blockRuntimeId": 2071 - }, - { - "id": "minecraft:carpet", - "blockRuntimeId": 2075 - }, - { - "id": "minecraft:concrete_powder", - "blockRuntimeId": 10656 - }, - { - "id": "minecraft:concrete_powder", - "blockRuntimeId": 10664 - }, - { - "id": "minecraft:concrete_powder", - "blockRuntimeId": 10663 - }, - { - "id": "minecraft:concrete_powder", - "blockRuntimeId": 10671 - }, - { - "id": "minecraft:concrete_powder", - "blockRuntimeId": 10668 - }, - { - "id": "minecraft:concrete_powder", - "blockRuntimeId": 10670 - }, - { - "id": "minecraft:concrete_powder", - "blockRuntimeId": 10657 - }, - { - "id": "minecraft:concrete_powder", - "blockRuntimeId": 10660 - }, - { - "id": "minecraft:concrete_powder", - "blockRuntimeId": 10661 - }, - { - "id": "minecraft:concrete_powder", - "blockRuntimeId": 10669 - }, - { - "id": "minecraft:concrete_powder", - "blockRuntimeId": 10665 - }, - { - "id": "minecraft:concrete_powder", - "blockRuntimeId": 10659 - }, - { - "id": "minecraft:concrete_powder", - "blockRuntimeId": 10667 - }, - { - "id": "minecraft:concrete_powder", - "blockRuntimeId": 10666 - }, - { - "id": "minecraft:concrete_powder", - "blockRuntimeId": 10658 - }, - { - "id": "minecraft:concrete_powder", - "blockRuntimeId": 10662 - }, - { - "id": "minecraft:concrete", - "blockRuntimeId": 1751 - }, - { - "id": "minecraft:concrete", - "blockRuntimeId": 1759 - }, - { - "id": "minecraft:concrete", - "blockRuntimeId": 1758 - }, - { - "id": "minecraft:concrete", - "blockRuntimeId": 1766 - }, - { - "id": "minecraft:concrete", - "blockRuntimeId": 1763 - }, - { - "id": "minecraft:concrete", - "blockRuntimeId": 1765 - }, - { - "id": "minecraft:concrete", - "blockRuntimeId": 1752 - }, - { - "id": "minecraft:concrete", - "blockRuntimeId": 1755 - }, - { - "id": "minecraft:concrete", - "blockRuntimeId": 1756 - }, - { - "id": "minecraft:concrete", - "blockRuntimeId": 1764 - }, - { - "id": "minecraft:concrete", - "blockRuntimeId": 1760 - }, - { - "id": "minecraft:concrete", - "blockRuntimeId": 1754 - }, - { - "id": "minecraft:concrete", - "blockRuntimeId": 1762 - }, - { - "id": "minecraft:concrete", - "blockRuntimeId": 1761 - }, - { - "id": "minecraft:concrete", - "blockRuntimeId": 1753 - }, - { - "id": "minecraft:concrete", - "blockRuntimeId": 1757 - }, - { - "id": "minecraft:clay", - "blockRuntimeId": 11536 - }, - { - "id": "minecraft:hardened_clay", - "blockRuntimeId": 1348 - }, - { - "id": "minecraft:stained_hardened_clay", - "blockRuntimeId": 10558 - }, - { - "id": "minecraft:stained_hardened_clay", - "blockRuntimeId": 10566 - }, - { - "id": "minecraft:stained_hardened_clay", - "blockRuntimeId": 10565 - }, - { - "id": "minecraft:stained_hardened_clay", - "blockRuntimeId": 10573 - }, - { - "id": "minecraft:stained_hardened_clay", - "blockRuntimeId": 10570 - }, - { - "id": "minecraft:stained_hardened_clay", - "blockRuntimeId": 10572 - }, - { - "id": "minecraft:stained_hardened_clay", - "blockRuntimeId": 10559 - }, - { - "id": "minecraft:stained_hardened_clay", - "blockRuntimeId": 10562 - }, - { - "id": "minecraft:stained_hardened_clay", - "blockRuntimeId": 10563 - }, - { - "id": "minecraft:stained_hardened_clay", - "blockRuntimeId": 10571 - }, - { - "id": "minecraft:stained_hardened_clay", - "blockRuntimeId": 10567 - }, - { - "id": "minecraft:stained_hardened_clay", - "blockRuntimeId": 10561 - }, - { - "id": "minecraft:stained_hardened_clay", - "blockRuntimeId": 10569 - }, - { - "id": "minecraft:stained_hardened_clay", - "blockRuntimeId": 10568 - }, - { - "id": "minecraft:stained_hardened_clay", - "blockRuntimeId": 10560 - }, - { - "id": "minecraft:stained_hardened_clay", - "blockRuntimeId": 10564 - }, - { - "id": "minecraft:white_glazed_terracotta", - "blockRuntimeId": 8745 - }, - { - "id": "minecraft:silver_glazed_terracotta", - "blockRuntimeId": 5033 - }, - { - "id": "minecraft:gray_glazed_terracotta", - "blockRuntimeId": 13098 - }, - { - "id": "minecraft:black_glazed_terracotta", - "blockRuntimeId": 9396 - }, - { - "id": "minecraft:brown_glazed_terracotta", - "blockRuntimeId": 5433 - }, - { - "id": "minecraft:red_glazed_terracotta", - "blockRuntimeId": 6436 - }, - { - "id": "minecraft:orange_glazed_terracotta", - "blockRuntimeId": 2272 - }, - { - "id": "minecraft:yellow_glazed_terracotta", - "blockRuntimeId": 2032 - }, - { - "id": "minecraft:lime_glazed_terracotta", - "blockRuntimeId": 632 - }, - { - "id": "minecraft:green_glazed_terracotta", - "blockRuntimeId": 11016 - }, - { - "id": "minecraft:cyan_glazed_terracotta", - "blockRuntimeId": 8528 - }, - { - "id": "minecraft:light_blue_glazed_terracotta", - "blockRuntimeId": 8642 - }, - { - "id": "minecraft:blue_glazed_terracotta", - "blockRuntimeId": 8636 - }, - { - "id": "minecraft:purple_glazed_terracotta", - "blockRuntimeId": 11415 - }, - { - "id": "minecraft:magenta_glazed_terracotta", - "blockRuntimeId": 2086 - }, - { - "id": "minecraft:pink_glazed_terracotta", - "blockRuntimeId": 10945 - }, - { - "id": "minecraft:purpur_block", - "blockRuntimeId": 12533 - }, - { - "id": "minecraft:purpur_block", - "blockRuntimeId": 12535 - }, - { - "id": "minecraft:packed_mud", - "blockRuntimeId": 696 - }, - { - "id": "minecraft:mud_bricks", - "blockRuntimeId": 11287 - }, - { - "id": "minecraft:nether_wart_block", - "blockRuntimeId": 6569 - }, - { - "id": "minecraft:warped_wart_block", - "blockRuntimeId": 9875 - }, - { - "id": "minecraft:shroomlight", - "blockRuntimeId": 8198 - }, - { - "id": "minecraft:crimson_nylium", - "blockRuntimeId": 6460 - }, - { - "id": "minecraft:warped_nylium", - "blockRuntimeId": 10741 - }, - { - "id": "minecraft:netherrack", - "blockRuntimeId": 11441 - }, - { - "id": "minecraft:basalt", - "blockRuntimeId": 6660 - }, - { - "id": "minecraft:polished_basalt", - "blockRuntimeId": 24 - }, - { - "id": "minecraft:smooth_basalt", - "blockRuntimeId": 2278 - }, - { - "id": "minecraft:soul_soil", - "blockRuntimeId": 9004 - }, - { - "id": "minecraft:dirt", - "blockRuntimeId": 8925 - }, - { - "id": "minecraft:dirt", - "blockRuntimeId": 8926 - }, - { - "id": "minecraft:farmland", - "blockRuntimeId": 6181 - }, - { - "id": "minecraft:grass", - "blockRuntimeId": 11379 - }, - { - "id": "minecraft:grass_path", - "blockRuntimeId": 12910 - }, - { - "id": "minecraft:podzol", - "blockRuntimeId": 7392 - }, - { - "id": "minecraft:mycelium", - "blockRuntimeId": 5572 - }, - { - "id": "minecraft:mud", - "blockRuntimeId": 11078 - }, - { - "id": "minecraft:stone", - "blockRuntimeId": 1744 - }, - { - "id": "minecraft:iron_ore", - "blockRuntimeId": 7432 - }, - { - "id": "minecraft:gold_ore", - "blockRuntimeId": 2031 - }, - { - "id": "minecraft:diamond_ore", - "blockRuntimeId": 6672 - }, - { - "id": "minecraft:lapis_ore", - "blockRuntimeId": 12518 - }, - { - "id": "minecraft:redstone_ore", - "blockRuntimeId": 6563 - }, - { - "id": "minecraft:coal_ore", - "blockRuntimeId": 6561 - }, - { - "id": "minecraft:copper_ore", - "blockRuntimeId": 5440 - }, - { - "id": "minecraft:emerald_ore", - "blockRuntimeId": 12172 - }, - { - "id": "minecraft:quartz_ore", - "blockRuntimeId": 6815 - }, - { - "id": "minecraft:nether_gold_ore", - "blockRuntimeId": 27 - }, - { - "id": "minecraft:ancient_debris", - "blockRuntimeId": 10489 - }, - { - "id": "minecraft:deepslate_iron_ore", - "blockRuntimeId": 12098 - }, - { - "id": "minecraft:deepslate_gold_ore", - "blockRuntimeId": 10488 - }, - { - "id": "minecraft:deepslate_diamond_ore", - "blockRuntimeId": 12864 - }, - { - "id": "minecraft:deepslate_lapis_ore", - "blockRuntimeId": 12082 - }, - { - "id": "minecraft:deepslate_redstone_ore", - "blockRuntimeId": 11022 - }, - { - "id": "minecraft:deepslate_emerald_ore", - "blockRuntimeId": 10742 - }, - { - "id": "minecraft:deepslate_coal_ore", - "blockRuntimeId": 12000 - }, - { - "id": "minecraft:deepslate_copper_ore", - "blockRuntimeId": 108 - }, - { - "id": "minecraft:gravel", - "blockRuntimeId": 13134 - }, - { - "id": "minecraft:stone", - "blockRuntimeId": 1745 - }, - { - "id": "minecraft:stone", - "blockRuntimeId": 1747 - }, - { - "id": "minecraft:stone", - "blockRuntimeId": 1749 - }, - { - "id": "minecraft:blackstone", - "blockRuntimeId": 12404 - }, - { - "id": "minecraft:deepslate", - "blockRuntimeId": 662 - }, - { - "id": "minecraft:stone", - "blockRuntimeId": 1746 - }, - { - "id": "minecraft:stone", - "blockRuntimeId": 1748 - }, - { - "id": "minecraft:stone", - "blockRuntimeId": 1750 - }, - { - "id": "minecraft:polished_blackstone", - "blockRuntimeId": 5571 - }, - { - "id": "minecraft:polished_deepslate", - "blockRuntimeId": 12580 - }, - { - "id": "minecraft:sand", - "blockRuntimeId": 6466 - }, - { - "id": "minecraft:sand", - "blockRuntimeId": 6467 - }, - { - "id": "minecraft:cactus", - "blockRuntimeId": 11390 - }, - { - "id": "minecraft:oak_log", - "blockRuntimeId": 691 - }, - { - "id": "minecraft:stripped_oak_log", - "blockRuntimeId": 12362 - }, - { - "id": "minecraft:spruce_log", - "blockRuntimeId": 6541 - }, - { - "id": "minecraft:stripped_spruce_log", - "blockRuntimeId": 10680 - }, - { - "id": "minecraft:birch_log", - "blockRuntimeId": 1767 - }, - { - "id": "minecraft:stripped_birch_log", - "blockRuntimeId": 9942 - }, - { - "id": "minecraft:jungle_log", - "blockRuntimeId": 624 - }, - { - "id": "minecraft:stripped_jungle_log", - "blockRuntimeId": 1733 - }, - { - "id": "minecraft:acacia_log", - "blockRuntimeId": 6641 - }, - { - "id": "minecraft:stripped_acacia_log", - "blockRuntimeId": 9418 - }, - { - "id": "minecraft:dark_oak_log", - "blockRuntimeId": 4589 - }, - { - "id": "minecraft:stripped_dark_oak_log", - "blockRuntimeId": 621 - }, - { - "id": "minecraft:mangrove_log", - "blockRuntimeId": 1051 - }, - { - "id": "minecraft:stripped_mangrove_log", - "blockRuntimeId": 13131 - }, - { - "id": "minecraft:crimson_stem", - "blockRuntimeId": 9867 - }, - { - "id": "minecraft:stripped_crimson_stem", - "blockRuntimeId": 11352 - }, - { - "id": "minecraft:warped_stem", - "blockRuntimeId": 10890 - }, - { - "id": "minecraft:stripped_warped_stem", - "blockRuntimeId": 12219 - }, - { - "id": "minecraft:wood", - "blockRuntimeId": 4592 - }, - { - "id": "minecraft:wood", - "blockRuntimeId": 4598 - }, - { - "id": "minecraft:wood", - "blockRuntimeId": 4593 - }, - { - "id": "minecraft:wood", - "blockRuntimeId": 4599 - }, - { - "id": "minecraft:wood", - "blockRuntimeId": 4594 - }, - { - "id": "minecraft:wood", - "blockRuntimeId": 4600 - }, - { - "id": "minecraft:wood", - "blockRuntimeId": 4595 - }, - { - "id": "minecraft:wood", - "blockRuntimeId": 4601 - }, - { - "id": "minecraft:wood", - "blockRuntimeId": 4596 - }, - { - "id": "minecraft:wood", - "blockRuntimeId": 4602 - }, - { - "id": "minecraft:wood", - "blockRuntimeId": 4597 - }, - { - "id": "minecraft:wood", - "blockRuntimeId": 4603 - }, - { - "id": "minecraft:mangrove_wood", - "blockRuntimeId": 6430 - }, - { - "id": "minecraft:stripped_mangrove_wood", - "blockRuntimeId": 6500 - }, - { - "id": "minecraft:crimson_hyphae", - "blockRuntimeId": 6602 - }, - { - "id": "minecraft:stripped_crimson_hyphae", - "blockRuntimeId": 10903 - }, - { - "id": "minecraft:warped_hyphae", - "blockRuntimeId": 9872 - }, - { - "id": "minecraft:stripped_warped_hyphae", - "blockRuntimeId": 8751 - }, - { - "id": "minecraft:leaves", - "blockRuntimeId": 10472 - }, - { - "id": "minecraft:leaves", - "blockRuntimeId": 10473 - }, - { - "id": "minecraft:leaves", - "blockRuntimeId": 10474 - }, - { - "id": "minecraft:leaves", - "blockRuntimeId": 10475 - }, - { - "id": "minecraft:leaves2", - "blockRuntimeId": 6664 - }, - { - "id": "minecraft:leaves2", - "blockRuntimeId": 6665 - }, - { - "id": "minecraft:mangrove_leaves", - "blockRuntimeId": 11072 - }, - { - "id": "minecraft:azalea_leaves", - "blockRuntimeId": 12529 - }, - { - "id": "minecraft:azalea_leaves_flowered", - "blockRuntimeId": 10731 - }, - { - "id": "minecraft:sapling", - "blockRuntimeId": 1807 - }, - { - "id": "minecraft:sapling", - "blockRuntimeId": 1808 - }, - { - "id": "minecraft:sapling", - "blockRuntimeId": 1809 - }, - { - "id": "minecraft:sapling", - "blockRuntimeId": 1810 - }, - { - "id": "minecraft:sapling", - "blockRuntimeId": 1811 - }, - { - "id": "minecraft:sapling", - "blockRuntimeId": 1812 - }, - { - "id": "minecraft:mangrove_propagule", - "blockRuntimeId": 11380 - }, - { - "id": "minecraft:bee_nest", - "blockRuntimeId": 8928 - }, - { - "id": "minecraft:wheat_seeds", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:pumpkin_seeds", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:melon_seeds", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:beetroot_seeds", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:wheat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:beetroot", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potato", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:poisonous_potato", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:carrot", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:golden_carrot", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:apple", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:golden_apple", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:enchanted_golden_apple", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:melon_block", - "blockRuntimeId": 1098 - }, - { - "id": "minecraft:melon_slice", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:glistering_melon_slice", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:sweet_berries", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:glow_berries", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:pumpkin", - "blockRuntimeId": 6891 - }, - { - "id": "minecraft:carved_pumpkin", - "blockRuntimeId": 12197 - }, - { - "id": "minecraft:lit_pumpkin", - "blockRuntimeId": 11079 - }, - { - "id": "minecraft:honeycomb", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:tallgrass", - "blockRuntimeId": 2048 - }, - { - "id": "minecraft:double_plant", - "blockRuntimeId": 8626 - }, - { - "id": "minecraft:tallgrass", - "blockRuntimeId": 2047 - }, - { - "id": "minecraft:double_plant", - "blockRuntimeId": 8625 - }, - { - "id": "minecraft:nether_sprouts", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:coral", - "blockRuntimeId": 10896 - }, - { - "id": "minecraft:coral", - "blockRuntimeId": 10894 - }, - { - "id": "minecraft:coral", - "blockRuntimeId": 10895 - }, - { - "id": "minecraft:coral", - "blockRuntimeId": 10893 - }, - { - "id": "minecraft:coral", - "blockRuntimeId": 10897 - }, - { - "id": "minecraft:coral", - "blockRuntimeId": 10901 - }, - { - "id": "minecraft:coral", - "blockRuntimeId": 10899 - }, - { - "id": "minecraft:coral", - "blockRuntimeId": 10900 - }, - { - "id": "minecraft:coral", - "blockRuntimeId": 10898 - }, - { - "id": "minecraft:coral", - "blockRuntimeId": 10902 - }, - { - "id": "minecraft:coral_fan", - "blockRuntimeId": 6930 - }, - { - "id": "minecraft:coral_fan", - "blockRuntimeId": 6928 - }, - { - "id": "minecraft:coral_fan", - "blockRuntimeId": 6929 - }, - { - "id": "minecraft:coral_fan", - "blockRuntimeId": 6927 - }, - { - "id": "minecraft:coral_fan", - "blockRuntimeId": 6931 - }, - { - "id": "minecraft:coral_fan_dead", - "blockRuntimeId": 72 - }, - { - "id": "minecraft:coral_fan_dead", - "blockRuntimeId": 70 - }, - { - "id": "minecraft:coral_fan_dead", - "blockRuntimeId": 71 - }, - { - "id": "minecraft:coral_fan_dead", - "blockRuntimeId": 69 - }, - { - "id": "minecraft:coral_fan_dead", - "blockRuntimeId": 73 - }, - { - "id": "minecraft:crimson_roots", - "blockRuntimeId": 12392 - }, - { - "id": "minecraft:warped_roots", - "blockRuntimeId": 6673 - }, - { - "id": "minecraft:yellow_flower", - "blockRuntimeId": 1003 - }, - { - "id": "minecraft:red_flower", - "blockRuntimeId": 5505 - }, - { - "id": "minecraft:red_flower", - "blockRuntimeId": 5506 - }, - { - "id": "minecraft:red_flower", - "blockRuntimeId": 5507 - }, - { - "id": "minecraft:red_flower", - "blockRuntimeId": 5508 - }, - { - "id": "minecraft:red_flower", - "blockRuntimeId": 5509 - }, - { - "id": "minecraft:red_flower", - "blockRuntimeId": 5510 - }, - { - "id": "minecraft:red_flower", - "blockRuntimeId": 5511 - }, - { - "id": "minecraft:red_flower", - "blockRuntimeId": 5512 - }, - { - "id": "minecraft:red_flower", - "blockRuntimeId": 5513 - }, - { - "id": "minecraft:red_flower", - "blockRuntimeId": 5514 - }, - { - "id": "minecraft:red_flower", - "blockRuntimeId": 5515 - }, - { - "id": "minecraft:double_plant", - "blockRuntimeId": 8623 - }, - { - "id": "minecraft:double_plant", - "blockRuntimeId": 8624 - }, - { - "id": "minecraft:double_plant", - "blockRuntimeId": 8627 - }, - { - "id": "minecraft:double_plant", - "blockRuntimeId": 8628 - }, - { - "id": "minecraft:wither_rose", - "blockRuntimeId": 10547 - }, - { - "id": "minecraft:white_dye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:light_gray_dye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:gray_dye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:black_dye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:brown_dye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:red_dye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:orange_dye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:yellow_dye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lime_dye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:green_dye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cyan_dye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:light_blue_dye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:blue_dye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:purple_dye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:magenta_dye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:pink_dye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:ink_sac", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:glow_ink_sac", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cocoa_beans", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lapis_lazuli", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bone_meal", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:vine", - "blockRuntimeId": 1997 - }, - { - "id": "minecraft:weeping_vines", - "blockRuntimeId": 8651 - }, - { - "id": "minecraft:twisting_vines", - "blockRuntimeId": 8864 - }, - { - "id": "minecraft:waterlily", - "blockRuntimeId": 2279 - }, - { - "id": "minecraft:seagrass", - "blockRuntimeId": 655 - }, - { - "id": "minecraft:kelp", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:deadbush", - "blockRuntimeId": 7419 - }, - { - "id": "minecraft:bamboo", - "blockRuntimeId": 5573 - }, - { - "id": "minecraft:snow", - "blockRuntimeId": 6465 - }, - { - "id": "minecraft:ice", - "blockRuntimeId": 11083 - }, - { - "id": "minecraft:packed_ice", - "blockRuntimeId": 695 - }, - { - "id": "minecraft:blue_ice", - "blockRuntimeId": 11431 - }, - { - "id": "minecraft:snow_layer", - "blockRuntimeId": 560 - }, - { - "id": "minecraft:pointed_dripstone", - "blockRuntimeId": 12235 - }, - { - "id": "minecraft:dripstone_block", - "blockRuntimeId": 1996 - }, - { - "id": "minecraft:moss_carpet", - "blockRuntimeId": 699 - }, - { - "id": "minecraft:moss_block", - "blockRuntimeId": 10944 - }, - { - "id": "minecraft:dirt_with_roots", - "blockRuntimeId": 8567 - }, - { - "id": "minecraft:hanging_roots", - "blockRuntimeId": 610 - }, - { - "id": "minecraft:mangrove_roots", - "blockRuntimeId": 10557 - }, - { - "id": "minecraft:muddy_mangrove_roots", - "blockRuntimeId": 1046 - }, - { - "id": "minecraft:big_dripleaf", - "blockRuntimeId": 9950 - }, - { - "id": "minecraft:small_dripleaf_block", - "blockRuntimeId": 6628 - }, - { - "id": "minecraft:spore_blossom", - "blockRuntimeId": 12137 - }, - { - "id": "minecraft:azalea", - "blockRuntimeId": 11286 - }, - { - "id": "minecraft:flowering_azalea", - "blockRuntimeId": 8648 - }, - { - "id": "minecraft:glow_lichen", - "blockRuntimeId": 8857 - }, - { - "id": "minecraft:amethyst_block", - "blockRuntimeId": 735 - }, - { - "id": "minecraft:budding_amethyst", - "blockRuntimeId": 11406 - }, - { - "id": "minecraft:amethyst_cluster", - "blockRuntimeId": 12636 - }, - { - "id": "minecraft:large_amethyst_bud", - "blockRuntimeId": 7470 - }, - { - "id": "minecraft:medium_amethyst_bud", - "blockRuntimeId": 6687 - }, - { - "id": "minecraft:small_amethyst_bud", - "blockRuntimeId": 1005 - }, - { - "id": "minecraft:tuff", - "blockRuntimeId": 1050 - }, - { - "id": "minecraft:calcite", - "blockRuntimeId": 620 - }, - { - "id": "minecraft:chicken", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:porkchop", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:beef", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:mutton", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:rabbit", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cod", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:salmon", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:tropical_fish", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:pufferfish", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:brown_mushroom", - "blockRuntimeId": 5432 - }, - { - "id": "minecraft:red_mushroom", - "blockRuntimeId": 6899 - }, - { - "id": "minecraft:crimson_fungus", - "blockRuntimeId": 12578 - }, - { - "id": "minecraft:warped_fungus", - "blockRuntimeId": 700 - }, - { - "id": "minecraft:brown_mushroom_block", - "blockRuntimeId": 12187 - }, - { - "id": "minecraft:red_mushroom_block", - "blockRuntimeId": 5500 - }, - { - "id": "minecraft:brown_mushroom_block", - "blockRuntimeId": 12188 - }, - { - "id": "minecraft:brown_mushroom_block", - "blockRuntimeId": 12173 - }, - { - "id": "minecraft:egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:sugar_cane", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:sugar", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:rotten_flesh", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bone", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:web", - "blockRuntimeId": 11107 - }, - { - "id": "minecraft:spider_eye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:mob_spawner", - "blockRuntimeId": 1107 - }, - { - "id": "minecraft:monster_egg", - "blockRuntimeId": 6413 - }, - { - "id": "minecraft:monster_egg", - "blockRuntimeId": 6414 - }, - { - "id": "minecraft:monster_egg", - "blockRuntimeId": 6415 - }, - { - "id": "minecraft:monster_egg", - "blockRuntimeId": 6416 - }, - { - "id": "minecraft:monster_egg", - "blockRuntimeId": 6417 - }, - { - "id": "minecraft:monster_egg", - "blockRuntimeId": 6418 - }, - { - "id": "minecraft:infested_deepslate", - "blockRuntimeId": 7383 - }, - { - "id": "minecraft:dragon_egg", - "blockRuntimeId": 12096 - }, - { - "id": "minecraft:turtle_egg", - "blockRuntimeId": 12823 - }, - { - "id": "minecraft:frog_spawn", - "blockRuntimeId": 6710 - }, - { - "id": "minecraft:pearlescent_froglight", - "blockRuntimeId": 10827 - }, - { - "id": "minecraft:verdant_froglight", - "blockRuntimeId": 10885 - }, - { - "id": "minecraft:ochre_froglight", - "blockRuntimeId": 5012 - }, - { - "id": "minecraft:chicken_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bee_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cow_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:pig_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:sheep_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:wolf_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:polar_bear_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:ocelot_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cat_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:mooshroom_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bat_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:parrot_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:rabbit_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:llama_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:horse_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:donkey_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:mule_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:skeleton_horse_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:zombie_horse_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:tropical_fish_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cod_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:pufferfish_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:salmon_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:dolphin_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:turtle_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:panda_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:fox_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:creeper_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:enderman_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:silverfish_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:skeleton_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:wither_skeleton_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:stray_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:slime_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:spider_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:zombie_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:zombie_pigman_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:husk_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:drowned_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:squid_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:glow_squid_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cave_spider_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:witch_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:guardian_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:elder_guardian_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:endermite_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:magma_cube_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:strider_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:hoglin_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:piglin_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:zoglin_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:piglin_brute_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:goat_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:axolotl_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:warden_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:allay_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:frog_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:tadpole_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:trader_llama_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:ghast_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:blaze_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:shulker_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:vindicator_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:evoker_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:vex_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:villager_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:wandering_trader_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:zombie_villager_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:phantom_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:pillager_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:ravager_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:iron_golem_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:snow_golem_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:obsidian", - "blockRuntimeId": 1134 - }, - { - "id": "minecraft:crying_obsidian", - "blockRuntimeId": 11116 - }, - { - "id": "minecraft:bedrock", - "blockRuntimeId": 11421 - }, - { - "id": "minecraft:soul_sand", - "blockRuntimeId": 9005 - }, - { - "id": "minecraft:magma", - "blockRuntimeId": 12835 - }, - { - "id": "minecraft:nether_wart", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:end_stone", - "blockRuntimeId": 6105 - }, - { - "id": "minecraft:chorus_flower", - "blockRuntimeId": 6844 - }, - { - "id": "minecraft:chorus_plant", - "blockRuntimeId": 8677 - }, - { - "id": "minecraft:chorus_fruit", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:popped_chorus_fruit", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:sponge", - "blockRuntimeId": 1335 - }, - { - "id": "minecraft:sponge", - "blockRuntimeId": 1336 - }, - { - "id": "minecraft:coral_block", - "blockRuntimeId": 8390 - }, - { - "id": "minecraft:coral_block", - "blockRuntimeId": 8391 - }, - { - "id": "minecraft:coral_block", - "blockRuntimeId": 8392 - }, - { - "id": "minecraft:coral_block", - "blockRuntimeId": 8393 - }, - { - "id": "minecraft:coral_block", - "blockRuntimeId": 8394 - }, - { - "id": "minecraft:coral_block", - "blockRuntimeId": 8395 - }, - { - "id": "minecraft:coral_block", - "blockRuntimeId": 8396 - }, - { - "id": "minecraft:coral_block", - "blockRuntimeId": 8397 - }, - { - "id": "minecraft:coral_block", - "blockRuntimeId": 8398 - }, - { - "id": "minecraft:coral_block", - "blockRuntimeId": 8399 - }, - { - "id": "minecraft:sculk", - "blockRuntimeId": 11440 - }, - { - "id": "minecraft:sculk_vein", - "blockRuntimeId": 11936 - }, - { - "id": "minecraft:sculk_catalyst", - "blockRuntimeId": 5502 - }, - { - "id": "minecraft:sculk_shrieker", - "blockRuntimeId": 627 - }, - { - "id": "minecraft:sculk_sensor", - "blockRuntimeId": 6700 - }, - { - "id": "minecraft:reinforced_deepslate", - "blockRuntimeId": 9390 - }, - { - "id": "minecraft:leather_helmet", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:chainmail_helmet", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:iron_helmet", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:golden_helmet", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:diamond_helmet", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:netherite_helmet", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:leather_chestplate", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:chainmail_chestplate", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:iron_chestplate", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:golden_chestplate", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:diamond_chestplate", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:netherite_chestplate", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:leather_leggings", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:chainmail_leggings", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:iron_leggings", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:golden_leggings", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:diamond_leggings", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:netherite_leggings", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:leather_boots", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:chainmail_boots", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:iron_boots", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:golden_boots", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:diamond_boots", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:netherite_boots", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:wooden_sword", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:stone_sword", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:iron_sword", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:golden_sword", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:diamond_sword", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:netherite_sword", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:wooden_axe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:stone_axe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:iron_axe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:golden_axe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:diamond_axe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:netherite_axe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:wooden_pickaxe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:stone_pickaxe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:iron_pickaxe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:golden_pickaxe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:diamond_pickaxe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:netherite_pickaxe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:wooden_shovel", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:stone_shovel", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:iron_shovel", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:golden_shovel", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:diamond_shovel", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:netherite_shovel", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:wooden_hoe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:stone_hoe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:iron_hoe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:golden_hoe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:diamond_hoe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:netherite_hoe", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bow", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:crossbow", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 6, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 7, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 8, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 9, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 10, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 11, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 12, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 13, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 14, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 15, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 16, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 17, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 18, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 19, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 20, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 21, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 22, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 23, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 24, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 25, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 26, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 27, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 28, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 29, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 30, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 31, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 32, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 33, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 34, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 35, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 36, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 37, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 38, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 39, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 40, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 41, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 42, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:arrow", - "damage": 43, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:shield", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cooked_chicken", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cooked_porkchop", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cooked_beef", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cooked_mutton", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cooked_rabbit", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cooked_cod", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cooked_salmon", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bread", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:mushroom_stew", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:beetroot_soup", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:rabbit_stew", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:baked_potato", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cookie", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:pumpkin_pie", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cake", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:dried_kelp", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:fishing_rod", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:carrot_on_a_stick", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:warped_fungus_on_a_stick", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:snowball", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:shears", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:flint_and_steel", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lead", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:clock", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:compass", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:recovery_compass", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:goat_horn", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:goat_horn", - "damage": 1, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:goat_horn", - "damage": 2, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:goat_horn", - "damage": 3, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:goat_horn", - "damage": 4, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:goat_horn", - "damage": 5, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:goat_horn", - "damage": 6, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:goat_horn", - "damage": 7, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:empty_map", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:empty_map", - "damage": 2, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:saddle", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:leather_horse_armor", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:iron_horse_armor", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:golden_horse_armor", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:diamond_horse_armor", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:trident", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:turtle_helmet", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:elytra", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:totem_of_undying", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:glass_bottle", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:experience_bottle", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 1, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 2, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 3, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 4, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 5, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 6, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 7, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 8, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 9, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 10, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 11, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 12, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 13, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 14, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 15, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 16, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 17, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 18, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 19, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 20, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 21, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 22, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 23, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 24, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 25, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 26, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 27, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 28, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 29, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 30, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 31, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 32, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 33, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 34, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 35, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 36, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 37, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 38, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 39, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 40, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 41, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:potion", - "damage": 42, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 1, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 2, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 3, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 4, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 5, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 6, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 7, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 8, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 9, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 10, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 11, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 12, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 13, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 14, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 15, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 16, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 17, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 18, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 19, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 20, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 21, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 22, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 23, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 24, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 25, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 26, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 27, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 28, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 29, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 30, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 31, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 32, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 33, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 34, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 35, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 36, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 37, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 38, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 39, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 40, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 41, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:splash_potion", - "damage": 42, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 1, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 2, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 3, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 4, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 5, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 6, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 7, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 8, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 9, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 10, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 11, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 12, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 13, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 14, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 15, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 16, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 17, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 18, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 19, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 20, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 21, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 22, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 23, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 24, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 25, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 26, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 27, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 28, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 29, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 30, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 31, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 32, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 33, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 34, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 35, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 36, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 37, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 38, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 39, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 40, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 41, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lingering_potion", - "damage": 42, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:spyglass", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:stick", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bed", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bed", - "damage": 8, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bed", - "damage": 7, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bed", - "damage": 15, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bed", - "damage": 12, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bed", - "damage": 14, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bed", - "damage": 1, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bed", - "damage": 4, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bed", - "damage": 5, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bed", - "damage": 13, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bed", - "damage": 9, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bed", - "damage": 3, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bed", - "damage": 11, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bed", - "damage": 10, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bed", - "damage": 2, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bed", - "damage": 6, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:torch", - "blockRuntimeId": 1827 - }, - { - "id": "minecraft:soul_torch", - "blockRuntimeId": 7386 - }, - { - "id": "minecraft:sea_pickle", - "blockRuntimeId": 9425 - }, - { - "id": "minecraft:lantern", - "blockRuntimeId": 11478 - }, - { - "id": "minecraft:soul_lantern", - "blockRuntimeId": 8923 - }, - { - "id": "minecraft:candle", - "blockRuntimeId": 12222 - }, - { - "id": "minecraft:white_candle", - "blockRuntimeId": 8469 - }, - { - "id": "minecraft:orange_candle", - "blockRuntimeId": 1066 - }, - { - "id": "minecraft:magenta_candle", - "blockRuntimeId": 1124 - }, - { - "id": "minecraft:light_blue_candle", - "blockRuntimeId": 6883 - }, - { - "id": "minecraft:yellow_candle", - "blockRuntimeId": 10574 - }, - { - "id": "minecraft:lime_candle", - "blockRuntimeId": 10760 - }, - { - "id": "minecraft:pink_candle", - "blockRuntimeId": 12189 - }, - { - "id": "minecraft:gray_candle", - "blockRuntimeId": 2058 - }, - { - "id": "minecraft:light_gray_candle", - "blockRuntimeId": 10616 - }, - { - "id": "minecraft:cyan_candle", - "blockRuntimeId": 12551 - }, - { - "id": "minecraft:purple_candle", - "blockRuntimeId": 11442 - }, - { - "id": "minecraft:blue_candle", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:brown_candle", - "blockRuntimeId": 9845 - }, - { - "id": "minecraft:green_candle", - "blockRuntimeId": 1781 - }, - { - "id": "minecraft:red_candle", - "blockRuntimeId": 7423 - }, - { - "id": "minecraft:black_candle", - "blockRuntimeId": 576 - }, - { - "id": "minecraft:crafting_table", - "blockRuntimeId": 9424 - }, - { - "id": "minecraft:cartography_table", - "blockRuntimeId": 13135 - }, - { - "id": "minecraft:fletching_table", - "blockRuntimeId": 9391 - }, - { - "id": "minecraft:smithing_table", - "blockRuntimeId": 5615 - }, - { - "id": "minecraft:beehive", - "blockRuntimeId": 10490 - }, - { - "id": "minecraft:campfire", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:soul_campfire", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:furnace", - "blockRuntimeId": 12628 - }, - { - "id": "minecraft:blast_furnace", - "blockRuntimeId": 12386 - }, - { - "id": "minecraft:smoker", - "blockRuntimeId": 1738 - }, - { - "id": "minecraft:respawn_anchor", - "blockRuntimeId": 1776 - }, - { - "id": "minecraft:brewing_stand", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:anvil", - "blockRuntimeId": 11040 - }, - { - "id": "minecraft:anvil", - "blockRuntimeId": 11044 - }, - { - "id": "minecraft:anvil", - "blockRuntimeId": 11048 - }, - { - "id": "minecraft:grindstone", - "blockRuntimeId": 12865 - }, - { - "id": "minecraft:enchanting_table", - "blockRuntimeId": 11121 - }, - { - "id": "minecraft:bookshelf", - "blockRuntimeId": 11077 - }, - { - "id": "minecraft:lectern", - "blockRuntimeId": 11344 - }, - { - "id": "minecraft:cauldron", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:composter", - "blockRuntimeId": 8586 - }, - { - "id": "minecraft:chest", - "blockRuntimeId": 11521 - }, - { - "id": "minecraft:trapped_chest", - "blockRuntimeId": 8755 - }, - { - "id": "minecraft:ender_chest", - "blockRuntimeId": 6680 - }, - { - "id": "minecraft:barrel", - "blockRuntimeId": 6832 - }, - { - "id": "minecraft:undyed_shulker_box", - "blockRuntimeId": 5570 - }, - { - "id": "minecraft:shulker_box", - "blockRuntimeId": 8485 - }, - { - "id": "minecraft:shulker_box", - "blockRuntimeId": 8493 - }, - { - "id": "minecraft:shulker_box", - "blockRuntimeId": 8492 - }, - { - "id": "minecraft:shulker_box", - "blockRuntimeId": 8500 - }, - { - "id": "minecraft:shulker_box", - "blockRuntimeId": 8497 - }, - { - "id": "minecraft:shulker_box", - "blockRuntimeId": 8499 - }, - { - "id": "minecraft:shulker_box", - "blockRuntimeId": 8486 - }, - { - "id": "minecraft:shulker_box", - "blockRuntimeId": 8489 - }, - { - "id": "minecraft:shulker_box", - "blockRuntimeId": 8490 - }, - { - "id": "minecraft:shulker_box", - "blockRuntimeId": 8498 - }, - { - "id": "minecraft:shulker_box", - "blockRuntimeId": 8494 - }, - { - "id": "minecraft:shulker_box", - "blockRuntimeId": 8488 - }, - { - "id": "minecraft:shulker_box", - "blockRuntimeId": 8496 - }, - { - "id": "minecraft:shulker_box", - "blockRuntimeId": 8495 - }, - { - "id": "minecraft:shulker_box", - "blockRuntimeId": 8487 - }, - { - "id": "minecraft:shulker_box", - "blockRuntimeId": 8491 - }, - { - "id": "minecraft:armor_stand", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:noteblock", - "blockRuntimeId": 1049 - }, - { - "id": "minecraft:jukebox", - "blockRuntimeId": 8008 - }, - { - "id": "minecraft:music_disc_13", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:music_disc_cat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:music_disc_blocks", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:music_disc_chirp", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:music_disc_far", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:music_disc_mall", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:music_disc_mellohi", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:music_disc_stal", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:music_disc_strad", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:music_disc_ward", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:music_disc_11", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:music_disc_wait", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:music_disc_otherside", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:music_disc_5", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:music_disc_pigstep", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:disc_fragment_5", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:glowstone_dust", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:glowstone", - "blockRuntimeId": 6154 - }, - { - "id": "minecraft:redstone_lamp", - "blockRuntimeId": 660 - }, - { - "id": "minecraft:sea_lantern", - "blockRuntimeId": 12365 - }, - { - "id": "minecraft:oak_sign", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:spruce_sign", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:birch_sign", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:jungle_sign", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:acacia_sign", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:dark_oak_sign", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:mangrove_sign", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:crimson_sign", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:warped_sign", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:painting", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:frame", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:glow_frame", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:honey_bottle", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:flower_pot", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bowl", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bucket", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:milk_bucket", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:water_bucket", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:lava_bucket", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:cod_bucket", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:salmon_bucket", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:tropical_fish_bucket", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:pufferfish_bucket", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:powder_snow_bucket", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:axolotl_bucket", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:tadpole_bucket", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:skull", - "damage": 3, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:skull", - "damage": 2, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:skull", - "damage": 4, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:skull", - "damage": 5, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:skull", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:skull", - "damage": 1, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:beacon", - "blockRuntimeId": 550 - }, - { - "id": "minecraft:bell", - "blockRuntimeId": 11312 - }, - { - "id": "minecraft:conduit", - "blockRuntimeId": 6503 - }, - { - "id": "minecraft:stonecutter_block", - "blockRuntimeId": 12393 - }, - { - "id": "minecraft:end_portal_frame", - "blockRuntimeId": 10443 - }, - { - "id": "minecraft:coal", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:charcoal", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:diamond", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:iron_nugget", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:raw_iron", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:raw_gold", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:raw_copper", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:copper_ingot", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:iron_ingot", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:netherite_scrap", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:netherite_ingot", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:gold_nugget", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:gold_ingot", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:emerald", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:quartz", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:clay_ball", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:brick", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:netherbrick", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:prismarine_shard", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:amethyst_shard", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:prismarine_crystals", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:nautilus_shell", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:heart_of_the_sea", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:scute", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:phantom_membrane", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:string", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:feather", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:flint", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:gunpowder", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:leather", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:rabbit_hide", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:rabbit_foot", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:fire_charge", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:blaze_rod", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:blaze_powder", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:magma_cream", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:fermented_spider_eye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:echo_shard", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:dragon_breath", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:shulker_shell", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:ghast_tear", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:slime_ball", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:ender_pearl", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:ender_eye", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:nether_star", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:end_rod", - "blockRuntimeId": 9861 - }, - { - "id": "minecraft:lightning_rod", - "blockRuntimeId": 2305 - }, - { - "id": "minecraft:end_crystal", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:paper", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:book", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:writable_book", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQFAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQFAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQFAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQGAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQGAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQGAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQHAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQHAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQHAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQIAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAUAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAUAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAUAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQMAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQMAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQNAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQNAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQOAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQOAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQOAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAUAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQQAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQRAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQRAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQRAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQSAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQSAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQSAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAUAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQUAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQUAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQVAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQWAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQXAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQXAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQXAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQYAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQYAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQYAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQZAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQZAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQaAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQbAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQcAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAUAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQeAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQeAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQeAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQfAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQfAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQfAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQgAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQhAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAQAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQjAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQjAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQjAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQkAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQkAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQkAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQlAAIDAGx2bAEAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQlAAIDAGx2bAIAAAA=" - }, - { - "id": "minecraft:enchanted_book", - "blockRuntimeId": 0, - "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQlAAIDAGx2bAMAAAA=" - }, - { - "id": "minecraft:oak_boat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:spruce_boat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:birch_boat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:jungle_boat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:acacia_boat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:dark_oak_boat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:mangrove_boat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:oak_chest_boat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:spruce_chest_boat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:birch_chest_boat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:jungle_chest_boat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:acacia_chest_boat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:dark_oak_chest_boat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:mangrove_chest_boat", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:rail", - "blockRuntimeId": 6189 - }, - { - "id": "minecraft:golden_rail", - "blockRuntimeId": 8501 - }, - { - "id": "minecraft:detector_rail", - "blockRuntimeId": 6401 - }, - { - "id": "minecraft:activator_rail", - "blockRuntimeId": 1010 - }, - { - "id": "minecraft:minecart", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:chest_minecart", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:hopper_minecart", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:tnt_minecart", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:redstone", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:redstone_block", - "blockRuntimeId": 5667 - }, - { - "id": "minecraft:redstone_torch", - "blockRuntimeId": 5027 - }, - { - "id": "minecraft:lever", - "blockRuntimeId": 10918 - }, - { - "id": "minecraft:wooden_button", - "blockRuntimeId": 10783 - }, - { - "id": "minecraft:spruce_button", - "blockRuntimeId": 6629 - }, - { - "id": "minecraft:birch_button", - "blockRuntimeId": 12592 - }, - { - "id": "minecraft:jungle_button", - "blockRuntimeId": 120 - }, - { - "id": "minecraft:acacia_button", - "blockRuntimeId": 12051 - }, - { - "id": "minecraft:dark_oak_button", - "blockRuntimeId": 96 - }, - { - "id": "minecraft:mangrove_button", - "blockRuntimeId": 11466 - }, - { - "id": "minecraft:stone_button", - "blockRuntimeId": 1302 - }, - { - "id": "minecraft:crimson_button", - "blockRuntimeId": 6746 - }, - { - "id": "minecraft:warped_button", - "blockRuntimeId": 12070 - }, - { - "id": "minecraft:polished_blackstone_button", - "blockRuntimeId": 12616 - }, - { - "id": "minecraft:tripwire_hook", - "blockRuntimeId": 9884 - }, - { - "id": "minecraft:wooden_pressure_plate", - "blockRuntimeId": 12890 - }, - { - "id": "minecraft:spruce_pressure_plate", - "blockRuntimeId": 5649 - }, - { - "id": "minecraft:birch_pressure_plate", - "blockRuntimeId": 5441 - }, - { - "id": "minecraft:jungle_pressure_plate", - "blockRuntimeId": 5524 - }, - { - "id": "minecraft:acacia_pressure_plate", - "blockRuntimeId": 8400 - }, - { - "id": "minecraft:dark_oak_pressure_plate", - "blockRuntimeId": 9926 - }, - { - "id": "minecraft:mangrove_pressure_plate", - "blockRuntimeId": 6138 - }, - { - "id": "minecraft:crimson_pressure_plate", - "blockRuntimeId": 13115 - }, - { - "id": "minecraft:warped_pressure_plate", - "blockRuntimeId": 666 - }, - { - "id": "minecraft:stone_pressure_plate", - "blockRuntimeId": 6155 - }, - { - "id": "minecraft:light_weighted_pressure_plate", - "blockRuntimeId": 5554 - }, - { - "id": "minecraft:heavy_weighted_pressure_plate", - "blockRuntimeId": 2289 - }, - { - "id": "minecraft:polished_blackstone_pressure_plate", - "blockRuntimeId": 10624 - }, - { - "id": "minecraft:observer", - "blockRuntimeId": 5015 - }, - { - "id": "minecraft:daylight_detector", - "blockRuntimeId": 6468 - }, - { - "id": "minecraft:repeater", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:comparator", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:hopper", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:dropper", - "blockRuntimeId": 12204 - }, - { - "id": "minecraft:dispenser", - "blockRuntimeId": 12839 - }, - { - "id": "minecraft:piston", - "blockRuntimeId": 2041 - }, - { - "id": "minecraft:sticky_piston", - "blockRuntimeId": 6675 - }, - { - "id": "minecraft:tnt", - "blockRuntimeId": 11101 - }, - { - "id": "minecraft:name_tag", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:loom", - "blockRuntimeId": 6101 - }, - { - "id": "minecraft:banner", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:banner", - "damage": 8, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:banner", - "damage": 7, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:banner", - "damage": 15, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:banner", - "damage": 12, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:banner", - "damage": 14, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:banner", - "damage": 1, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:banner", - "damage": 4, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:banner", - "damage": 5, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:banner", - "damage": 13, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:banner", - "damage": 9, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:banner", - "damage": 3, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:banner", - "damage": 11, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:banner", - "damage": 10, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:banner", - "damage": 2, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:banner", - "damage": 6, - "blockRuntimeId": 0 - }, - { - "id": "minecraft:banner", - "damage": 15, - "blockRuntimeId": 0, - "nbt_b64": "CgAAAwQAVHlwZQEAAAAA" - }, - { - "id": "minecraft:creeper_banner_pattern", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:skull_banner_pattern", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:flower_banner_pattern", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:mojang_banner_pattern", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:field_masoned_banner_pattern", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:bordure_indented_banner_pattern", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:piglin_banner_pattern", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:globe_banner_pattern", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwAAAAAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAABwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAIBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAHBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAPBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAMBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAOBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAABBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAEBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAFBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAANBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAJBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAADBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAALBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAKBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAACBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_rocket", - "blockRuntimeId": 0, - "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAGBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA" - }, - { - "id": "minecraft:firework_star", - "blockRuntimeId": 0, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yIR0d/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 8, - "blockRuntimeId": 0, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yUk9H/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 7, - "blockRuntimeId": 0, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yl52d/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 15, - "blockRuntimeId": 0, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9y8PDw/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 12, - "blockRuntimeId": 0, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9y2rM6/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 14, - "blockRuntimeId": 0, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yHYD5/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 1, - "blockRuntimeId": 0, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yJi6w/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 4, - "blockRuntimeId": 0, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yqkQ8/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 5, - "blockRuntimeId": 0, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yuDKJ/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 13, - "blockRuntimeId": 0, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yvU7H/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 9, - "blockRuntimeId": 0, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yqovz/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 3, - "blockRuntimeId": 0, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yMlSD/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 11, - "blockRuntimeId": 0, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yPdj+/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 10, - "blockRuntimeId": 0, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yH8eA/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 2, - "blockRuntimeId": 0, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yFnxe/wA=" - }, - { - "id": "minecraft:firework_star", - "damage": 6, - "blockRuntimeId": 0, - "nbt_b64": "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9ynJwW/wA=" - }, - { - "id": "minecraft:chain", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:target", - "blockRuntimeId": 10782 - }, - { - "id": "minecraft:lodestone_compass", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:wither_spawn_egg", - "blockRuntimeId": 0 - }, - { - "id": "minecraft:ender_dragon_spawn_egg", - "blockRuntimeId": 0 - } - ] -} \ No newline at end of file diff --git a/core/src/main/resources/bedrock/runtime_item_states.1_19_80.json b/core/src/main/resources/bedrock/runtime_item_states.1_19_80.json deleted file mode 100644 index 0b931d671..000000000 --- a/core/src/main/resources/bedrock/runtime_item_states.1_19_80.json +++ /dev/null @@ -1,5066 +0,0 @@ -[ - { - "name": "minecraft:acacia_boat", - "id": 380 - }, - { - "name": "minecraft:acacia_button", - "id": -140 - }, - { - "name": "minecraft:acacia_chest_boat", - "id": 648 - }, - { - "name": "minecraft:acacia_door", - "id": 562 - }, - { - "name": "minecraft:acacia_fence", - "id": -575 - }, - { - "name": "minecraft:acacia_fence_gate", - "id": 187 - }, - { - "name": "minecraft:acacia_hanging_sign", - "id": -504 - }, - { - "name": "minecraft:acacia_log", - "id": 162 - }, - { - "name": "minecraft:acacia_pressure_plate", - "id": -150 - }, - { - "name": "minecraft:acacia_sign", - "id": 585 - }, - { - "name": "minecraft:acacia_stairs", - "id": 163 - }, - { - "name": "minecraft:acacia_standing_sign", - "id": -190 - }, - { - "name": "minecraft:acacia_trapdoor", - "id": -145 - }, - { - "name": "minecraft:acacia_wall_sign", - "id": -191 - }, - { - "name": "minecraft:activator_rail", - "id": 126 - }, - { - "name": "minecraft:agent_spawn_egg", - "id": 488 - }, - { - "name": "minecraft:air", - "id": -158 - }, - { - "name": "minecraft:allay_spawn_egg", - "id": 637 - }, - { - "name": "minecraft:allow", - "id": 210 - }, - { - "name": "minecraft:amethyst_block", - "id": -327 - }, - { - "name": "minecraft:amethyst_cluster", - "id": -329 - }, - { - "name": "minecraft:amethyst_shard", - "id": 630 - }, - { - "name": "minecraft:ancient_debris", - "id": -271 - }, - { - "name": "minecraft:andesite_stairs", - "id": -171 - }, - { - "name": "minecraft:angler_pottery_shard", - "id": 662 - }, - { - "name": "minecraft:anvil", - "id": 145 - }, - { - "name": "minecraft:apple", - "id": 257 - }, - { - "name": "minecraft:archer_pottery_shard", - "id": 663 - }, - { - "name": "minecraft:armor_stand", - "id": 558 - }, - { - "name": "minecraft:arms_up_pottery_shard", - "id": 664 - }, - { - "name": "minecraft:arrow", - "id": 302 - }, - { - "name": "minecraft:axolotl_bucket", - "id": 370 - }, - { - "name": "minecraft:axolotl_spawn_egg", - "id": 502 - }, - { - "name": "minecraft:azalea", - "id": -337 - }, - { - "name": "minecraft:azalea_leaves", - "id": -324 - }, - { - "name": "minecraft:azalea_leaves_flowered", - "id": -325 - }, - { - "name": "minecraft:baked_potato", - "id": 281 - }, - { - "name": "minecraft:balloon", - "id": 604 - }, - { - "name": "minecraft:bamboo", - "id": -163 - }, - { - "name": "minecraft:bamboo_block", - "id": -527 - }, - { - "name": "minecraft:bamboo_button", - "id": -511 - }, - { - "name": "minecraft:bamboo_chest_raft", - "id": 660 - }, - { - "name": "minecraft:bamboo_door", - "id": -517 - }, - { - "name": "minecraft:bamboo_double_slab", - "id": -521 - }, - { - "name": "minecraft:bamboo_fence", - "id": -515 - }, - { - "name": "minecraft:bamboo_fence_gate", - "id": -516 - }, - { - "name": "minecraft:bamboo_hanging_sign", - "id": -522 - }, - { - "name": "minecraft:bamboo_mosaic", - "id": -509 - }, - { - "name": "minecraft:bamboo_mosaic_double_slab", - "id": -525 - }, - { - "name": "minecraft:bamboo_mosaic_slab", - "id": -524 - }, - { - "name": "minecraft:bamboo_mosaic_stairs", - "id": -523 - }, - { - "name": "minecraft:bamboo_planks", - "id": -510 - }, - { - "name": "minecraft:bamboo_pressure_plate", - "id": -514 - }, - { - "name": "minecraft:bamboo_raft", - "id": 659 - }, - { - "name": "minecraft:bamboo_sapling", - "id": -164 - }, - { - "name": "minecraft:bamboo_sign", - "id": 658 - }, - { - "name": "minecraft:bamboo_slab", - "id": -513 - }, - { - "name": "minecraft:bamboo_stairs", - "id": -512 - }, - { - "name": "minecraft:bamboo_standing_sign", - "id": -518 - }, - { - "name": "minecraft:bamboo_trapdoor", - "id": -520 - }, - { - "name": "minecraft:bamboo_wall_sign", - "id": -519 - }, - { - "name": "minecraft:banner", - "id": 573 - }, - { - "name": "minecraft:banner_pattern", - "id": 706 - }, - { - "name": "minecraft:barrel", - "id": -203 - }, - { - "name": "minecraft:barrier", - "id": -161 - }, - { - "name": "minecraft:basalt", - "id": -234 - }, - { - "name": "minecraft:bat_spawn_egg", - "id": 454 - }, - { - "name": "minecraft:beacon", - "id": 138 - }, - { - "name": "minecraft:bed", - "id": 419 - }, - { - "name": "minecraft:bedrock", - "id": 7 - }, - { - "name": "minecraft:bee_nest", - "id": -218 - }, - { - "name": "minecraft:bee_spawn_egg", - "id": 495 - }, - { - "name": "minecraft:beef", - "id": 273 - }, - { - "name": "minecraft:beehive", - "id": -219 - }, - { - "name": "minecraft:beetroot", - "id": 285 - }, - { - "name": "minecraft:beetroot_seeds", - "id": 295 - }, - { - "name": "minecraft:beetroot_soup", - "id": 286 - }, - { - "name": "minecraft:bell", - "id": -206 - }, - { - "name": "minecraft:big_dripleaf", - "id": -323 - }, - { - "name": "minecraft:birch_boat", - "id": 377 - }, - { - "name": "minecraft:birch_button", - "id": -141 - }, - { - "name": "minecraft:birch_chest_boat", - "id": 645 - }, - { - "name": "minecraft:birch_door", - "id": 560 - }, - { - "name": "minecraft:birch_fence", - "id": -576 - }, - { - "name": "minecraft:birch_fence_gate", - "id": 184 - }, - { - "name": "minecraft:birch_hanging_sign", - "id": -502 - }, - { - "name": "minecraft:birch_log", - "id": -570 - }, - { - "name": "minecraft:birch_pressure_plate", - "id": -151 - }, - { - "name": "minecraft:birch_sign", - "id": 583 - }, - { - "name": "minecraft:birch_stairs", - "id": 135 - }, - { - "name": "minecraft:birch_standing_sign", - "id": -186 - }, - { - "name": "minecraft:birch_trapdoor", - "id": -146 - }, - { - "name": "minecraft:birch_wall_sign", - "id": -187 - }, - { - "name": "minecraft:black_candle", - "id": -428 - }, - { - "name": "minecraft:black_candle_cake", - "id": -445 - }, - { - "name": "minecraft:black_dye", - "id": 396 - }, - { - "name": "minecraft:black_glazed_terracotta", - "id": 235 - }, - { - "name": "minecraft:black_wool", - "id": -554 - }, - { - "name": "minecraft:blackstone", - "id": -273 - }, - { - "name": "minecraft:blackstone_double_slab", - "id": -283 - }, - { - "name": "minecraft:blackstone_slab", - "id": -282 - }, - { - "name": "minecraft:blackstone_stairs", - "id": -276 - }, - { - "name": "minecraft:blackstone_wall", - "id": -277 - }, - { - "name": "minecraft:blade_pottery_shard", - "id": 665 - }, - { - "name": "minecraft:blast_furnace", - "id": -196 - }, - { - "name": "minecraft:blaze_powder", - "id": 430 - }, - { - "name": "minecraft:blaze_rod", - "id": 424 - }, - { - "name": "minecraft:blaze_spawn_egg", - "id": 457 - }, - { - "name": "minecraft:bleach", - "id": 602 - }, - { - "name": "minecraft:blue_candle", - "id": -424 - }, - { - "name": "minecraft:blue_candle_cake", - "id": -441 - }, - { - "name": "minecraft:blue_dye", - "id": 400 - }, - { - "name": "minecraft:blue_glazed_terracotta", - "id": 231 - }, - { - "name": "minecraft:blue_ice", - "id": -11 - }, - { - "name": "minecraft:blue_wool", - "id": -563 - }, - { - "name": "minecraft:boat", - "id": 704 - }, - { - "name": "minecraft:bone", - "id": 416 - }, - { - "name": "minecraft:bone_block", - "id": 216 - }, - { - "name": "minecraft:bone_meal", - "id": 412 - }, - { - "name": "minecraft:book", - "id": 388 - }, - { - "name": "minecraft:bookshelf", - "id": 47 - }, - { - "name": "minecraft:border_block", - "id": 212 - }, - { - "name": "minecraft:bordure_indented_banner_pattern", - "id": 592 - }, - { - "name": "minecraft:bow", - "id": 301 - }, - { - "name": "minecraft:bowl", - "id": 322 - }, - { - "name": "minecraft:bread", - "id": 261 - }, - { - "name": "minecraft:brewer_pottery_shard", - "id": 666 - }, - { - "name": "minecraft:brewing_stand", - "id": 432 - }, - { - "name": "minecraft:brick", - "id": 384 - }, - { - "name": "minecraft:brick_block", - "id": 45 - }, - { - "name": "minecraft:brick_stairs", - "id": 108 - }, - { - "name": "minecraft:brown_candle", - "id": -425 - }, - { - "name": "minecraft:brown_candle_cake", - "id": -442 - }, - { - "name": "minecraft:brown_dye", - "id": 399 - }, - { - "name": "minecraft:brown_glazed_terracotta", - "id": 232 - }, - { - "name": "minecraft:brown_mushroom", - "id": 39 - }, - { - "name": "minecraft:brown_mushroom_block", - "id": 99 - }, - { - "name": "minecraft:brown_wool", - "id": -555 - }, - { - "name": "minecraft:brush", - "id": 682 - }, - { - "name": "minecraft:bubble_column", - "id": -160 - }, - { - "name": "minecraft:bucket", - "id": 361 - }, - { - "name": "minecraft:budding_amethyst", - "id": -328 - }, - { - "name": "minecraft:burn_pottery_shard", - "id": 667 - }, - { - "name": "minecraft:cactus", - "id": 81 - }, - { - "name": "minecraft:cake", - "id": 418 - }, - { - "name": "minecraft:calcite", - "id": -326 - }, - { - "name": "minecraft:calibrated_sculk_sensor", - "id": -580 - }, - { - "name": "minecraft:camel_spawn_egg", - "id": 661 - }, - { - "name": "minecraft:camera", - "id": 599 - }, - { - "name": "minecraft:campfire", - "id": 595 - }, - { - "name": "minecraft:candle", - "id": -412 - }, - { - "name": "minecraft:candle_cake", - "id": -429 - }, - { - "name": "minecraft:carpet", - "id": 171 - }, - { - "name": "minecraft:carrot", - "id": 279 - }, - { - "name": "minecraft:carrot_on_a_stick", - "id": 523 - }, - { - "name": "minecraft:carrots", - "id": 141 - }, - { - "name": "minecraft:cartography_table", - "id": -200 - }, - { - "name": "minecraft:carved_pumpkin", - "id": -155 - }, - { - "name": "minecraft:cat_spawn_egg", - "id": 489 - }, - { - "name": "minecraft:cauldron", - "id": 433 - }, - { - "name": "minecraft:cave_spider_spawn_egg", - "id": 458 - }, - { - "name": "minecraft:cave_vines", - "id": -322 - }, - { - "name": "minecraft:cave_vines_body_with_berries", - "id": -375 - }, - { - "name": "minecraft:cave_vines_head_with_berries", - "id": -376 - }, - { - "name": "minecraft:chain", - "id": 625 - }, - { - "name": "minecraft:chain_command_block", - "id": 189 - }, - { - "name": "minecraft:chainmail_boots", - "id": 343 - }, - { - "name": "minecraft:chainmail_chestplate", - "id": 341 - }, - { - "name": "minecraft:chainmail_helmet", - "id": 340 - }, - { - "name": "minecraft:chainmail_leggings", - "id": 342 - }, - { - "name": "minecraft:charcoal", - "id": 304 - }, - { - "name": "minecraft:chemical_heat", - "id": 192 - }, - { - "name": "minecraft:chemistry_table", - "id": 238 - }, - { - "name": "minecraft:cherry_boat", - "id": 655 - }, - { - "name": "minecraft:cherry_button", - "id": -530 - }, - { - "name": "minecraft:cherry_chest_boat", - "id": 656 - }, - { - "name": "minecraft:cherry_door", - "id": -531 - }, - { - "name": "minecraft:cherry_double_slab", - "id": -540 - }, - { - "name": "minecraft:cherry_fence", - "id": -532 - }, - { - "name": "minecraft:cherry_fence_gate", - "id": -533 - }, - { - "name": "minecraft:cherry_hanging_sign", - "id": -534 - }, - { - "name": "minecraft:cherry_leaves", - "id": -548 - }, - { - "name": "minecraft:cherry_log", - "id": -536 - }, - { - "name": "minecraft:cherry_planks", - "id": -537 - }, - { - "name": "minecraft:cherry_pressure_plate", - "id": -538 - }, - { - "name": "minecraft:cherry_sapling", - "id": -547 - }, - { - "name": "minecraft:cherry_sign", - "id": 657 - }, - { - "name": "minecraft:cherry_slab", - "id": -539 - }, - { - "name": "minecraft:cherry_stairs", - "id": -541 - }, - { - "name": "minecraft:cherry_standing_sign", - "id": -542 - }, - { - "name": "minecraft:cherry_trapdoor", - "id": -543 - }, - { - "name": "minecraft:cherry_wall_sign", - "id": -544 - }, - { - "name": "minecraft:cherry_wood", - "id": -546 - }, - { - "name": "minecraft:chest", - "id": 54 - }, - { - "name": "minecraft:chest_boat", - "id": 651 - }, - { - "name": "minecraft:chest_minecart", - "id": 390 - }, - { - "name": "minecraft:chicken", - "id": 275 - }, - { - "name": "minecraft:chicken_spawn_egg", - "id": 436 - }, - { - "name": "minecraft:chiseled_bookshelf", - "id": -526 - }, - { - "name": "minecraft:chiseled_deepslate", - "id": -395 - }, - { - "name": "minecraft:chiseled_nether_bricks", - "id": -302 - }, - { - "name": "minecraft:chiseled_polished_blackstone", - "id": -279 - }, - { - "name": "minecraft:chorus_flower", - "id": 200 - }, - { - "name": "minecraft:chorus_fruit", - "id": 564 - }, - { - "name": "minecraft:chorus_plant", - "id": 240 - }, - { - "name": "minecraft:clay", - "id": 82 - }, - { - "name": "minecraft:clay_ball", - "id": 385 - }, - { - "name": "minecraft:client_request_placeholder_block", - "id": -465 - }, - { - "name": "minecraft:clock", - "id": 394 - }, - { - "name": "minecraft:coal", - "id": 303 - }, - { - "name": "minecraft:coal_block", - "id": 173 - }, - { - "name": "minecraft:coal_ore", - "id": 16 - }, - { - "name": "minecraft:coast_armor_trim_smithing_template", - "id": 686 - }, - { - "name": "minecraft:cobbled_deepslate", - "id": -379 - }, - { - "name": "minecraft:cobbled_deepslate_double_slab", - "id": -396 - }, - { - "name": "minecraft:cobbled_deepslate_slab", - "id": -380 - }, - { - "name": "minecraft:cobbled_deepslate_stairs", - "id": -381 - }, - { - "name": "minecraft:cobbled_deepslate_wall", - "id": -382 - }, - { - "name": "minecraft:cobblestone", - "id": 4 - }, - { - "name": "minecraft:cobblestone_wall", - "id": 139 - }, - { - "name": "minecraft:cocoa", - "id": 127 - }, - { - "name": "minecraft:cocoa_beans", - "id": 413 - }, - { - "name": "minecraft:cod", - "id": 264 - }, - { - "name": "minecraft:cod_bucket", - "id": 365 - }, - { - "name": "minecraft:cod_spawn_egg", - "id": 481 - }, - { - "name": "minecraft:colored_torch_bp", - "id": 204 - }, - { - "name": "minecraft:colored_torch_rg", - "id": 202 - }, - { - "name": "minecraft:command_block", - "id": 137 - }, - { - "name": "minecraft:command_block_minecart", - "id": 569 - }, - { - "name": "minecraft:comparator", - "id": 528 - }, - { - "name": "minecraft:compass", - "id": 392 - }, - { - "name": "minecraft:composter", - "id": -213 - }, - { - "name": "minecraft:compound", - "id": 600 - }, - { - "name": "minecraft:concrete", - "id": 236 - }, - { - "name": "minecraft:concrete_powder", - "id": 237 - }, - { - "name": "minecraft:conduit", - "id": -157 - }, - { - "name": "minecraft:cooked_beef", - "id": 274 - }, - { - "name": "minecraft:cooked_chicken", - "id": 276 - }, - { - "name": "minecraft:cooked_cod", - "id": 268 - }, - { - "name": "minecraft:cooked_mutton", - "id": 557 - }, - { - "name": "minecraft:cooked_porkchop", - "id": 263 - }, - { - "name": "minecraft:cooked_rabbit", - "id": 289 - }, - { - "name": "minecraft:cooked_salmon", - "id": 269 - }, - { - "name": "minecraft:cookie", - "id": 271 - }, - { - "name": "minecraft:copper_block", - "id": -340 - }, - { - "name": "minecraft:copper_ingot", - "id": 510 - }, - { - "name": "minecraft:copper_ore", - "id": -311 - }, - { - "name": "minecraft:coral", - "id": -131 - }, - { - "name": "minecraft:coral_block", - "id": -132 - }, - { - "name": "minecraft:coral_fan", - "id": -133 - }, - { - "name": "minecraft:coral_fan_dead", - "id": -134 - }, - { - "name": "minecraft:coral_fan_hang", - "id": -135 - }, - { - "name": "minecraft:coral_fan_hang2", - "id": -136 - }, - { - "name": "minecraft:coral_fan_hang3", - "id": -137 - }, - { - "name": "minecraft:cow_spawn_egg", - "id": 437 - }, - { - "name": "minecraft:cracked_deepslate_bricks", - "id": -410 - }, - { - "name": "minecraft:cracked_deepslate_tiles", - "id": -409 - }, - { - "name": "minecraft:cracked_nether_bricks", - "id": -303 - }, - { - "name": "minecraft:cracked_polished_blackstone_bricks", - "id": -280 - }, - { - "name": "minecraft:crafting_table", - "id": 58 - }, - { - "name": "minecraft:creeper_banner_pattern", - "id": 588 - }, - { - "name": "minecraft:creeper_spawn_egg", - "id": 442 - }, - { - "name": "minecraft:crimson_button", - "id": -260 - }, - { - "name": "minecraft:crimson_door", - "id": 622 - }, - { - "name": "minecraft:crimson_double_slab", - "id": -266 - }, - { - "name": "minecraft:crimson_fence", - "id": -256 - }, - { - "name": "minecraft:crimson_fence_gate", - "id": -258 - }, - { - "name": "minecraft:crimson_fungus", - "id": -228 - }, - { - "name": "minecraft:crimson_hanging_sign", - "id": -506 - }, - { - "name": "minecraft:crimson_hyphae", - "id": -299 - }, - { - "name": "minecraft:crimson_nylium", - "id": -232 - }, - { - "name": "minecraft:crimson_planks", - "id": -242 - }, - { - "name": "minecraft:crimson_pressure_plate", - "id": -262 - }, - { - "name": "minecraft:crimson_roots", - "id": -223 - }, - { - "name": "minecraft:crimson_sign", - "id": 620 - }, - { - "name": "minecraft:crimson_slab", - "id": -264 - }, - { - "name": "minecraft:crimson_stairs", - "id": -254 - }, - { - "name": "minecraft:crimson_standing_sign", - "id": -250 - }, - { - "name": "minecraft:crimson_stem", - "id": -225 - }, - { - "name": "minecraft:crimson_trapdoor", - "id": -246 - }, - { - "name": "minecraft:crimson_wall_sign", - "id": -252 - }, - { - "name": "minecraft:crossbow", - "id": 581 - }, - { - "name": "minecraft:crying_obsidian", - "id": -289 - }, - { - "name": "minecraft:cut_copper", - "id": -347 - }, - { - "name": "minecraft:cut_copper_slab", - "id": -361 - }, - { - "name": "minecraft:cut_copper_stairs", - "id": -354 - }, - { - "name": "minecraft:cyan_candle", - "id": -422 - }, - { - "name": "minecraft:cyan_candle_cake", - "id": -439 - }, - { - "name": "minecraft:cyan_dye", - "id": 402 - }, - { - "name": "minecraft:cyan_glazed_terracotta", - "id": 229 - }, - { - "name": "minecraft:cyan_wool", - "id": -561 - }, - { - "name": "minecraft:danger_pottery_shard", - "id": 668 - }, - { - "name": "minecraft:dark_oak_boat", - "id": 381 - }, - { - "name": "minecraft:dark_oak_button", - "id": -142 - }, - { - "name": "minecraft:dark_oak_chest_boat", - "id": 649 - }, - { - "name": "minecraft:dark_oak_door", - "id": 563 - }, - { - "name": "minecraft:dark_oak_fence", - "id": -577 - }, - { - "name": "minecraft:dark_oak_fence_gate", - "id": 186 - }, - { - "name": "minecraft:dark_oak_hanging_sign", - "id": -505 - }, - { - "name": "minecraft:dark_oak_log", - "id": -572 - }, - { - "name": "minecraft:dark_oak_pressure_plate", - "id": -152 - }, - { - "name": "minecraft:dark_oak_sign", - "id": 586 - }, - { - "name": "minecraft:dark_oak_stairs", - "id": 164 - }, - { - "name": "minecraft:dark_oak_trapdoor", - "id": -147 - }, - { - "name": "minecraft:dark_prismarine_stairs", - "id": -3 - }, - { - "name": "minecraft:darkoak_standing_sign", - "id": -192 - }, - { - "name": "minecraft:darkoak_wall_sign", - "id": -193 - }, - { - "name": "minecraft:daylight_detector", - "id": 151 - }, - { - "name": "minecraft:daylight_detector_inverted", - "id": 178 - }, - { - "name": "minecraft:deadbush", - "id": 32 - }, - { - "name": "minecraft:decorated_pot", - "id": -551 - }, - { - "name": "minecraft:deepslate", - "id": -378 - }, - { - "name": "minecraft:deepslate_brick_double_slab", - "id": -399 - }, - { - "name": "minecraft:deepslate_brick_slab", - "id": -392 - }, - { - "name": "minecraft:deepslate_brick_stairs", - "id": -393 - }, - { - "name": "minecraft:deepslate_brick_wall", - "id": -394 - }, - { - "name": "minecraft:deepslate_bricks", - "id": -391 - }, - { - "name": "minecraft:deepslate_coal_ore", - "id": -406 - }, - { - "name": "minecraft:deepslate_copper_ore", - "id": -408 - }, - { - "name": "minecraft:deepslate_diamond_ore", - "id": -405 - }, - { - "name": "minecraft:deepslate_emerald_ore", - "id": -407 - }, - { - "name": "minecraft:deepslate_gold_ore", - "id": -402 - }, - { - "name": "minecraft:deepslate_iron_ore", - "id": -401 - }, - { - "name": "minecraft:deepslate_lapis_ore", - "id": -400 - }, - { - "name": "minecraft:deepslate_redstone_ore", - "id": -403 - }, - { - "name": "minecraft:deepslate_tile_double_slab", - "id": -398 - }, - { - "name": "minecraft:deepslate_tile_slab", - "id": -388 - }, - { - "name": "minecraft:deepslate_tile_stairs", - "id": -389 - }, - { - "name": "minecraft:deepslate_tile_wall", - "id": -390 - }, - { - "name": "minecraft:deepslate_tiles", - "id": -387 - }, - { - "name": "minecraft:deny", - "id": 211 - }, - { - "name": "minecraft:detector_rail", - "id": 28 - }, - { - "name": "minecraft:diamond", - "id": 305 - }, - { - "name": "minecraft:diamond_axe", - "id": 320 - }, - { - "name": "minecraft:diamond_block", - "id": 57 - }, - { - "name": "minecraft:diamond_boots", - "id": 351 - }, - { - "name": "minecraft:diamond_chestplate", - "id": 349 - }, - { - "name": "minecraft:diamond_helmet", - "id": 348 - }, - { - "name": "minecraft:diamond_hoe", - "id": 333 - }, - { - "name": "minecraft:diamond_horse_armor", - "id": 539 - }, - { - "name": "minecraft:diamond_leggings", - "id": 350 - }, - { - "name": "minecraft:diamond_ore", - "id": 56 - }, - { - "name": "minecraft:diamond_pickaxe", - "id": 319 - }, - { - "name": "minecraft:diamond_shovel", - "id": 318 - }, - { - "name": "minecraft:diamond_sword", - "id": 317 - }, - { - "name": "minecraft:diorite_stairs", - "id": -170 - }, - { - "name": "minecraft:dirt", - "id": 3 - }, - { - "name": "minecraft:dirt_with_roots", - "id": -318 - }, - { - "name": "minecraft:disc_fragment_5", - "id": 643 - }, - { - "name": "minecraft:dispenser", - "id": 23 - }, - { - "name": "minecraft:dolphin_spawn_egg", - "id": 485 - }, - { - "name": "minecraft:donkey_spawn_egg", - "id": 466 - }, - { - "name": "minecraft:double_cut_copper_slab", - "id": -368 - }, - { - "name": "minecraft:double_plant", - "id": 175 - }, - { - "name": "minecraft:double_stone_block_slab", - "id": 43 - }, - { - "name": "minecraft:double_stone_block_slab2", - "id": 181 - }, - { - "name": "minecraft:double_stone_block_slab3", - "id": -167 - }, - { - "name": "minecraft:double_stone_block_slab4", - "id": -168 - }, - { - "name": "minecraft:double_wooden_slab", - "id": 157 - }, - { - "name": "minecraft:dragon_breath", - "id": 566 - }, - { - "name": "minecraft:dragon_egg", - "id": 122 - }, - { - "name": "minecraft:dried_kelp", - "id": 270 - }, - { - "name": "minecraft:dried_kelp_block", - "id": -139 - }, - { - "name": "minecraft:dripstone_block", - "id": -317 - }, - { - "name": "minecraft:dropper", - "id": 125 - }, - { - "name": "minecraft:drowned_spawn_egg", - "id": 484 - }, - { - "name": "minecraft:dune_armor_trim_smithing_template", - "id": 685 - }, - { - "name": "minecraft:dye", - "id": 705 - }, - { - "name": "minecraft:echo_shard", - "id": 653 - }, - { - "name": "minecraft:egg", - "id": 391 - }, - { - "name": "minecraft:elder_guardian_spawn_egg", - "id": 472 - }, - { - "name": "minecraft:element_0", - "id": 36 - }, - { - "name": "minecraft:element_1", - "id": -12 - }, - { - "name": "minecraft:element_10", - "id": -21 - }, - { - "name": "minecraft:element_100", - "id": -111 - }, - { - "name": "minecraft:element_101", - "id": -112 - }, - { - "name": "minecraft:element_102", - "id": -113 - }, - { - "name": "minecraft:element_103", - "id": -114 - }, - { - "name": "minecraft:element_104", - "id": -115 - }, - { - "name": "minecraft:element_105", - "id": -116 - }, - { - "name": "minecraft:element_106", - "id": -117 - }, - { - "name": "minecraft:element_107", - "id": -118 - }, - { - "name": "minecraft:element_108", - "id": -119 - }, - { - "name": "minecraft:element_109", - "id": -120 - }, - { - "name": "minecraft:element_11", - "id": -22 - }, - { - "name": "minecraft:element_110", - "id": -121 - }, - { - "name": "minecraft:element_111", - "id": -122 - }, - { - "name": "minecraft:element_112", - "id": -123 - }, - { - "name": "minecraft:element_113", - "id": -124 - }, - { - "name": "minecraft:element_114", - "id": -125 - }, - { - "name": "minecraft:element_115", - "id": -126 - }, - { - "name": "minecraft:element_116", - "id": -127 - }, - { - "name": "minecraft:element_117", - "id": -128 - }, - { - "name": "minecraft:element_118", - "id": -129 - }, - { - "name": "minecraft:element_12", - "id": -23 - }, - { - "name": "minecraft:element_13", - "id": -24 - }, - { - "name": "minecraft:element_14", - "id": -25 - }, - { - "name": "minecraft:element_15", - "id": -26 - }, - { - "name": "minecraft:element_16", - "id": -27 - }, - { - "name": "minecraft:element_17", - "id": -28 - }, - { - "name": "minecraft:element_18", - "id": -29 - }, - { - "name": "minecraft:element_19", - "id": -30 - }, - { - "name": "minecraft:element_2", - "id": -13 - }, - { - "name": "minecraft:element_20", - "id": -31 - }, - { - "name": "minecraft:element_21", - "id": -32 - }, - { - "name": "minecraft:element_22", - "id": -33 - }, - { - "name": "minecraft:element_23", - "id": -34 - }, - { - "name": "minecraft:element_24", - "id": -35 - }, - { - "name": "minecraft:element_25", - "id": -36 - }, - { - "name": "minecraft:element_26", - "id": -37 - }, - { - "name": "minecraft:element_27", - "id": -38 - }, - { - "name": "minecraft:element_28", - "id": -39 - }, - { - "name": "minecraft:element_29", - "id": -40 - }, - { - "name": "minecraft:element_3", - "id": -14 - }, - { - "name": "minecraft:element_30", - "id": -41 - }, - { - "name": "minecraft:element_31", - "id": -42 - }, - { - "name": "minecraft:element_32", - "id": -43 - }, - { - "name": "minecraft:element_33", - "id": -44 - }, - { - "name": "minecraft:element_34", - "id": -45 - }, - { - "name": "minecraft:element_35", - "id": -46 - }, - { - "name": "minecraft:element_36", - "id": -47 - }, - { - "name": "minecraft:element_37", - "id": -48 - }, - { - "name": "minecraft:element_38", - "id": -49 - }, - { - "name": "minecraft:element_39", - "id": -50 - }, - { - "name": "minecraft:element_4", - "id": -15 - }, - { - "name": "minecraft:element_40", - "id": -51 - }, - { - "name": "minecraft:element_41", - "id": -52 - }, - { - "name": "minecraft:element_42", - "id": -53 - }, - { - "name": "minecraft:element_43", - "id": -54 - }, - { - "name": "minecraft:element_44", - "id": -55 - }, - { - "name": "minecraft:element_45", - "id": -56 - }, - { - "name": "minecraft:element_46", - "id": -57 - }, - { - "name": "minecraft:element_47", - "id": -58 - }, - { - "name": "minecraft:element_48", - "id": -59 - }, - { - "name": "minecraft:element_49", - "id": -60 - }, - { - "name": "minecraft:element_5", - "id": -16 - }, - { - "name": "minecraft:element_50", - "id": -61 - }, - { - "name": "minecraft:element_51", - "id": -62 - }, - { - "name": "minecraft:element_52", - "id": -63 - }, - { - "name": "minecraft:element_53", - "id": -64 - }, - { - "name": "minecraft:element_54", - "id": -65 - }, - { - "name": "minecraft:element_55", - "id": -66 - }, - { - "name": "minecraft:element_56", - "id": -67 - }, - { - "name": "minecraft:element_57", - "id": -68 - }, - { - "name": "minecraft:element_58", - "id": -69 - }, - { - "name": "minecraft:element_59", - "id": -70 - }, - { - "name": "minecraft:element_6", - "id": -17 - }, - { - "name": "minecraft:element_60", - "id": -71 - }, - { - "name": "minecraft:element_61", - "id": -72 - }, - { - "name": "minecraft:element_62", - "id": -73 - }, - { - "name": "minecraft:element_63", - "id": -74 - }, - { - "name": "minecraft:element_64", - "id": -75 - }, - { - "name": "minecraft:element_65", - "id": -76 - }, - { - "name": "minecraft:element_66", - "id": -77 - }, - { - "name": "minecraft:element_67", - "id": -78 - }, - { - "name": "minecraft:element_68", - "id": -79 - }, - { - "name": "minecraft:element_69", - "id": -80 - }, - { - "name": "minecraft:element_7", - "id": -18 - }, - { - "name": "minecraft:element_70", - "id": -81 - }, - { - "name": "minecraft:element_71", - "id": -82 - }, - { - "name": "minecraft:element_72", - "id": -83 - }, - { - "name": "minecraft:element_73", - "id": -84 - }, - { - "name": "minecraft:element_74", - "id": -85 - }, - { - "name": "minecraft:element_75", - "id": -86 - }, - { - "name": "minecraft:element_76", - "id": -87 - }, - { - "name": "minecraft:element_77", - "id": -88 - }, - { - "name": "minecraft:element_78", - "id": -89 - }, - { - "name": "minecraft:element_79", - "id": -90 - }, - { - "name": "minecraft:element_8", - "id": -19 - }, - { - "name": "minecraft:element_80", - "id": -91 - }, - { - "name": "minecraft:element_81", - "id": -92 - }, - { - "name": "minecraft:element_82", - "id": -93 - }, - { - "name": "minecraft:element_83", - "id": -94 - }, - { - "name": "minecraft:element_84", - "id": -95 - }, - { - "name": "minecraft:element_85", - "id": -96 - }, - { - "name": "minecraft:element_86", - "id": -97 - }, - { - "name": "minecraft:element_87", - "id": -98 - }, - { - "name": "minecraft:element_88", - "id": -99 - }, - { - "name": "minecraft:element_89", - "id": -100 - }, - { - "name": "minecraft:element_9", - "id": -20 - }, - { - "name": "minecraft:element_90", - "id": -101 - }, - { - "name": "minecraft:element_91", - "id": -102 - }, - { - "name": "minecraft:element_92", - "id": -103 - }, - { - "name": "minecraft:element_93", - "id": -104 - }, - { - "name": "minecraft:element_94", - "id": -105 - }, - { - "name": "minecraft:element_95", - "id": -106 - }, - { - "name": "minecraft:element_96", - "id": -107 - }, - { - "name": "minecraft:element_97", - "id": -108 - }, - { - "name": "minecraft:element_98", - "id": -109 - }, - { - "name": "minecraft:element_99", - "id": -110 - }, - { - "name": "minecraft:elytra", - "id": 570 - }, - { - "name": "minecraft:emerald", - "id": 518 - }, - { - "name": "minecraft:emerald_block", - "id": 133 - }, - { - "name": "minecraft:emerald_ore", - "id": 129 - }, - { - "name": "minecraft:empty_map", - "id": 521 - }, - { - "name": "minecraft:enchanted_book", - "id": 527 - }, - { - "name": "minecraft:enchanted_golden_apple", - "id": 259 - }, - { - "name": "minecraft:enchanting_table", - "id": 116 - }, - { - "name": "minecraft:end_brick_stairs", - "id": -178 - }, - { - "name": "minecraft:end_bricks", - "id": 206 - }, - { - "name": "minecraft:end_crystal", - "id": 708 - }, - { - "name": "minecraft:end_gateway", - "id": 209 - }, - { - "name": "minecraft:end_portal", - "id": 119 - }, - { - "name": "minecraft:end_portal_frame", - "id": 120 - }, - { - "name": "minecraft:end_rod", - "id": 208 - }, - { - "name": "minecraft:end_stone", - "id": 121 - }, - { - "name": "minecraft:ender_chest", - "id": 130 - }, - { - "name": "minecraft:ender_dragon_spawn_egg", - "id": 507 - }, - { - "name": "minecraft:ender_eye", - "id": 434 - }, - { - "name": "minecraft:ender_pearl", - "id": 423 - }, - { - "name": "minecraft:enderman_spawn_egg", - "id": 443 - }, - { - "name": "minecraft:endermite_spawn_egg", - "id": 461 - }, - { - "name": "minecraft:evoker_spawn_egg", - "id": 476 - }, - { - "name": "minecraft:experience_bottle", - "id": 514 - }, - { - "name": "minecraft:explorer_pottery_shard", - "id": 669 - }, - { - "name": "minecraft:exposed_copper", - "id": -341 - }, - { - "name": "minecraft:exposed_cut_copper", - "id": -348 - }, - { - "name": "minecraft:exposed_cut_copper_slab", - "id": -362 - }, - { - "name": "minecraft:exposed_cut_copper_stairs", - "id": -355 - }, - { - "name": "minecraft:exposed_double_cut_copper_slab", - "id": -369 - }, - { - "name": "minecraft:eye_armor_trim_smithing_template", - "id": 689 - }, - { - "name": "minecraft:farmland", - "id": 60 - }, - { - "name": "minecraft:feather", - "id": 328 - }, - { - "name": "minecraft:fence", - "id": 702 - }, - { - "name": "minecraft:fence_gate", - "id": 107 - }, - { - "name": "minecraft:fermented_spider_eye", - "id": 429 - }, - { - "name": "minecraft:field_masoned_banner_pattern", - "id": 591 - }, - { - "name": "minecraft:filled_map", - "id": 421 - }, - { - "name": "minecraft:fire", - "id": 51 - }, - { - "name": "minecraft:fire_charge", - "id": 515 - }, - { - "name": "minecraft:firework_rocket", - "id": 525 - }, - { - "name": "minecraft:firework_star", - "id": 526 - }, - { - "name": "minecraft:fishing_rod", - "id": 393 - }, - { - "name": "minecraft:fletching_table", - "id": -201 - }, - { - "name": "minecraft:flint", - "id": 357 - }, - { - "name": "minecraft:flint_and_steel", - "id": 300 - }, - { - "name": "minecraft:flower_banner_pattern", - "id": 587 - }, - { - "name": "minecraft:flower_pot", - "id": 520 - }, - { - "name": "minecraft:flowering_azalea", - "id": -338 - }, - { - "name": "minecraft:flowing_lava", - "id": 10 - }, - { - "name": "minecraft:flowing_water", - "id": 8 - }, - { - "name": "minecraft:fox_spawn_egg", - "id": 491 - }, - { - "name": "minecraft:frame", - "id": 519 - }, - { - "name": "minecraft:friend_pottery_shard", - "id": 670 - }, - { - "name": "minecraft:frog_spawn", - "id": -468 - }, - { - "name": "minecraft:frog_spawn_egg", - "id": 634 - }, - { - "name": "minecraft:frosted_ice", - "id": 207 - }, - { - "name": "minecraft:furnace", - "id": 61 - }, - { - "name": "minecraft:ghast_spawn_egg", - "id": 455 - }, - { - "name": "minecraft:ghast_tear", - "id": 425 - }, - { - "name": "minecraft:gilded_blackstone", - "id": -281 - }, - { - "name": "minecraft:glass", - "id": 20 - }, - { - "name": "minecraft:glass_bottle", - "id": 428 - }, - { - "name": "minecraft:glass_pane", - "id": 102 - }, - { - "name": "minecraft:glistering_melon_slice", - "id": 435 - }, - { - "name": "minecraft:globe_banner_pattern", - "id": 594 - }, - { - "name": "minecraft:glow_berries", - "id": 709 - }, - { - "name": "minecraft:glow_frame", - "id": 629 - }, - { - "name": "minecraft:glow_ink_sac", - "id": 509 - }, - { - "name": "minecraft:glow_lichen", - "id": -411 - }, - { - "name": "minecraft:glow_squid_spawn_egg", - "id": 504 - }, - { - "name": "minecraft:glow_stick", - "id": 607 - }, - { - "name": "minecraft:glowingobsidian", - "id": 246 - }, - { - "name": "minecraft:glowstone", - "id": 89 - }, - { - "name": "minecraft:glowstone_dust", - "id": 395 - }, - { - "name": "minecraft:goat_horn", - "id": 633 - }, - { - "name": "minecraft:goat_spawn_egg", - "id": 503 - }, - { - "name": "minecraft:gold_block", - "id": 41 - }, - { - "name": "minecraft:gold_ingot", - "id": 307 - }, - { - "name": "minecraft:gold_nugget", - "id": 426 - }, - { - "name": "minecraft:gold_ore", - "id": 14 - }, - { - "name": "minecraft:golden_apple", - "id": 258 - }, - { - "name": "minecraft:golden_axe", - "id": 326 - }, - { - "name": "minecraft:golden_boots", - "id": 355 - }, - { - "name": "minecraft:golden_carrot", - "id": 283 - }, - { - "name": "minecraft:golden_chestplate", - "id": 353 - }, - { - "name": "minecraft:golden_helmet", - "id": 352 - }, - { - "name": "minecraft:golden_hoe", - "id": 334 - }, - { - "name": "minecraft:golden_horse_armor", - "id": 538 - }, - { - "name": "minecraft:golden_leggings", - "id": 354 - }, - { - "name": "minecraft:golden_pickaxe", - "id": 325 - }, - { - "name": "minecraft:golden_rail", - "id": 27 - }, - { - "name": "minecraft:golden_shovel", - "id": 324 - }, - { - "name": "minecraft:golden_sword", - "id": 323 - }, - { - "name": "minecraft:granite_stairs", - "id": -169 - }, - { - "name": "minecraft:grass", - "id": 2 - }, - { - "name": "minecraft:grass_path", - "id": 198 - }, - { - "name": "minecraft:gravel", - "id": 13 - }, - { - "name": "minecraft:gray_candle", - "id": -420 - }, - { - "name": "minecraft:gray_candle_cake", - "id": -437 - }, - { - "name": "minecraft:gray_dye", - "id": 404 - }, - { - "name": "minecraft:gray_glazed_terracotta", - "id": 227 - }, - { - "name": "minecraft:gray_wool", - "id": -553 - }, - { - "name": "minecraft:green_candle", - "id": -426 - }, - { - "name": "minecraft:green_candle_cake", - "id": -443 - }, - { - "name": "minecraft:green_dye", - "id": 398 - }, - { - "name": "minecraft:green_glazed_terracotta", - "id": 233 - }, - { - "name": "minecraft:green_wool", - "id": -560 - }, - { - "name": "minecraft:grindstone", - "id": -195 - }, - { - "name": "minecraft:guardian_spawn_egg", - "id": 462 - }, - { - "name": "minecraft:gunpowder", - "id": 329 - }, - { - "name": "minecraft:hanging_roots", - "id": -319 - }, - { - "name": "minecraft:hard_glass", - "id": 253 - }, - { - "name": "minecraft:hard_glass_pane", - "id": 190 - }, - { - "name": "minecraft:hard_stained_glass", - "id": 254 - }, - { - "name": "minecraft:hard_stained_glass_pane", - "id": 191 - }, - { - "name": "minecraft:hardened_clay", - "id": 172 - }, - { - "name": "minecraft:hay_block", - "id": 170 - }, - { - "name": "minecraft:heart_of_the_sea", - "id": 577 - }, - { - "name": "minecraft:heart_pottery_shard", - "id": 671 - }, - { - "name": "minecraft:heartbreak_pottery_shard", - "id": 672 - }, - { - "name": "minecraft:heavy_weighted_pressure_plate", - "id": 148 - }, - { - "name": "minecraft:hoglin_spawn_egg", - "id": 497 - }, - { - "name": "minecraft:honey_block", - "id": -220 - }, - { - "name": "minecraft:honey_bottle", - "id": 598 - }, - { - "name": "minecraft:honeycomb", - "id": 597 - }, - { - "name": "minecraft:honeycomb_block", - "id": -221 - }, - { - "name": "minecraft:hopper", - "id": 533 - }, - { - "name": "minecraft:hopper_minecart", - "id": 532 - }, - { - "name": "minecraft:horse_spawn_egg", - "id": 459 - }, - { - "name": "minecraft:host_armor_trim_smithing_template", - "id": 699 - }, - { - "name": "minecraft:howl_pottery_shard", - "id": 673 - }, - { - "name": "minecraft:husk_spawn_egg", - "id": 464 - }, - { - "name": "minecraft:ice", - "id": 79 - }, - { - "name": "minecraft:ice_bomb", - "id": 601 - }, - { - "name": "minecraft:infested_deepslate", - "id": -454 - }, - { - "name": "minecraft:info_update", - "id": 248 - }, - { - "name": "minecraft:info_update2", - "id": 249 - }, - { - "name": "minecraft:ink_sac", - "id": 414 - }, - { - "name": "minecraft:invisible_bedrock", - "id": 95 - }, - { - "name": "minecraft:iron_axe", - "id": 299 - }, - { - "name": "minecraft:iron_bars", - "id": 101 - }, - { - "name": "minecraft:iron_block", - "id": 42 - }, - { - "name": "minecraft:iron_boots", - "id": 347 - }, - { - "name": "minecraft:iron_chestplate", - "id": 345 - }, - { - "name": "minecraft:iron_door", - "id": 373 - }, - { - "name": "minecraft:iron_golem_spawn_egg", - "id": 505 - }, - { - "name": "minecraft:iron_helmet", - "id": 344 - }, - { - "name": "minecraft:iron_hoe", - "id": 332 - }, - { - "name": "minecraft:iron_horse_armor", - "id": 537 - }, - { - "name": "minecraft:iron_ingot", - "id": 306 - }, - { - "name": "minecraft:iron_leggings", - "id": 346 - }, - { - "name": "minecraft:iron_nugget", - "id": 575 - }, - { - "name": "minecraft:iron_ore", - "id": 15 - }, - { - "name": "minecraft:iron_pickaxe", - "id": 298 - }, - { - "name": "minecraft:iron_shovel", - "id": 297 - }, - { - "name": "minecraft:iron_sword", - "id": 308 - }, - { - "name": "minecraft:iron_trapdoor", - "id": 167 - }, - { - "name": "minecraft:item.acacia_door", - "id": 196 - }, - { - "name": "minecraft:item.bed", - "id": 26 - }, - { - "name": "minecraft:item.beetroot", - "id": 244 - }, - { - "name": "minecraft:item.birch_door", - "id": 194 - }, - { - "name": "minecraft:item.brewing_stand", - "id": 117 - }, - { - "name": "minecraft:item.cake", - "id": 92 - }, - { - "name": "minecraft:item.camera", - "id": 242 - }, - { - "name": "minecraft:item.campfire", - "id": -209 - }, - { - "name": "minecraft:item.cauldron", - "id": 118 - }, - { - "name": "minecraft:item.chain", - "id": -286 - }, - { - "name": "minecraft:item.crimson_door", - "id": -244 - }, - { - "name": "minecraft:item.dark_oak_door", - "id": 197 - }, - { - "name": "minecraft:item.flower_pot", - "id": 140 - }, - { - "name": "minecraft:item.frame", - "id": 199 - }, - { - "name": "minecraft:item.glow_frame", - "id": -339 - }, - { - "name": "minecraft:item.hopper", - "id": 154 - }, - { - "name": "minecraft:item.iron_door", - "id": 71 - }, - { - "name": "minecraft:item.jungle_door", - "id": 195 - }, - { - "name": "minecraft:item.kelp", - "id": -138 - }, - { - "name": "minecraft:item.mangrove_door", - "id": -493 - }, - { - "name": "minecraft:item.nether_sprouts", - "id": -238 - }, - { - "name": "minecraft:item.nether_wart", - "id": 115 - }, - { - "name": "minecraft:item.reeds", - "id": 83 - }, - { - "name": "minecraft:item.skull", - "id": 144 - }, - { - "name": "minecraft:item.soul_campfire", - "id": -290 - }, - { - "name": "minecraft:item.spruce_door", - "id": 193 - }, - { - "name": "minecraft:item.warped_door", - "id": -245 - }, - { - "name": "minecraft:item.wheat", - "id": 59 - }, - { - "name": "minecraft:item.wooden_door", - "id": 64 - }, - { - "name": "minecraft:jigsaw", - "id": -211 - }, - { - "name": "minecraft:jukebox", - "id": 84 - }, - { - "name": "minecraft:jungle_boat", - "id": 378 - }, - { - "name": "minecraft:jungle_button", - "id": -143 - }, - { - "name": "minecraft:jungle_chest_boat", - "id": 646 - }, - { - "name": "minecraft:jungle_door", - "id": 561 - }, - { - "name": "minecraft:jungle_fence", - "id": -578 - }, - { - "name": "minecraft:jungle_fence_gate", - "id": 185 - }, - { - "name": "minecraft:jungle_hanging_sign", - "id": -503 - }, - { - "name": "minecraft:jungle_log", - "id": -571 - }, - { - "name": "minecraft:jungle_pressure_plate", - "id": -153 - }, - { - "name": "minecraft:jungle_sign", - "id": 584 - }, - { - "name": "minecraft:jungle_stairs", - "id": 136 - }, - { - "name": "minecraft:jungle_standing_sign", - "id": -188 - }, - { - "name": "minecraft:jungle_trapdoor", - "id": -148 - }, - { - "name": "minecraft:jungle_wall_sign", - "id": -189 - }, - { - "name": "minecraft:kelp", - "id": 383 - }, - { - "name": "minecraft:ladder", - "id": 65 - }, - { - "name": "minecraft:lantern", - "id": -208 - }, - { - "name": "minecraft:lapis_block", - "id": 22 - }, - { - "name": "minecraft:lapis_lazuli", - "id": 415 - }, - { - "name": "minecraft:lapis_ore", - "id": 21 - }, - { - "name": "minecraft:large_amethyst_bud", - "id": -330 - }, - { - "name": "minecraft:lava", - "id": 11 - }, - { - "name": "minecraft:lava_bucket", - "id": 364 - }, - { - "name": "minecraft:lava_cauldron", - "id": -210 - }, - { - "name": "minecraft:lead", - "id": 553 - }, - { - "name": "minecraft:leather", - "id": 382 - }, - { - "name": "minecraft:leather_boots", - "id": 339 - }, - { - "name": "minecraft:leather_chestplate", - "id": 337 - }, - { - "name": "minecraft:leather_helmet", - "id": 336 - }, - { - "name": "minecraft:leather_horse_armor", - "id": 536 - }, - { - "name": "minecraft:leather_leggings", - "id": 338 - }, - { - "name": "minecraft:leaves", - "id": 18 - }, - { - "name": "minecraft:leaves2", - "id": 161 - }, - { - "name": "minecraft:lectern", - "id": -194 - }, - { - "name": "minecraft:lever", - "id": 69 - }, - { - "name": "minecraft:light_block", - "id": -215 - }, - { - "name": "minecraft:light_blue_candle", - "id": -416 - }, - { - "name": "minecraft:light_blue_candle_cake", - "id": -433 - }, - { - "name": "minecraft:light_blue_dye", - "id": 408 - }, - { - "name": "minecraft:light_blue_glazed_terracotta", - "id": 223 - }, - { - "name": "minecraft:light_blue_wool", - "id": -562 - }, - { - "name": "minecraft:light_gray_candle", - "id": -421 - }, - { - "name": "minecraft:light_gray_candle_cake", - "id": -438 - }, - { - "name": "minecraft:light_gray_dye", - "id": 403 - }, - { - "name": "minecraft:light_gray_wool", - "id": -552 - }, - { - "name": "minecraft:light_weighted_pressure_plate", - "id": 147 - }, - { - "name": "minecraft:lightning_rod", - "id": -312 - }, - { - "name": "minecraft:lime_candle", - "id": -418 - }, - { - "name": "minecraft:lime_candle_cake", - "id": -435 - }, - { - "name": "minecraft:lime_dye", - "id": 406 - }, - { - "name": "minecraft:lime_glazed_terracotta", - "id": 225 - }, - { - "name": "minecraft:lime_wool", - "id": -559 - }, - { - "name": "minecraft:lingering_potion", - "id": 568 - }, - { - "name": "minecraft:lit_blast_furnace", - "id": -214 - }, - { - "name": "minecraft:lit_deepslate_redstone_ore", - "id": -404 - }, - { - "name": "minecraft:lit_furnace", - "id": 62 - }, - { - "name": "minecraft:lit_pumpkin", - "id": 91 - }, - { - "name": "minecraft:lit_redstone_lamp", - "id": 124 - }, - { - "name": "minecraft:lit_redstone_ore", - "id": 74 - }, - { - "name": "minecraft:lit_smoker", - "id": -199 - }, - { - "name": "minecraft:llama_spawn_egg", - "id": 474 - }, - { - "name": "minecraft:lodestone", - "id": -222 - }, - { - "name": "minecraft:lodestone_compass", - "id": 608 - }, - { - "name": "minecraft:log", - "id": 701 - }, - { - "name": "minecraft:log2", - "id": 703 - }, - { - "name": "minecraft:loom", - "id": -204 - }, - { - "name": "minecraft:magenta_candle", - "id": -415 - }, - { - "name": "minecraft:magenta_candle_cake", - "id": -432 - }, - { - "name": "minecraft:magenta_dye", - "id": 409 - }, - { - "name": "minecraft:magenta_glazed_terracotta", - "id": 222 - }, - { - "name": "minecraft:magenta_wool", - "id": -565 - }, - { - "name": "minecraft:magma", - "id": 213 - }, - { - "name": "minecraft:magma_cream", - "id": 431 - }, - { - "name": "minecraft:magma_cube_spawn_egg", - "id": 456 - }, - { - "name": "minecraft:mangrove_boat", - "id": 641 - }, - { - "name": "minecraft:mangrove_button", - "id": -487 - }, - { - "name": "minecraft:mangrove_chest_boat", - "id": 650 - }, - { - "name": "minecraft:mangrove_door", - "id": 639 - }, - { - "name": "minecraft:mangrove_double_slab", - "id": -499 - }, - { - "name": "minecraft:mangrove_fence", - "id": -491 - }, - { - "name": "minecraft:mangrove_fence_gate", - "id": -492 - }, - { - "name": "minecraft:mangrove_hanging_sign", - "id": -508 - }, - { - "name": "minecraft:mangrove_leaves", - "id": -472 - }, - { - "name": "minecraft:mangrove_log", - "id": -484 - }, - { - "name": "minecraft:mangrove_planks", - "id": -486 - }, - { - "name": "minecraft:mangrove_pressure_plate", - "id": -490 - }, - { - "name": "minecraft:mangrove_propagule", - "id": -474 - }, - { - "name": "minecraft:mangrove_roots", - "id": -482 - }, - { - "name": "minecraft:mangrove_sign", - "id": 640 - }, - { - "name": "minecraft:mangrove_slab", - "id": -489 - }, - { - "name": "minecraft:mangrove_stairs", - "id": -488 - }, - { - "name": "minecraft:mangrove_standing_sign", - "id": -494 - }, - { - "name": "minecraft:mangrove_trapdoor", - "id": -496 - }, - { - "name": "minecraft:mangrove_wall_sign", - "id": -495 - }, - { - "name": "minecraft:mangrove_wood", - "id": -497 - }, - { - "name": "minecraft:medicine", - "id": 605 - }, - { - "name": "minecraft:medium_amethyst_bud", - "id": -331 - }, - { - "name": "minecraft:melon_block", - "id": 103 - }, - { - "name": "minecraft:melon_seeds", - "id": 293 - }, - { - "name": "minecraft:melon_slice", - "id": 272 - }, - { - "name": "minecraft:melon_stem", - "id": 105 - }, - { - "name": "minecraft:milk_bucket", - "id": 362 - }, - { - "name": "minecraft:minecart", - "id": 371 - }, - { - "name": "minecraft:miner_pottery_shard", - "id": 674 - }, - { - "name": "minecraft:mob_spawner", - "id": 52 - }, - { - "name": "minecraft:mojang_banner_pattern", - "id": 590 - }, - { - "name": "minecraft:monster_egg", - "id": 97 - }, - { - "name": "minecraft:mooshroom_spawn_egg", - "id": 441 - }, - { - "name": "minecraft:moss_block", - "id": -320 - }, - { - "name": "minecraft:moss_carpet", - "id": -335 - }, - { - "name": "minecraft:mossy_cobblestone", - "id": 48 - }, - { - "name": "minecraft:mossy_cobblestone_stairs", - "id": -179 - }, - { - "name": "minecraft:mossy_stone_brick_stairs", - "id": -175 - }, - { - "name": "minecraft:mourner_pottery_shard", - "id": 675 - }, - { - "name": "minecraft:moving_block", - "id": 250 - }, - { - "name": "minecraft:mud", - "id": -473 - }, - { - "name": "minecraft:mud_brick_double_slab", - "id": -479 - }, - { - "name": "minecraft:mud_brick_slab", - "id": -478 - }, - { - "name": "minecraft:mud_brick_stairs", - "id": -480 - }, - { - "name": "minecraft:mud_brick_wall", - "id": -481 - }, - { - "name": "minecraft:mud_bricks", - "id": -475 - }, - { - "name": "minecraft:muddy_mangrove_roots", - "id": -483 - }, - { - "name": "minecraft:mule_spawn_egg", - "id": 467 - }, - { - "name": "minecraft:mushroom_stew", - "id": 260 - }, - { - "name": "minecraft:music_disc_11", - "id": 550 - }, - { - "name": "minecraft:music_disc_13", - "id": 540 - }, - { - "name": "minecraft:music_disc_5", - "id": 642 - }, - { - "name": "minecraft:music_disc_blocks", - "id": 542 - }, - { - "name": "minecraft:music_disc_cat", - "id": 541 - }, - { - "name": "minecraft:music_disc_chirp", - "id": 543 - }, - { - "name": "minecraft:music_disc_far", - "id": 544 - }, - { - "name": "minecraft:music_disc_mall", - "id": 545 - }, - { - "name": "minecraft:music_disc_mellohi", - "id": 546 - }, - { - "name": "minecraft:music_disc_otherside", - "id": 632 - }, - { - "name": "minecraft:music_disc_pigstep", - "id": 626 - }, - { - "name": "minecraft:music_disc_stal", - "id": 547 - }, - { - "name": "minecraft:music_disc_strad", - "id": 548 - }, - { - "name": "minecraft:music_disc_wait", - "id": 551 - }, - { - "name": "minecraft:music_disc_ward", - "id": 549 - }, - { - "name": "minecraft:mutton", - "id": 556 - }, - { - "name": "minecraft:mycelium", - "id": 110 - }, - { - "name": "minecraft:name_tag", - "id": 554 - }, - { - "name": "minecraft:nautilus_shell", - "id": 576 - }, - { - "name": "minecraft:nether_brick", - "id": 112 - }, - { - "name": "minecraft:nether_brick_fence", - "id": 113 - }, - { - "name": "minecraft:nether_brick_stairs", - "id": 114 - }, - { - "name": "minecraft:nether_gold_ore", - "id": -288 - }, - { - "name": "minecraft:nether_sprouts", - "id": 627 - }, - { - "name": "minecraft:nether_star", - "id": 524 - }, - { - "name": "minecraft:nether_wart", - "id": 294 - }, - { - "name": "minecraft:nether_wart_block", - "id": 214 - }, - { - "name": "minecraft:netherbrick", - "id": 529 - }, - { - "name": "minecraft:netherite_axe", - "id": 612 - }, - { - "name": "minecraft:netherite_block", - "id": -270 - }, - { - "name": "minecraft:netherite_boots", - "id": 618 - }, - { - "name": "minecraft:netherite_chestplate", - "id": 616 - }, - { - "name": "minecraft:netherite_helmet", - "id": 615 - }, - { - "name": "minecraft:netherite_hoe", - "id": 613 - }, - { - "name": "minecraft:netherite_ingot", - "id": 614 - }, - { - "name": "minecraft:netherite_leggings", - "id": 617 - }, - { - "name": "minecraft:netherite_pickaxe", - "id": 611 - }, - { - "name": "minecraft:netherite_scrap", - "id": 619 - }, - { - "name": "minecraft:netherite_shovel", - "id": 610 - }, - { - "name": "minecraft:netherite_sword", - "id": 609 - }, - { - "name": "minecraft:netherite_upgrade_smithing_template", - "id": 683 - }, - { - "name": "minecraft:netherrack", - "id": 87 - }, - { - "name": "minecraft:netherreactor", - "id": 247 - }, - { - "name": "minecraft:normal_stone_stairs", - "id": -180 - }, - { - "name": "minecraft:noteblock", - "id": 25 - }, - { - "name": "minecraft:npc_spawn_egg", - "id": 471 - }, - { - "name": "minecraft:oak_boat", - "id": 376 - }, - { - "name": "minecraft:oak_chest_boat", - "id": 644 - }, - { - "name": "minecraft:oak_fence", - "id": 85 - }, - { - "name": "minecraft:oak_hanging_sign", - "id": -500 - }, - { - "name": "minecraft:oak_log", - "id": 17 - }, - { - "name": "minecraft:oak_sign", - "id": 359 - }, - { - "name": "minecraft:oak_stairs", - "id": 53 - }, - { - "name": "minecraft:observer", - "id": 251 - }, - { - "name": "minecraft:obsidian", - "id": 49 - }, - { - "name": "minecraft:ocelot_spawn_egg", - "id": 452 - }, - { - "name": "minecraft:ochre_froglight", - "id": -471 - }, - { - "name": "minecraft:orange_candle", - "id": -414 - }, - { - "name": "minecraft:orange_candle_cake", - "id": -431 - }, - { - "name": "minecraft:orange_dye", - "id": 410 - }, - { - "name": "minecraft:orange_glazed_terracotta", - "id": 221 - }, - { - "name": "minecraft:orange_wool", - "id": -557 - }, - { - "name": "minecraft:oxidized_copper", - "id": -343 - }, - { - "name": "minecraft:oxidized_cut_copper", - "id": -350 - }, - { - "name": "minecraft:oxidized_cut_copper_slab", - "id": -364 - }, - { - "name": "minecraft:oxidized_cut_copper_stairs", - "id": -357 - }, - { - "name": "minecraft:oxidized_double_cut_copper_slab", - "id": -371 - }, - { - "name": "minecraft:packed_ice", - "id": 174 - }, - { - "name": "minecraft:packed_mud", - "id": -477 - }, - { - "name": "minecraft:painting", - "id": 358 - }, - { - "name": "minecraft:panda_spawn_egg", - "id": 490 - }, - { - "name": "minecraft:paper", - "id": 387 - }, - { - "name": "minecraft:parrot_spawn_egg", - "id": 479 - }, - { - "name": "minecraft:pearlescent_froglight", - "id": -469 - }, - { - "name": "minecraft:phantom_membrane", - "id": 580 - }, - { - "name": "minecraft:phantom_spawn_egg", - "id": 487 - }, - { - "name": "minecraft:pig_spawn_egg", - "id": 438 - }, - { - "name": "minecraft:piglin_banner_pattern", - "id": 593 - }, - { - "name": "minecraft:piglin_brute_spawn_egg", - "id": 500 - }, - { - "name": "minecraft:piglin_spawn_egg", - "id": 498 - }, - { - "name": "minecraft:pillager_spawn_egg", - "id": 492 - }, - { - "name": "minecraft:pink_candle", - "id": -419 - }, - { - "name": "minecraft:pink_candle_cake", - "id": -436 - }, - { - "name": "minecraft:pink_dye", - "id": 405 - }, - { - "name": "minecraft:pink_glazed_terracotta", - "id": 226 - }, - { - "name": "minecraft:pink_petals", - "id": -549 - }, - { - "name": "minecraft:pink_wool", - "id": -566 - }, - { - "name": "minecraft:piston", - "id": 33 - }, - { - "name": "minecraft:piston_arm_collision", - "id": 34 - }, - { - "name": "minecraft:planks", - "id": 5 - }, - { - "name": "minecraft:plenty_pottery_shard", - "id": 676 - }, - { - "name": "minecraft:podzol", - "id": 243 - }, - { - "name": "minecraft:pointed_dripstone", - "id": -308 - }, - { - "name": "minecraft:poisonous_potato", - "id": 282 - }, - { - "name": "minecraft:polar_bear_spawn_egg", - "id": 473 - }, - { - "name": "minecraft:polished_andesite_stairs", - "id": -174 - }, - { - "name": "minecraft:polished_basalt", - "id": -235 - }, - { - "name": "minecraft:polished_blackstone", - "id": -291 - }, - { - "name": "minecraft:polished_blackstone_brick_double_slab", - "id": -285 - }, - { - "name": "minecraft:polished_blackstone_brick_slab", - "id": -284 - }, - { - "name": "minecraft:polished_blackstone_brick_stairs", - "id": -275 - }, - { - "name": "minecraft:polished_blackstone_brick_wall", - "id": -278 - }, - { - "name": "minecraft:polished_blackstone_bricks", - "id": -274 - }, - { - "name": "minecraft:polished_blackstone_button", - "id": -296 - }, - { - "name": "minecraft:polished_blackstone_double_slab", - "id": -294 - }, - { - "name": "minecraft:polished_blackstone_pressure_plate", - "id": -295 - }, - { - "name": "minecraft:polished_blackstone_slab", - "id": -293 - }, - { - "name": "minecraft:polished_blackstone_stairs", - "id": -292 - }, - { - "name": "minecraft:polished_blackstone_wall", - "id": -297 - }, - { - "name": "minecraft:polished_deepslate", - "id": -383 - }, - { - "name": "minecraft:polished_deepslate_double_slab", - "id": -397 - }, - { - "name": "minecraft:polished_deepslate_slab", - "id": -384 - }, - { - "name": "minecraft:polished_deepslate_stairs", - "id": -385 - }, - { - "name": "minecraft:polished_deepslate_wall", - "id": -386 - }, - { - "name": "minecraft:polished_diorite_stairs", - "id": -173 - }, - { - "name": "minecraft:polished_granite_stairs", - "id": -172 - }, - { - "name": "minecraft:popped_chorus_fruit", - "id": 565 - }, - { - "name": "minecraft:porkchop", - "id": 262 - }, - { - "name": "minecraft:portal", - "id": 90 - }, - { - "name": "minecraft:potato", - "id": 280 - }, - { - "name": "minecraft:potatoes", - "id": 142 - }, - { - "name": "minecraft:potion", - "id": 427 - }, - { - "name": "minecraft:powder_snow", - "id": -306 - }, - { - "name": "minecraft:powder_snow_bucket", - "id": 369 - }, - { - "name": "minecraft:powered_comparator", - "id": 150 - }, - { - "name": "minecraft:powered_repeater", - "id": 94 - }, - { - "name": "minecraft:prismarine", - "id": 168 - }, - { - "name": "minecraft:prismarine_bricks_stairs", - "id": -4 - }, - { - "name": "minecraft:prismarine_crystals", - "id": 555 - }, - { - "name": "minecraft:prismarine_shard", - "id": 571 - }, - { - "name": "minecraft:prismarine_stairs", - "id": -2 - }, - { - "name": "minecraft:prize_pottery_shard", - "id": 677 - }, - { - "name": "minecraft:pufferfish", - "id": 267 - }, - { - "name": "minecraft:pufferfish_bucket", - "id": 368 - }, - { - "name": "minecraft:pufferfish_spawn_egg", - "id": 482 - }, - { - "name": "minecraft:pumpkin", - "id": 86 - }, - { - "name": "minecraft:pumpkin_pie", - "id": 284 - }, - { - "name": "minecraft:pumpkin_seeds", - "id": 292 - }, - { - "name": "minecraft:pumpkin_stem", - "id": 104 - }, - { - "name": "minecraft:purple_candle", - "id": -423 - }, - { - "name": "minecraft:purple_candle_cake", - "id": -440 - }, - { - "name": "minecraft:purple_dye", - "id": 401 - }, - { - "name": "minecraft:purple_glazed_terracotta", - "id": 219 - }, - { - "name": "minecraft:purple_wool", - "id": -564 - }, - { - "name": "minecraft:purpur_block", - "id": 201 - }, - { - "name": "minecraft:purpur_stairs", - "id": 203 - }, - { - "name": "minecraft:quartz", - "id": 530 - }, - { - "name": "minecraft:quartz_block", - "id": 155 - }, - { - "name": "minecraft:quartz_bricks", - "id": -304 - }, - { - "name": "minecraft:quartz_ore", - "id": 153 - }, - { - "name": "minecraft:quartz_stairs", - "id": 156 - }, - { - "name": "minecraft:rabbit", - "id": 288 - }, - { - "name": "minecraft:rabbit_foot", - "id": 534 - }, - { - "name": "minecraft:rabbit_hide", - "id": 535 - }, - { - "name": "minecraft:rabbit_spawn_egg", - "id": 460 - }, - { - "name": "minecraft:rabbit_stew", - "id": 290 - }, - { - "name": "minecraft:rail", - "id": 66 - }, - { - "name": "minecraft:raiser_armor_trim_smithing_template", - "id": 697 - }, - { - "name": "minecraft:rapid_fertilizer", - "id": 603 - }, - { - "name": "minecraft:ravager_spawn_egg", - "id": 494 - }, - { - "name": "minecraft:raw_copper", - "id": 513 - }, - { - "name": "minecraft:raw_copper_block", - "id": -452 - }, - { - "name": "minecraft:raw_gold", - "id": 512 - }, - { - "name": "minecraft:raw_gold_block", - "id": -453 - }, - { - "name": "minecraft:raw_iron", - "id": 511 - }, - { - "name": "minecraft:raw_iron_block", - "id": -451 - }, - { - "name": "minecraft:recovery_compass", - "id": 652 - }, - { - "name": "minecraft:red_candle", - "id": -427 - }, - { - "name": "minecraft:red_candle_cake", - "id": -444 - }, - { - "name": "minecraft:red_dye", - "id": 397 - }, - { - "name": "minecraft:red_flower", - "id": 38 - }, - { - "name": "minecraft:red_glazed_terracotta", - "id": 234 - }, - { - "name": "minecraft:red_mushroom", - "id": 40 - }, - { - "name": "minecraft:red_mushroom_block", - "id": 100 - }, - { - "name": "minecraft:red_nether_brick", - "id": 215 - }, - { - "name": "minecraft:red_nether_brick_stairs", - "id": -184 - }, - { - "name": "minecraft:red_sandstone", - "id": 179 - }, - { - "name": "minecraft:red_sandstone_stairs", - "id": 180 - }, - { - "name": "minecraft:red_wool", - "id": -556 - }, - { - "name": "minecraft:redstone", - "id": 374 - }, - { - "name": "minecraft:redstone_block", - "id": 152 - }, - { - "name": "minecraft:redstone_lamp", - "id": 123 - }, - { - "name": "minecraft:redstone_ore", - "id": 73 - }, - { - "name": "minecraft:redstone_torch", - "id": 76 - }, - { - "name": "minecraft:redstone_wire", - "id": 55 - }, - { - "name": "minecraft:reinforced_deepslate", - "id": -466 - }, - { - "name": "minecraft:repeater", - "id": 420 - }, - { - "name": "minecraft:repeating_command_block", - "id": 188 - }, - { - "name": "minecraft:reserved6", - "id": 255 - }, - { - "name": "minecraft:respawn_anchor", - "id": -272 - }, - { - "name": "minecraft:rib_armor_trim_smithing_template", - "id": 693 - }, - { - "name": "minecraft:rotten_flesh", - "id": 277 - }, - { - "name": "minecraft:saddle", - "id": 372 - }, - { - "name": "minecraft:salmon", - "id": 265 - }, - { - "name": "minecraft:salmon_bucket", - "id": 366 - }, - { - "name": "minecraft:salmon_spawn_egg", - "id": 483 - }, - { - "name": "minecraft:sand", - "id": 12 - }, - { - "name": "minecraft:sandstone", - "id": 24 - }, - { - "name": "minecraft:sandstone_stairs", - "id": 128 - }, - { - "name": "minecraft:sapling", - "id": 6 - }, - { - "name": "minecraft:scaffolding", - "id": -165 - }, - { - "name": "minecraft:sculk", - "id": -458 - }, - { - "name": "minecraft:sculk_catalyst", - "id": -460 - }, - { - "name": "minecraft:sculk_sensor", - "id": -307 - }, - { - "name": "minecraft:sculk_shrieker", - "id": -461 - }, - { - "name": "minecraft:sculk_vein", - "id": -459 - }, - { - "name": "minecraft:scute", - "id": 578 - }, - { - "name": "minecraft:sea_lantern", - "id": 169 - }, - { - "name": "minecraft:sea_pickle", - "id": -156 - }, - { - "name": "minecraft:seagrass", - "id": -130 - }, - { - "name": "minecraft:sentry_armor_trim_smithing_template", - "id": 684 - }, - { - "name": "minecraft:shaper_armor_trim_smithing_template", - "id": 698 - }, - { - "name": "minecraft:sheaf_pottery_shard", - "id": 678 - }, - { - "name": "minecraft:shears", - "id": 422 - }, - { - "name": "minecraft:sheep_spawn_egg", - "id": 439 - }, - { - "name": "minecraft:shelter_pottery_shard", - "id": 679 - }, - { - "name": "minecraft:shield", - "id": 356 - }, - { - "name": "minecraft:shroomlight", - "id": -230 - }, - { - "name": "minecraft:shulker_box", - "id": 218 - }, - { - "name": "minecraft:shulker_shell", - "id": 572 - }, - { - "name": "minecraft:shulker_spawn_egg", - "id": 470 - }, - { - "name": "minecraft:silence_armor_trim_smithing_template", - "id": 695 - }, - { - "name": "minecraft:silver_glazed_terracotta", - "id": 228 - }, - { - "name": "minecraft:silverfish_spawn_egg", - "id": 444 - }, - { - "name": "minecraft:skeleton_horse_spawn_egg", - "id": 468 - }, - { - "name": "minecraft:skeleton_spawn_egg", - "id": 445 - }, - { - "name": "minecraft:skull", - "id": 522 - }, - { - "name": "minecraft:skull_banner_pattern", - "id": 589 - }, - { - "name": "minecraft:skull_pottery_shard", - "id": 680 - }, - { - "name": "minecraft:slime", - "id": 165 - }, - { - "name": "minecraft:slime_ball", - "id": 389 - }, - { - "name": "minecraft:slime_spawn_egg", - "id": 446 - }, - { - "name": "minecraft:small_amethyst_bud", - "id": -332 - }, - { - "name": "minecraft:small_dripleaf_block", - "id": -336 - }, - { - "name": "minecraft:smithing_table", - "id": -202 - }, - { - "name": "minecraft:smoker", - "id": -198 - }, - { - "name": "minecraft:smooth_basalt", - "id": -377 - }, - { - "name": "minecraft:smooth_quartz_stairs", - "id": -185 - }, - { - "name": "minecraft:smooth_red_sandstone_stairs", - "id": -176 - }, - { - "name": "minecraft:smooth_sandstone_stairs", - "id": -177 - }, - { - "name": "minecraft:smooth_stone", - "id": -183 - }, - { - "name": "minecraft:sniffer_spawn_egg", - "id": 501 - }, - { - "name": "minecraft:snort_pottery_shard", - "id": 681 - }, - { - "name": "minecraft:snout_armor_trim_smithing_template", - "id": 692 - }, - { - "name": "minecraft:snow", - "id": 80 - }, - { - "name": "minecraft:snow_golem_spawn_egg", - "id": 506 - }, - { - "name": "minecraft:snow_layer", - "id": 78 - }, - { - "name": "minecraft:snowball", - "id": 375 - }, - { - "name": "minecraft:soul_campfire", - "id": 628 - }, - { - "name": "minecraft:soul_fire", - "id": -237 - }, - { - "name": "minecraft:soul_lantern", - "id": -269 - }, - { - "name": "minecraft:soul_sand", - "id": 88 - }, - { - "name": "minecraft:soul_soil", - "id": -236 - }, - { - "name": "minecraft:soul_torch", - "id": -268 - }, - { - "name": "minecraft:sparkler", - "id": 606 - }, - { - "name": "minecraft:spawn_egg", - "id": 707 - }, - { - "name": "minecraft:spider_eye", - "id": 278 - }, - { - "name": "minecraft:spider_spawn_egg", - "id": 447 - }, - { - "name": "minecraft:spire_armor_trim_smithing_template", - "id": 694 - }, - { - "name": "minecraft:splash_potion", - "id": 567 - }, - { - "name": "minecraft:sponge", - "id": 19 - }, - { - "name": "minecraft:spore_blossom", - "id": -321 - }, - { - "name": "minecraft:spruce_boat", - "id": 379 - }, - { - "name": "minecraft:spruce_button", - "id": -144 - }, - { - "name": "minecraft:spruce_chest_boat", - "id": 647 - }, - { - "name": "minecraft:spruce_door", - "id": 559 - }, - { - "name": "minecraft:spruce_fence", - "id": -579 - }, - { - "name": "minecraft:spruce_fence_gate", - "id": 183 - }, - { - "name": "minecraft:spruce_hanging_sign", - "id": -501 - }, - { - "name": "minecraft:spruce_log", - "id": -569 - }, - { - "name": "minecraft:spruce_pressure_plate", - "id": -154 - }, - { - "name": "minecraft:spruce_sign", - "id": 582 - }, - { - "name": "minecraft:spruce_stairs", - "id": 134 - }, - { - "name": "minecraft:spruce_standing_sign", - "id": -181 - }, - { - "name": "minecraft:spruce_trapdoor", - "id": -149 - }, - { - "name": "minecraft:spruce_wall_sign", - "id": -182 - }, - { - "name": "minecraft:spyglass", - "id": 631 - }, - { - "name": "minecraft:squid_spawn_egg", - "id": 451 - }, - { - "name": "minecraft:stained_glass", - "id": 241 - }, - { - "name": "minecraft:stained_glass_pane", - "id": 160 - }, - { - "name": "minecraft:stained_hardened_clay", - "id": 159 - }, - { - "name": "minecraft:standing_banner", - "id": 176 - }, - { - "name": "minecraft:standing_sign", - "id": 63 - }, - { - "name": "minecraft:stick", - "id": 321 - }, - { - "name": "minecraft:sticky_piston", - "id": 29 - }, - { - "name": "minecraft:sticky_piston_arm_collision", - "id": -217 - }, - { - "name": "minecraft:stone", - "id": 1 - }, - { - "name": "minecraft:stone_axe", - "id": 316 - }, - { - "name": "minecraft:stone_block_slab", - "id": 44 - }, - { - "name": "minecraft:stone_block_slab2", - "id": 182 - }, - { - "name": "minecraft:stone_block_slab3", - "id": -162 - }, - { - "name": "minecraft:stone_block_slab4", - "id": -166 - }, - { - "name": "minecraft:stone_brick_stairs", - "id": 109 - }, - { - "name": "minecraft:stone_button", - "id": 77 - }, - { - "name": "minecraft:stone_hoe", - "id": 331 - }, - { - "name": "minecraft:stone_pickaxe", - "id": 315 - }, - { - "name": "minecraft:stone_pressure_plate", - "id": 70 - }, - { - "name": "minecraft:stone_shovel", - "id": 314 - }, - { - "name": "minecraft:stone_stairs", - "id": 67 - }, - { - "name": "minecraft:stone_sword", - "id": 313 - }, - { - "name": "minecraft:stonebrick", - "id": 98 - }, - { - "name": "minecraft:stonecutter", - "id": 245 - }, - { - "name": "minecraft:stonecutter_block", - "id": -197 - }, - { - "name": "minecraft:stray_spawn_egg", - "id": 463 - }, - { - "name": "minecraft:strider_spawn_egg", - "id": 496 - }, - { - "name": "minecraft:string", - "id": 327 - }, - { - "name": "minecraft:stripped_acacia_log", - "id": -8 - }, - { - "name": "minecraft:stripped_bamboo_block", - "id": -528 - }, - { - "name": "minecraft:stripped_birch_log", - "id": -6 - }, - { - "name": "minecraft:stripped_cherry_log", - "id": -535 - }, - { - "name": "minecraft:stripped_cherry_wood", - "id": -545 - }, - { - "name": "minecraft:stripped_crimson_hyphae", - "id": -300 - }, - { - "name": "minecraft:stripped_crimson_stem", - "id": -240 - }, - { - "name": "minecraft:stripped_dark_oak_log", - "id": -9 - }, - { - "name": "minecraft:stripped_jungle_log", - "id": -7 - }, - { - "name": "minecraft:stripped_mangrove_log", - "id": -485 - }, - { - "name": "minecraft:stripped_mangrove_wood", - "id": -498 - }, - { - "name": "minecraft:stripped_oak_log", - "id": -10 - }, - { - "name": "minecraft:stripped_spruce_log", - "id": -5 - }, - { - "name": "minecraft:stripped_warped_hyphae", - "id": -301 - }, - { - "name": "minecraft:stripped_warped_stem", - "id": -241 - }, - { - "name": "minecraft:structure_block", - "id": 252 - }, - { - "name": "minecraft:structure_void", - "id": 217 - }, - { - "name": "minecraft:sugar", - "id": 417 - }, - { - "name": "minecraft:sugar_cane", - "id": 386 - }, - { - "name": "minecraft:suspicious_gravel", - "id": -573 - }, - { - "name": "minecraft:suspicious_sand", - "id": -529 - }, - { - "name": "minecraft:suspicious_stew", - "id": 596 - }, - { - "name": "minecraft:sweet_berries", - "id": 287 - }, - { - "name": "minecraft:sweet_berry_bush", - "id": -207 - }, - { - "name": "minecraft:tadpole_bucket", - "id": 636 - }, - { - "name": "minecraft:tadpole_spawn_egg", - "id": 635 - }, - { - "name": "minecraft:tallgrass", - "id": 31 - }, - { - "name": "minecraft:target", - "id": -239 - }, - { - "name": "minecraft:tide_armor_trim_smithing_template", - "id": 691 - }, - { - "name": "minecraft:tinted_glass", - "id": -334 - }, - { - "name": "minecraft:tnt", - "id": 46 - }, - { - "name": "minecraft:tnt_minecart", - "id": 531 - }, - { - "name": "minecraft:torch", - "id": 50 - }, - { - "name": "minecraft:torchflower", - "id": -568 - }, - { - "name": "minecraft:torchflower_crop", - "id": -567 - }, - { - "name": "minecraft:torchflower_seeds", - "id": 296 - }, - { - "name": "minecraft:totem_of_undying", - "id": 574 - }, - { - "name": "minecraft:trader_llama_spawn_egg", - "id": 654 - }, - { - "name": "minecraft:trapdoor", - "id": 96 - }, - { - "name": "minecraft:trapped_chest", - "id": 146 - }, - { - "name": "minecraft:trident", - "id": 552 - }, - { - "name": "minecraft:trip_wire", - "id": 132 - }, - { - "name": "minecraft:tripwire_hook", - "id": 131 - }, - { - "name": "minecraft:tropical_fish", - "id": 266 - }, - { - "name": "minecraft:tropical_fish_bucket", - "id": 367 - }, - { - "name": "minecraft:tropical_fish_spawn_egg", - "id": 480 - }, - { - "name": "minecraft:tuff", - "id": -333 - }, - { - "name": "minecraft:turtle_egg", - "id": -159 - }, - { - "name": "minecraft:turtle_helmet", - "id": 579 - }, - { - "name": "minecraft:turtle_spawn_egg", - "id": 486 - }, - { - "name": "minecraft:twisting_vines", - "id": -287 - }, - { - "name": "minecraft:underwater_torch", - "id": 239 - }, - { - "name": "minecraft:undyed_shulker_box", - "id": 205 - }, - { - "name": "minecraft:unknown", - "id": -305 - }, - { - "name": "minecraft:unlit_redstone_torch", - "id": 75 - }, - { - "name": "minecraft:unpowered_comparator", - "id": 149 - }, - { - "name": "minecraft:unpowered_repeater", - "id": 93 - }, - { - "name": "minecraft:verdant_froglight", - "id": -470 - }, - { - "name": "minecraft:vex_armor_trim_smithing_template", - "id": 690 - }, - { - "name": "minecraft:vex_spawn_egg", - "id": 477 - }, - { - "name": "minecraft:villager_spawn_egg", - "id": 450 - }, - { - "name": "minecraft:vindicator_spawn_egg", - "id": 475 - }, - { - "name": "minecraft:vine", - "id": 106 - }, - { - "name": "minecraft:wall_banner", - "id": 177 - }, - { - "name": "minecraft:wall_sign", - "id": 68 - }, - { - "name": "minecraft:wandering_trader_spawn_egg", - "id": 493 - }, - { - "name": "minecraft:ward_armor_trim_smithing_template", - "id": 688 - }, - { - "name": "minecraft:warden_spawn_egg", - "id": 638 - }, - { - "name": "minecraft:warped_button", - "id": -261 - }, - { - "name": "minecraft:warped_door", - "id": 623 - }, - { - "name": "minecraft:warped_double_slab", - "id": -267 - }, - { - "name": "minecraft:warped_fence", - "id": -257 - }, - { - "name": "minecraft:warped_fence_gate", - "id": -259 - }, - { - "name": "minecraft:warped_fungus", - "id": -229 - }, - { - "name": "minecraft:warped_fungus_on_a_stick", - "id": 624 - }, - { - "name": "minecraft:warped_hanging_sign", - "id": -507 - }, - { - "name": "minecraft:warped_hyphae", - "id": -298 - }, - { - "name": "minecraft:warped_nylium", - "id": -233 - }, - { - "name": "minecraft:warped_planks", - "id": -243 - }, - { - "name": "minecraft:warped_pressure_plate", - "id": -263 - }, - { - "name": "minecraft:warped_roots", - "id": -224 - }, - { - "name": "minecraft:warped_sign", - "id": 621 - }, - { - "name": "minecraft:warped_slab", - "id": -265 - }, - { - "name": "minecraft:warped_stairs", - "id": -255 - }, - { - "name": "minecraft:warped_standing_sign", - "id": -251 - }, - { - "name": "minecraft:warped_stem", - "id": -226 - }, - { - "name": "minecraft:warped_trapdoor", - "id": -247 - }, - { - "name": "minecraft:warped_wall_sign", - "id": -253 - }, - { - "name": "minecraft:warped_wart_block", - "id": -227 - }, - { - "name": "minecraft:water", - "id": 9 - }, - { - "name": "minecraft:water_bucket", - "id": 363 - }, - { - "name": "minecraft:waterlily", - "id": 111 - }, - { - "name": "minecraft:waxed_copper", - "id": -344 - }, - { - "name": "minecraft:waxed_cut_copper", - "id": -351 - }, - { - "name": "minecraft:waxed_cut_copper_slab", - "id": -365 - }, - { - "name": "minecraft:waxed_cut_copper_stairs", - "id": -358 - }, - { - "name": "minecraft:waxed_double_cut_copper_slab", - "id": -372 - }, - { - "name": "minecraft:waxed_exposed_copper", - "id": -345 - }, - { - "name": "minecraft:waxed_exposed_cut_copper", - "id": -352 - }, - { - "name": "minecraft:waxed_exposed_cut_copper_slab", - "id": -366 - }, - { - "name": "minecraft:waxed_exposed_cut_copper_stairs", - "id": -359 - }, - { - "name": "minecraft:waxed_exposed_double_cut_copper_slab", - "id": -373 - }, - { - "name": "minecraft:waxed_oxidized_copper", - "id": -446 - }, - { - "name": "minecraft:waxed_oxidized_cut_copper", - "id": -447 - }, - { - "name": "minecraft:waxed_oxidized_cut_copper_slab", - "id": -449 - }, - { - "name": "minecraft:waxed_oxidized_cut_copper_stairs", - "id": -448 - }, - { - "name": "minecraft:waxed_oxidized_double_cut_copper_slab", - "id": -450 - }, - { - "name": "minecraft:waxed_weathered_copper", - "id": -346 - }, - { - "name": "minecraft:waxed_weathered_cut_copper", - "id": -353 - }, - { - "name": "minecraft:waxed_weathered_cut_copper_slab", - "id": -367 - }, - { - "name": "minecraft:waxed_weathered_cut_copper_stairs", - "id": -360 - }, - { - "name": "minecraft:waxed_weathered_double_cut_copper_slab", - "id": -374 - }, - { - "name": "minecraft:wayfinder_armor_trim_smithing_template", - "id": 696 - }, - { - "name": "minecraft:weathered_copper", - "id": -342 - }, - { - "name": "minecraft:weathered_cut_copper", - "id": -349 - }, - { - "name": "minecraft:weathered_cut_copper_slab", - "id": -363 - }, - { - "name": "minecraft:weathered_cut_copper_stairs", - "id": -356 - }, - { - "name": "minecraft:weathered_double_cut_copper_slab", - "id": -370 - }, - { - "name": "minecraft:web", - "id": 30 - }, - { - "name": "minecraft:weeping_vines", - "id": -231 - }, - { - "name": "minecraft:wheat", - "id": 335 - }, - { - "name": "minecraft:wheat_seeds", - "id": 291 - }, - { - "name": "minecraft:white_candle", - "id": -413 - }, - { - "name": "minecraft:white_candle_cake", - "id": -430 - }, - { - "name": "minecraft:white_dye", - "id": 411 - }, - { - "name": "minecraft:white_glazed_terracotta", - "id": 220 - }, - { - "name": "minecraft:white_wool", - "id": 35 - }, - { - "name": "minecraft:wild_armor_trim_smithing_template", - "id": 687 - }, - { - "name": "minecraft:witch_spawn_egg", - "id": 453 - }, - { - "name": "minecraft:wither_rose", - "id": -216 - }, - { - "name": "minecraft:wither_skeleton_spawn_egg", - "id": 465 - }, - { - "name": "minecraft:wither_spawn_egg", - "id": 508 - }, - { - "name": "minecraft:wolf_spawn_egg", - "id": 440 - }, - { - "name": "minecraft:wood", - "id": -212 - }, - { - "name": "minecraft:wooden_axe", - "id": 312 - }, - { - "name": "minecraft:wooden_button", - "id": 143 - }, - { - "name": "minecraft:wooden_door", - "id": 360 - }, - { - "name": "minecraft:wooden_hoe", - "id": 330 - }, - { - "name": "minecraft:wooden_pickaxe", - "id": 311 - }, - { - "name": "minecraft:wooden_pressure_plate", - "id": 72 - }, - { - "name": "minecraft:wooden_shovel", - "id": 310 - }, - { - "name": "minecraft:wooden_slab", - "id": 158 - }, - { - "name": "minecraft:wooden_sword", - "id": 309 - }, - { - "name": "minecraft:wool", - "id": 700 - }, - { - "name": "minecraft:writable_book", - "id": 516 - }, - { - "name": "minecraft:written_book", - "id": 517 - }, - { - "name": "minecraft:yellow_candle", - "id": -417 - }, - { - "name": "minecraft:yellow_candle_cake", - "id": -434 - }, - { - "name": "minecraft:yellow_dye", - "id": 407 - }, - { - "name": "minecraft:yellow_flower", - "id": 37 - }, - { - "name": "minecraft:yellow_glazed_terracotta", - "id": 224 - }, - { - "name": "minecraft:yellow_wool", - "id": -558 - }, - { - "name": "minecraft:zoglin_spawn_egg", - "id": 499 - }, - { - "name": "minecraft:zombie_horse_spawn_egg", - "id": 469 - }, - { - "name": "minecraft:zombie_pigman_spawn_egg", - "id": 449 - }, - { - "name": "minecraft:zombie_spawn_egg", - "id": 448 - }, - { - "name": "minecraft:zombie_villager_spawn_egg", - "id": 478 - } -] \ No newline at end of file diff --git a/core/src/main/resources/languages b/core/src/main/resources/languages index fda08c186..afbf78bbe 160000 --- a/core/src/main/resources/languages +++ b/core/src/main/resources/languages @@ -1 +1 @@ -Subproject commit fda08c186de979ff89b01d2b66f48daa5e218d01 +Subproject commit afbf78bbe0b39d0a076a42c228828c12f7f7da90 From 1b05f9f15e3a7b05f95e7087ca60a9e8334d57e1 Mon Sep 17 00:00:00 2001 From: chris Date: Wed, 30 Aug 2023 22:18:06 +0200 Subject: [PATCH 063/344] Register extension commands on Geyser-Fabric (#4080) * Register Extension commands on Geyser-Fabric * Allow Geyser commands to accept arguments aswell - e.g. geyser dump logs --- .../platform/fabric/GeyserFabricMod.java | 35 +++++++++++++++++-- .../fabric/command/FabricCommandSender.java | 2 +- .../command/GeyserFabricCommandExecutor.java | 7 +++- 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMod.java b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMod.java index 64b050ec5..0bbe73f16 100644 --- a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMod.java +++ b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMod.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.platform.fabric; +import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import net.fabricmc.api.EnvType; import net.fabricmc.api.ModInitializer; @@ -36,11 +37,12 @@ import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.server.MinecraftServer; import org.apache.logging.log4j.LogManager; -import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserLogger; import org.geysermc.geyser.api.command.Command; +import org.geysermc.geyser.api.extension.Extension; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.command.GeyserCommand; import org.geysermc.geyser.command.GeyserCommandManager; import org.geysermc.geyser.configuration.GeyserConfiguration; @@ -161,9 +163,37 @@ public class GeyserFabricMod implements ModInitializer, GeyserBootstrap { builder.then(Commands.literal(command.getKey()) .executes(executor) // Could also test for Bedrock but depending on when this is called it may backfire - .requires(executor::testPermission)); + .requires(executor::testPermission) + // Allows parsing of arguments; e.g. for /geyser dump logs or the connectiontest command + .then(Commands.argument("args", StringArgumentType.greedyString()) + .executes(context -> executor.runWithArgs(context, StringArgumentType.getString(context, "args"))) + .requires(executor::testPermission))); } server.getCommands().getDispatcher().register(builder); + + // Register extension commands + for (Map.Entry> extensionMapEntry : geyser.commandManager().extensionCommands().entrySet()) { + Map extensionCommands = extensionMapEntry.getValue(); + if (extensionCommands.isEmpty()) { + continue; + } + + // Register help command for just "/" + GeyserFabricCommandExecutor extensionHelpExecutor = new GeyserFabricCommandExecutor(geyser, + (GeyserCommand) extensionCommands.get("help")); + LiteralArgumentBuilder extCmdBuilder = Commands.literal(extensionMapEntry.getKey().description().id()).executes(extensionHelpExecutor); + + for (Map.Entry command : extensionCommands.entrySet()) { + GeyserFabricCommandExecutor executor = new GeyserFabricCommandExecutor(geyser, (GeyserCommand) command.getValue()); + extCmdBuilder.then(Commands.literal(command.getKey()) + .executes(executor) + .requires(executor::testPermission) + .then(Commands.argument("args", StringArgumentType.greedyString()) + .executes(context -> executor.runWithArgs(context, StringArgumentType.getString(context, "args"))) + .requires(executor::testPermission))); + } + server.getCommands().getDispatcher().register(extCmdBuilder); + } } @Override @@ -217,7 +247,6 @@ public class GeyserFabricMod implements ModInitializer, GeyserBootstrap { return this.server.getServerVersion(); } - @SuppressWarnings("ConstantConditions") // IDEA thinks that ip cannot be null @NotNull @Override public String getServerBindAddress() { diff --git a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/command/FabricCommandSender.java b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/command/FabricCommandSender.java index 5973e04f1..6517ac133 100644 --- a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/command/FabricCommandSender.java +++ b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/command/FabricCommandSender.java @@ -75,6 +75,6 @@ public class FabricCommandSender implements GeyserCommandSource { @Override public boolean hasPermission(String permission) { - return Permissions.check(source, permission); + return Permissions.check(source, permission, source.getServer().getOperatorUserPermissionLevel()); } } diff --git a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/command/GeyserFabricCommandExecutor.java b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/command/GeyserFabricCommandExecutor.java index 7600e4136..8da7c8512 100644 --- a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/command/GeyserFabricCommandExecutor.java +++ b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/command/GeyserFabricCommandExecutor.java @@ -53,6 +53,10 @@ public class GeyserFabricCommandExecutor extends GeyserCommandExecutor implement @Override public int run(CommandContext context) { + return runWithArgs(context, ""); + } + + public int runWithArgs(CommandContext context, String args) { CommandSourceStack source = (CommandSourceStack) context.getSource(); FabricCommandSender sender = new FabricCommandSender(source); GeyserSession session = getGeyserSession(sender); @@ -68,7 +72,8 @@ public class GeyserFabricCommandExecutor extends GeyserCommandExecutor implement sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.bedrock_only", sender.locale())); return 0; } - command.execute(session, sender, new String[0]); + + command.execute(session, sender, args.split(" ")); return 0; } } From bf81fc11394f6f7996096d4b4f2d024bf5a337f5 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Thu, 31 Aug 2023 10:09:14 -0700 Subject: [PATCH 064/344] Allow Null Texture for Block Mappings/API (#4094) * Allow null textures for blocks.json use * Missing semicolon --- .../block/custom/component/MaterialInstance.java | 13 ++++++------- .../geyser/level/block/GeyserMaterialInstance.java | 13 ++++++------- .../mappings/versions/MappingsReader_v1.java | 2 +- .../populator/CustomBlockRegistryPopulator.java | 11 +++++++---- 4 files changed, 20 insertions(+), 19 deletions(-) diff --git a/api/src/main/java/org/geysermc/geyser/api/block/custom/component/MaterialInstance.java b/api/src/main/java/org/geysermc/geyser/api/block/custom/component/MaterialInstance.java index 26edab2f6..bf30dd2b2 100644 --- a/api/src/main/java/org/geysermc/geyser/api/block/custom/component/MaterialInstance.java +++ b/api/src/main/java/org/geysermc/geyser/api/block/custom/component/MaterialInstance.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.api.block.custom.component; -import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.api.GeyserApi; @@ -38,7 +37,7 @@ public interface MaterialInstance { * * @return The texture of the block. */ - @NonNull String texture(); + @Nullable String texture(); /** * Gets the render method of the block @@ -52,14 +51,14 @@ public interface MaterialInstance { * * @return If the block should be dimmed on certain faces. */ - @Nullable boolean faceDimming(); + boolean faceDimming(); /** * Gets if the block should have ambient occlusion * * @return If the block should have ambient occlusion. */ - @Nullable boolean ambientOcclusion(); + boolean ambientOcclusion(); /** * Creates a builder for MaterialInstance. @@ -71,13 +70,13 @@ public interface MaterialInstance { } interface Builder { - Builder texture(@NonNull String texture); + Builder texture(@Nullable String texture); Builder renderMethod(@Nullable String renderMethod); - Builder faceDimming(@Nullable boolean faceDimming); + Builder faceDimming(boolean faceDimming); - Builder ambientOcclusion(@Nullable boolean ambientOcclusion); + Builder ambientOcclusion(boolean ambientOcclusion); MaterialInstance build(); } diff --git a/core/src/main/java/org/geysermc/geyser/level/block/GeyserMaterialInstance.java b/core/src/main/java/org/geysermc/geyser/level/block/GeyserMaterialInstance.java index 80a880152..527b8fe79 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/GeyserMaterialInstance.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/GeyserMaterialInstance.java @@ -26,7 +26,6 @@ package org.geysermc.geyser.level.block; import lombok.RequiredArgsConstructor; -import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.api.block.custom.component.MaterialInstance; @@ -45,7 +44,7 @@ public class GeyserMaterialInstance implements MaterialInstance { } @Override - public @NonNull String texture() { + public @Nullable String texture() { return texture; } @@ -55,12 +54,12 @@ public class GeyserMaterialInstance implements MaterialInstance { } @Override - public @Nullable boolean faceDimming() { + public boolean faceDimming() { return faceDimming; } @Override - public @Nullable boolean ambientOcclusion() { + public boolean ambientOcclusion() { return ambientOcclusion; } @@ -71,7 +70,7 @@ public class GeyserMaterialInstance implements MaterialInstance { private boolean ambientOcclusion; @Override - public Builder texture(@NonNull String texture) { + public Builder texture(@Nullable String texture) { this.texture = texture; return this; } @@ -83,13 +82,13 @@ public class GeyserMaterialInstance implements MaterialInstance { } @Override - public Builder faceDimming(@Nullable boolean faceDimming) { + public Builder faceDimming(boolean faceDimming) { this.faceDimming = faceDimming; return this; } @Override - public Builder ambientOcclusion(@Nullable boolean ambientOcclusion) { + public Builder ambientOcclusion(boolean ambientOcclusion) { this.ambientOcclusion = ambientOcclusion; return this; } diff --git a/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java b/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java index 51c2220cb..e63bf6bf9 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java +++ b/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java @@ -626,7 +626,7 @@ public class MappingsReader_v1 extends MappingsReader { */ private MaterialInstance createMaterialInstanceComponent(JsonNode node, String name) { // Set default values, and use what the user provides if they have provided something - String texture = name; + String texture = null; if (node.has("texture")) { texture = node.get("texture").asText(); } diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java index 5d453582c..504db753d 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java @@ -325,12 +325,15 @@ public class CustomBlockRegistryPopulator { NbtMapBuilder materialsBuilder = NbtMap.builder(); for (Map.Entry entry : components.materialInstances().entrySet()) { MaterialInstance materialInstance = entry.getValue(); - materialsBuilder.putCompound(entry.getKey(), NbtMap.builder() - .putString("texture", materialInstance.texture()) + NbtMapBuilder materialBuilder = NbtMap.builder() .putString("render_method", materialInstance.renderMethod()) .putBoolean("face_dimming", materialInstance.faceDimming()) - .putBoolean("ambient_occlusion", materialInstance.faceDimming()) - .build()); + .putBoolean("ambient_occlusion", materialInstance.faceDimming()); + // Texture can be unspecified when blocks.json is used in RP (https://wiki.bedrock.dev/blocks/blocks-stable.html#minecraft-material-instances) + if (materialInstance.texture() != null) { + materialBuilder.putString("texture", materialInstance.texture()); + } + materialsBuilder.putCompound(entry.getKey(), materialBuilder.build()); } builder.putCompound("minecraft:material_instances", NbtMap.builder() From 0d5cb51d5f15fe2fb675a7d015cbc76f776f723c Mon Sep 17 00:00:00 2001 From: chris Date: Wed, 6 Sep 2023 05:16:44 +0200 Subject: [PATCH 065/344] Make `geyser connectiontest` command more foolproof (#3951) Co-authored-by: Camotoy <20743703+Camotoy@users.noreply.github.com> --- .../defaults/ConnectionTestCommand.java | 122 ++++++++++++++---- .../geyser/network/netty/GeyserServer.java | 7 + .../player/BedrockActionTranslator.java | 2 +- 3 files changed, 107 insertions(+), 24 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/ConnectionTestCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/ConnectionTestCommand.java index 8471fcd3f..12294ae06 100644 --- a/core/src/main/java/org/geysermc/geyser/command/defaults/ConnectionTestCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/ConnectionTestCommand.java @@ -26,8 +26,8 @@ package org.geysermc.geyser.command.defaults; import com.fasterxml.jackson.databind.JsonNode; -import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.command.GeyserCommand; import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.session.GeyserSession; @@ -36,11 +36,20 @@ import org.geysermc.geyser.util.LoopbackUtil; import org.geysermc.geyser.util.WebUtils; import org.jetbrains.annotations.Nullable; +import java.util.Random; import java.util.concurrent.CompletableFuture; public class ConnectionTestCommand extends GeyserCommand { + /* + * The MOTD is temporarily changed during the connection test. + * This allows us to check if we are pinging the correct Geyser instance + */ + public static String CONNECTION_TEST_MOTD = null; + private final GeyserImpl geyser; + private final Random random = new Random(); + public ConnectionTestCommand(GeyserImpl geyser, String name, String description, String permission) { super(name, description, permission); this.geyser = geyser; @@ -55,23 +64,61 @@ public class ConnectionTestCommand extends GeyserCommand { } if (args.length == 0) { - sender.sendMessage("Provide the Bedrock server IP you are trying to connect with. Example: `test.geysermc.org:19132`"); + sender.sendMessage("Provide the server IP and port you are trying to test Bedrock connections for. Example: `test.geysermc.org:19132`"); return; } + // Replace "<" and ">" symbols if they are present to avoid the common issue of people including them + String[] fullAddress = args[0].replace("<", "").replace(">", "").split(":", 2); + // Still allow people to not supply a port and fallback to 19132 - String[] fullAddress = args[0].split(":", 2); int port; if (fullAddress.length == 2) { - port = Integer.parseInt(fullAddress[1]); + try { + port = Integer.parseInt(fullAddress[1]); + } catch (NumberFormatException e) { + // can occur if e.g. "/geyser connectiontest : is ran + sender.sendMessage("Not a valid port! Specify a valid numeric port."); + return; + } } else { port = 19132; } + String ip = fullAddress[0]; + + // Issue: people commonly checking placeholders + if (ip.equals("ip")) { + sender.sendMessage(ip + " is not a valid IP, and instead a placeholder. Please specify the IP to check."); + return; + } + + // Issue: checking 0.0.0.0 won't work + if (ip.equals("0.0.0.0")) { + sender.sendMessage("Please specify the IP that you would connect with. 0.0.0.0 in the config tells Geyser to the listen on the server's IPv4."); + return; + } + + // Issue: people testing local ip + if (ip.equals("localhost") || ip.startsWith("127.") || ip.startsWith("10.") || ip.startsWith("192.168.")) { + sender.sendMessage("This tool checks if connections from other networks are possible, so you cannot check a local IP."); + return; + } // Issue: do the ports not line up? if (port != geyser.getConfig().getBedrock().port()) { - sender.sendMessage("The port you supplied (" + port + ") does not match the port supplied in Geyser's configuration (" - + geyser.getConfig().getBedrock().port() + "). You can change it under `bedrock` `port`."); + if (fullAddress.length == 2) { + sender.sendMessage("The port you are testing with (" + port + ") is not the same as you set in your Geyser configuration (" + + geyser.getConfig().getBedrock().port() + ")"); + sender.sendMessage("Re-run the command with the port in the config, or change the `bedrock` `port` in the config."); + if (geyser.getConfig().getBedrock().isCloneRemotePort()) { + sender.sendMessage("You have `clone-remote-port` enabled. This option ignores the `bedrock` `port` in the config, and uses the Java server port instead."); + } + } else { + sender.sendMessage("You did not specify the port to check (add it with \":\"), " + + "and the default port 19132 does not match the port in your Geyser configuration (" + + geyser.getConfig().getBedrock().port() + ")!"); + sender.sendMessage("Re-run the command with that port, or change the port in the config under `bedrock` `port`."); + } } // Issue: is the `bedrock` `address` in the config different? @@ -79,7 +126,7 @@ public class ConnectionTestCommand extends GeyserCommand { sender.sendMessage("The address specified in `bedrock` `address` is not \"0.0.0.0\" - this may cause issues unless this is deliberate and intentional."); } - // Issue: did someone turn on enable-proxy-protocol and they didn't mean it? + // Issue: did someone turn on enable-proxy-protocol, and they didn't mean it? if (geyser.getConfig().getBedrock().isEnableProxyProtocol()) { sender.sendMessage("You have the `enable-proxy-protocol` setting enabled. " + "Unless you're deliberately using additional software that REQUIRES this setting, you may not need it enabled."); @@ -88,7 +135,6 @@ public class ConnectionTestCommand extends GeyserCommand { CompletableFuture.runAsync(() -> { try { // Issue: SRV record? - String ip = fullAddress[0]; String[] record = WebUtils.findSrvRecord(geyser, ip); if (record != null && !ip.equals(record[3]) && !record[2].equals(String.valueOf(port))) { sender.sendMessage("Bedrock Edition does not support SRV records. Try connecting to your server using the address " + record[3] + " and the port " + record[2] @@ -102,20 +148,50 @@ public class ConnectionTestCommand extends GeyserCommand { "See here for steps on how to resolve: " + "https://wiki.geysermc.org/geyser/fixing-unable-to-connect-to-world/#using-geyser-on-the-same-computer"); } - // mcsrvstatus will likely be replaced in the future with our own service where we can also test - // around the OVH workaround without worrying about caching - JsonNode output = WebUtils.getJson("https://api.mcsrvstat.us/bedrock/2/" + args[0]); + // Generate some random, unique bits that another server wouldn't provide + byte[] randomBytes = new byte[2]; + this.random.nextBytes(randomBytes); + StringBuilder randomStr = new StringBuilder(); + for (byte b : randomBytes) { + randomStr.append(Integer.toHexString(b)); + } + String connectionTestMotd = "Geyser Connection Test " + randomStr; + CONNECTION_TEST_MOTD = connectionTestMotd; - long cacheTime = output.get("debug").get("cachetime").asLong(); - String when; - if (cacheTime == 0) { - when = "now"; - } else { - when = ((System.currentTimeMillis() / 1000L) - cacheTime) + " seconds ago"; + sender.sendMessage("Testing server connection now. Please wait..."); + JsonNode output; + try { + output = WebUtils.getJson("https://checker.geysermc.org/ping?hostname=" + ip + "&port=" + port); + } finally { + CONNECTION_TEST_MOTD = null; } - if (output.get("online").asBoolean()) { - sender.sendMessage("Your server is likely online as of " + when + "!"); + JsonNode cache = output.get("cache"); + String when; + if (cache.get("fromCache").asBoolean()) { + when = cache.get("secondsSince").asInt() + " seconds ago"; + } else { + when = "now"; + } + + if (output.get("success").asBoolean()) { + JsonNode ping = output.get("ping"); + JsonNode pong = ping.get("pong"); + String remoteMotd = pong.get("motd").asText(); + if (!connectionTestMotd.equals(remoteMotd)) { + sender.sendMessage("The MOTD did not match when we pinged the server (we got '" + remoteMotd + "'). " + + "Did you supply the correct IP and port of your server?"); + sendLinks(sender); + return; + } + + if (ping.get("tcpFirst").asBoolean()) { + sender.sendMessage("Your server hardware likely has some sort of firewall preventing people from joining easily. See https://geysermc.link/ovh-firewall for more information."); + sendLinks(sender); + return; + } + + sender.sendMessage("Your server is likely online and working as of " + when + "!"); sendLinks(sender); return; } @@ -123,16 +199,16 @@ public class ConnectionTestCommand extends GeyserCommand { sender.sendMessage("Your server is likely unreachable from outside the network as of " + when + "."); sendLinks(sender); } catch (Exception e) { - sender.sendMessage("Error while trying to check your connection!"); + sender.sendMessage("An error occurred while trying to check your connection! Check the console for more information."); geyser.getLogger().error("Error while trying to check your connection!", e); } }); } private void sendLinks(GeyserCommandSource sender) { - sender.sendMessage("If you still have issues, check to see if your hosting provider has a specific setup: " + - "https://wiki.geysermc.org/geyser/supported-hosting-providers/" + ", see this page: " - + "https://wiki.geysermc.org/geyser/fixing-unable-to-connect-to-world/" + ", or contact us on our Discord: " + "https://discord.gg/geysermc"); + sender.sendMessage("If you still face issues, check the setup guide for instructions: " + + "https://wiki.geysermc.org/geyser/setup/"); + sender.sendMessage("If that does not work, see " + "https://wiki.geysermc.org/geyser/fixing-unable-to-connect-to-world/" + ", or contact us on Discord: " + "https://discord.gg/geysermc"); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java b/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java index 22f46ee22..df9e1e9d9 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java @@ -47,6 +47,7 @@ import org.cloudburstmc.netty.channel.raknet.config.RakChannelOption; import org.cloudburstmc.netty.handler.codec.raknet.server.RakServerOfflineHandler; import org.cloudburstmc.protocol.bedrock.BedrockPong; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.command.defaults.ConnectionTestCommand; import org.geysermc.geyser.configuration.GeyserConfiguration; import org.geysermc.geyser.event.type.GeyserBedrockPingEventImpl; import org.geysermc.geyser.network.CIDRMatcher; @@ -254,6 +255,12 @@ public final class GeyserServer { pong.subMotd(GeyserImpl.NAME); } + if (ConnectionTestCommand.CONNECTION_TEST_MOTD != null) { + // Force-override as we are testing the connection and want to verify we are connecting to the right server through the MOTD + pong.motd(ConnectionTestCommand.CONNECTION_TEST_MOTD); + pong.subMotd(GeyserImpl.NAME); + } + // The ping will not appear if the MOTD + sub-MOTD is of a certain length. // We don't know why, though byte[] motdArray = pong.motd().getBytes(StandardCharsets.UTF_8); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java index 6b210b808..bdd76f518 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java @@ -285,7 +285,7 @@ public class BedrockActionTranslator extends PacketTranslator Date: Wed, 6 Sep 2023 20:19:51 +0200 Subject: [PATCH 066/344] Remove blockstate version (#4011) * Remove blockstate version * Regr, add comment why version tag is removed --- .../geyser/entity/type/ItemFrameEntity.java | 3 +-- .../populator/BlockRegistryPopulator.java | 16 +++++++--------- .../populator/CustomBlockRegistryPopulator.java | 6 ++---- .../geyser/registry/type/BlockMappings.java | 2 -- 4 files changed, 10 insertions(+), 17 deletions(-) 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 eb9329bcd..295972200 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 @@ -83,8 +83,7 @@ public class ItemFrameEntity extends Entity { super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); NbtMapBuilder blockBuilder = NbtMap.builder() - .putString("name", this.definition.entityType() == EntityType.GLOW_ITEM_FRAME ? "minecraft:glow_frame" : "minecraft:frame") - .putInt("version", session.getBlockMappings().getBlockStateVersion()); + .putString("name", this.definition.entityType() == EntityType.GLOW_ITEM_FRAME ? "minecraft:glow_frame" : "minecraft:frame"); NbtMapBuilder statesBuilder = NbtMap.builder() .putInt("facing_direction", direction.ordinal()) .putByte("item_frame_map_bit", (byte) 0) 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 d3a72d017..49b3b6b7a 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 @@ -147,6 +147,7 @@ public final class BlockRegistryPopulator { vanillaBlockStates = new ArrayList<>(blockPalette.getList("blocks", NbtType.COMPOUND)); for (int i = 0; i < vanillaBlockStates.size(); i++) { NbtMapBuilder builder = vanillaBlockStates.get(i).toBuilder(); + builder.remove("version"); // Remove all nbt tags which are not needed for differentiating states builder.remove("name_hash"); // Quick workaround - was added in 1.19.20 builder.remove("network_id"); // Added in 1.19.80 - ???? builder.putCompound("states", statesInterner.intern((NbtMap) builder.remove("states"))); @@ -157,7 +158,6 @@ public final class BlockRegistryPopulator { } catch (Exception e) { throw new AssertionError("Unable to get blocks from runtime block states", e); } - int stateVersion = vanillaBlockStates.get(0).getInt("version"); List customBlockProperties = new ArrayList<>(); List customBlockStates = new ArrayList<>(); @@ -166,7 +166,7 @@ public final class BlockRegistryPopulator { if (BlockRegistries.CUSTOM_BLOCKS.get().length != 0) { for (CustomBlockData customBlock : BlockRegistries.CUSTOM_BLOCKS.get()) { customBlockProperties.add(CustomBlockRegistryPopulator.generateBlockPropertyData(customBlock, protocolVersion)); - CustomBlockRegistryPopulator.generateCustomBlockStates(customBlock, customBlockStates, customExtBlockStates, stateVersion); + CustomBlockRegistryPopulator.generateCustomBlockStates(customBlock, customBlockStates, customExtBlockStates); } blockStates.addAll(customBlockStates); GeyserImpl.getInstance().getLogger().debug("Added " + customBlockStates.size() + " custom block states to v" + protocolVersion + " palette."); @@ -237,7 +237,7 @@ public final class BlockRegistryPopulator { javaRuntimeId++; Map.Entry entry = blocksIterator.next(); String javaId = entry.getKey(); - GeyserBedrockBlock vanillaBedrockDefinition = blockStateOrderedMap.get(buildBedrockState(entry.getValue(), stateVersion, stateMapper)); + GeyserBedrockBlock vanillaBedrockDefinition = blockStateOrderedMap.get(buildBedrockState(entry.getValue(), stateMapper)); GeyserBedrockBlock bedrockDefinition; CustomBlockState blockStateOverride = BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.get(javaRuntimeId); @@ -245,7 +245,7 @@ public final class BlockRegistryPopulator { bedrockDefinition = vanillaBedrockDefinition; if (bedrockDefinition == null) { throw new RuntimeException("Unable to find " + javaId + " Bedrock runtime ID! Built NBT tag: \n" + - palette.getKey().key() + buildBedrockState(entry.getValue(), stateVersion, stateMapper)); + palette.getKey().key() + buildBedrockState(entry.getValue(), stateMapper)); } } else { bedrockDefinition = customBlockStateDefinitions.get(blockStateOverride); @@ -341,8 +341,7 @@ public final class BlockRegistryPopulator { } }); - BlockRegistries.BLOCKS.register(palette.getKey().valueInt(), builder.blockStateVersion(stateVersion) - .bedrockRuntimeMap(bedrockRuntimeMap) + BlockRegistries.BLOCKS.register(palette.getKey().valueInt(), builder.bedrockRuntimeMap(bedrockRuntimeMap) .javaToBedrockBlocks(javaToBedrockBlocks) .javaToVanillaBedrockBlocks(javaToVanillaBedrockBlocks) .stateDefinitionMap(blockStateOrderedMap) @@ -579,11 +578,10 @@ public final class BlockRegistryPopulator { return blockStateSet; } - private static NbtMap buildBedrockState(JsonNode node, int blockStateVersion, BiFunction statesMapper) { + private static NbtMap buildBedrockState(JsonNode node, BiFunction statesMapper) { NbtMapBuilder tagBuilder = NbtMap.builder(); String bedrockIdentifier = node.get("bedrock_identifier").textValue(); - tagBuilder.putString("name", bedrockIdentifier) - .putInt("version", blockStateVersion); + tagBuilder.putString("name", bedrockIdentifier); NbtMapBuilder statesBuilder = NbtMap.builder(); diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java index 504db753d..ca9d40ef6 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java @@ -199,10 +199,9 @@ public class CustomBlockRegistryPopulator { * * @param customBlock the custom block data to generate states for * @param blockStates the list of NBT maps to append the custom block states to - * @param customExtBlockStates the list of custom block states to append the custom block states to - * @param stateVersion the state version to use for the custom block states + * @param customExtBlockStates the list of custom block states to append the custom block states to */ - static void generateCustomBlockStates(CustomBlockData customBlock, List blockStates, List customExtBlockStates, int stateVersion) { + static void generateCustomBlockStates(CustomBlockData customBlock, List blockStates, List customExtBlockStates) { int totalPermutations = 1; for (CustomBlockProperty property : customBlock.properties().values()) { totalPermutations *= property.values().size(); @@ -219,7 +218,6 @@ public class CustomBlockRegistryPopulator { blockStates.add(NbtMap.builder() .putString("name", customBlock.identifier()) - .putInt("version", stateVersion) .putCompound("states", states) .build()); customExtBlockStates.add(new GeyserCustomBlockState(customBlock, states)); 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 3c33ea097..80be3fbce 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 @@ -46,8 +46,6 @@ public class BlockMappings implements DefinitionRegistry { BlockDefinition bedrockWater; BlockDefinition bedrockMovingBlock; - int blockStateVersion; - GeyserBedrockBlock[] javaToBedrockBlocks; GeyserBedrockBlock[] javaToVanillaBedrockBlocks; From 3ec591509c6998221a23546d2db396fac28ab747 Mon Sep 17 00:00:00 2001 From: chris Date: Thu, 7 Sep 2023 00:13:19 +0200 Subject: [PATCH 067/344] Fix forced zoom issue when switching into spectator mode (#4093) * init: spectator mode support * properly set second abilitylayer for spectator mode * Fixes https://github.com/GeyserMC/Geyser/issues/3318 by not sending changed flags in spectator mode --- .../entity/type/living/ArmorStandEntity.java | 2 +- .../type/player/SessionPlayerEntity.java | 12 ++++- .../geyser/session/GeyserSession.java | 44 ++++++++++++------- .../protocol/java/JavaLoginTranslator.java | 3 +- .../protocol/java/JavaRespawnTranslator.java | 3 +- .../java/level/JavaGameEventTranslator.java | 3 +- .../org/geysermc/geyser/util/EntityUtils.java | 15 +++++++ 7 files changed, 60 insertions(+), 22 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java index 903f08b64..c9018fe76 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java @@ -249,7 +249,7 @@ public class ArmorStandEntity extends LivingEntity { @Override public InteractionResult interactAt(Hand hand) { if (!isMarker && session.getPlayerInventory().getItemInHand(hand).asItem() != Items.NAME_TAG) { - // Java Edition returns SUCCESS if in spectator mode, but this is overrided with an earlier check on the client + // Java Edition returns SUCCESS if in spectator mode, but this is overridden with an earlier check on the client return InteractionResult.CONSUME; } else { return InteractionResult.PASS; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java index 540aa989f..bcd32253f 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java @@ -30,6 +30,7 @@ import com.github.steveice10.mc.protocol.data.game.entity.attribute.AttributeTyp import com.github.steveice10.mc.protocol.data.game.entity.metadata.GlobalPos; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose; import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; +import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import lombok.Getter; import org.cloudburstmc.math.vector.Vector3f; @@ -109,10 +110,17 @@ public class SessionPlayerEntity extends PlayerEntity { this.position = position; } + /** + * Sending any updated flags (sprinting, onFire, etc.) to the client while in spectator is not needed + * Also "fixes" https://github.com/GeyserMC/Geyser/issues/3318 + */ @Override public void setFlags(ByteEntityMetadata entityMetadata) { - super.setFlags(entityMetadata); - session.setSwimmingInWater((entityMetadata.getPrimitiveValue() & 0x10) == 0x10 && getFlag(EntityFlag.SPRINTING)); + // TODO: proper fix, BDS somehow does it? https://paste.gg/p/anonymous/3adfb7612f1540be80fa03a2281f93dc (BDS 1.20.13) + if (!this.session.getGameMode().equals(GameMode.SPECTATOR)) { + super.setFlags(entityMetadata); + session.setSwimmingInWater((entityMetadata.getPrimitiveValue() & 0x10) == 0x10 && getFlag(EntityFlag.SPRINTING)); + } refreshSpeed = true; } diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 9cfc29889..f7d362e0d 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -98,20 +98,20 @@ import org.cloudburstmc.protocol.common.util.OptionalBoolean; import org.geysermc.api.util.BedrockPlatform; import org.geysermc.api.util.InputMode; import org.geysermc.api.util.UiProfile; -import org.geysermc.geyser.api.bedrock.camera.CameraShake; -import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.cumulus.form.Form; import org.geysermc.cumulus.form.util.FormBuilder; import org.geysermc.floodgate.crypto.FloodgateCipher; import org.geysermc.floodgate.util.BedrockData; import org.geysermc.geyser.Constants; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.bedrock.camera.CameraShake; import org.geysermc.geyser.api.connection.GeyserConnection; import org.geysermc.geyser.api.entity.type.GeyserEntity; import org.geysermc.geyser.api.entity.type.player.GeyserPlayerEntity; import org.geysermc.geyser.api.event.bedrock.SessionLoginEvent; import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.api.network.RemoteServer; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.configuration.EmoteOffhandWorkaroundOption; import org.geysermc.geyser.configuration.GeyserConfiguration; @@ -131,7 +131,6 @@ import org.geysermc.geyser.item.Items; import org.geysermc.geyser.level.JavaDimension; import org.geysermc.geyser.level.WorldManager; import org.geysermc.geyser.level.physics.CollisionManager; -import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.network.netty.LocalSession; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.type.BlockMappings; @@ -147,6 +146,7 @@ import org.geysermc.geyser.translator.inventory.InventoryTranslator; import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.util.ChunkUtils; import org.geysermc.geyser.util.DimensionUtils; +import org.geysermc.geyser.util.EntityUtils; import org.geysermc.geyser.util.LoginEncryptionUtils; import org.jetbrains.annotations.NotNull; @@ -1516,11 +1516,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { StartGamePacket startGamePacket = new StartGamePacket(); startGamePacket.setUniqueEntityId(playerEntity.getGeyserId()); startGamePacket.setRuntimeEntityId(playerEntity.getGeyserId()); - startGamePacket.setPlayerGameType(switch (gameMode) { - case CREATIVE -> GameType.CREATIVE; - case ADVENTURE -> GameType.ADVENTURE; - default -> GameType.SURVIVAL; - }); + startGamePacket.setPlayerGameType(EntityUtils.toBedrockGamemode(gameMode)); startGamePacket.setPlayerPosition(Vector3f.from(0, 69, 0)); startGamePacket.setRotation(Vector2f.from(1, 1)); @@ -1756,7 +1752,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { AbilityLayer abilityLayer = new AbilityLayer(); Set abilities = abilityLayer.getAbilityValues(); - if (canFly || spectator) { + if (canFly) { abilities.add(Ability.MAY_FLY); } @@ -1790,15 +1786,31 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { } if (spectator) { - abilities.add(Ability.NO_CLIP); + AbilityLayer spectatorLayer = new AbilityLayer(); + spectatorLayer.setLayerType(AbilityLayer.Type.SPECTATOR); + // Setting all abilitySet causes the zoom issue... BDS only sends these, so ig we will too + Set abilitySet = spectatorLayer.getAbilitiesSet(); + abilitySet.add(Ability.BUILD); + abilitySet.add(Ability.MINE); + abilitySet.add(Ability.DOORS_AND_SWITCHES); + abilitySet.add(Ability.OPEN_CONTAINERS); + abilitySet.add(Ability.ATTACK_PLAYERS); + abilitySet.add(Ability.ATTACK_MOBS); + abilitySet.add(Ability.INVULNERABLE); + abilitySet.add(Ability.FLYING); + abilitySet.add(Ability.MAY_FLY); + abilitySet.add(Ability.INSTABUILD); + abilitySet.add(Ability.NO_CLIP); + + Set abilityValues = spectatorLayer.getAbilityValues(); + abilityValues.add(Ability.INVULNERABLE); + abilityValues.add(Ability.FLYING); + abilityValues.add(Ability.NO_CLIP); + + updateAbilitiesPacket.getAbilityLayers().add(spectatorLayer); } - // https://github.com/GeyserMC/Geyser/issues/3769 Setting Spectator mode ability layer - if (spectator) { - abilityLayer.setLayerType(AbilityLayer.Type.SPECTATOR); - } else { - abilityLayer.setLayerType(AbilityLayer.Type.BASE); - } + abilityLayer.setLayerType(AbilityLayer.Type.BASE); abilityLayer.setFlySpeed(flySpeed); // https://github.com/GeyserMC/Geyser/issues/3139 as of 1.19.10 abilityLayer.setWalkSpeed(walkSpeed == 0f ? 0.01f : walkSpeed); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java index 9f7fd4f40..135e9ed01 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java @@ -45,6 +45,7 @@ import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.util.ChunkUtils; import org.geysermc.geyser.util.DimensionUtils; +import org.geysermc.geyser.util.EntityUtils; import org.geysermc.geyser.util.JavaCodecUtil; import org.geysermc.geyser.util.PluginMessageUtils; @@ -113,7 +114,7 @@ public class JavaLoginTranslator extends PacketTranslator { @@ -59,7 +60,7 @@ public class JavaRespawnTranslator extends PacketTranslator { @@ -105,7 +106,7 @@ public class JavaGameEventTranslator extends PacketTranslator GameType.CREATIVE; + case ADVENTURE -> GameType.ADVENTURE; + case SPECTATOR -> GameType.SPECTATOR; + default -> GameType.SURVIVAL; + }; + } + private EntityUtils() { } } From acf24d4d6bf8d58f5c8bec634b70707689ff3c62 Mon Sep 17 00:00:00 2001 From: chris Date: Thu, 7 Sep 2023 09:07:42 +0200 Subject: [PATCH 068/344] Revert sending actionbar messages as jukebox, avoid pink system chat overlays (#4066) System chat overlays too aren't pink anymore - they're still sent as jukebox for better visibility though. --- .../protocol/java/JavaSystemChatTranslator.java | 7 ++++++- .../title/JavaSetActionBarTextTranslator.java | 17 +++++++---------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaSystemChatTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaSystemChatTranslator.java index c1f318645..e400773c8 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaSystemChatTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaSystemChatTranslator.java @@ -29,6 +29,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundSy import net.kyori.adventure.text.TranslatableComponent; import org.cloudburstmc.protocol.bedrock.packet.TextPacket; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; @@ -55,7 +56,11 @@ public class JavaSystemChatTranslator extends PacketTranslator Date: Sat, 9 Sep 2023 00:13:57 +0200 Subject: [PATCH 069/344] Fix: Update inventory names (#4106) Ensure inventory name updates used for e.g. JsonUI work properly. --- .../protocol/java/inventory/JavaOpenScreenTranslator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaOpenScreenTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaOpenScreenTranslator.java index fd733773e..3a18e0b78 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaOpenScreenTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaOpenScreenTranslator.java @@ -73,7 +73,8 @@ public class JavaOpenScreenTranslator extends PacketTranslator Date: Sat, 9 Sep 2023 00:34:19 +0200 Subject: [PATCH 070/344] Feature: Allow client-side "game settings" menu gamemode/difficulty changes (#4062) Removes difficulty/Gamemode settings from the custom server settings form since these are now present in the client side settings. --- .../world/GeyserFabricWorldManager.java | 6 +++ .../manager/GeyserSpigotWorldManager.java | 6 +++ .../geyser/level/GeyserWorldManager.java | 6 +++ .../geysermc/geyser/level/WorldManager.java | 18 +++++++ .../geyser/network/LoggingPacketHandler.java | 5 ++ .../registry/PacketTranslatorRegistry.java | 2 + .../BedrockSetDefaultGameTypeTranslator.java | 53 +++++++++++++++++++ .../BedrockSetDifficultyTranslator.java | 48 +++++++++++++++++ .../BedrockSetPlayerGameTypeTranslator.java | 30 +++++++++-- .../geysermc/geyser/util/SettingsUtils.java | 31 ----------- 10 files changed, 169 insertions(+), 36 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetDefaultGameTypeTranslator.java create mode 100644 core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetDifficultyTranslator.java diff --git a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/world/GeyserFabricWorldManager.java b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/world/GeyserFabricWorldManager.java index 9cd01f993..923db9b25 100644 --- a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/world/GeyserFabricWorldManager.java +++ b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/world/GeyserFabricWorldManager.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.platform.fabric.world; +import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityInfo; import me.lucko.fabric.api.permissions.v0.Permissions; import net.minecraft.core.BlockPos; @@ -153,6 +154,11 @@ public class GeyserFabricWorldManager extends GeyserWorldManager { return Permissions.check(player, permission); } + @Override + public GameMode getDefaultGameMode(GeyserSession session) { + return GameMode.byId(server.getDefaultGameType().getId()); + } + @Nonnull @Override public CompletableFuture getPickItemNbt(GeyserSession session, int x, int y, int z, boolean addNbtData) { diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java index 056747d6a..c8ccfffd7 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.platform.spigot.world.manager; +import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityInfo; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.bukkit.Bukkit; @@ -171,6 +172,11 @@ public class GeyserSpigotWorldManager extends WorldManager { return gameRule.getDefaultIntValue(); } + @Override + public GameMode getDefaultGameMode(GeyserSession session) { + return GameMode.byId(Bukkit.getDefaultGameMode().ordinal()); + } + @Override public boolean hasPermission(GeyserSession session, String permission) { return Bukkit.getPlayer(session.getPlayerEntity().getUsername()).hasPermission(permission); diff --git a/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java b/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java index 8d4b3f2e6..a8e2d00ae 100644 --- a/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java +++ b/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.level; +import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityInfo; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; @@ -160,6 +161,11 @@ public class GeyserWorldManager extends WorldManager { return gameRule.getDefaultIntValue(); } + @Override + public GameMode getDefaultGameMode(GeyserSession session) { + return GameMode.SURVIVAL; + } + @Override public boolean hasPermission(GeyserSession session, String permission) { return false; diff --git a/core/src/main/java/org/geysermc/geyser/level/WorldManager.java b/core/src/main/java/org/geysermc/geyser/level/WorldManager.java index 006caff55..a4de993d2 100644 --- a/core/src/main/java/org/geysermc/geyser/level/WorldManager.java +++ b/core/src/main/java/org/geysermc/geyser/level/WorldManager.java @@ -170,6 +170,24 @@ public abstract class WorldManager { session.sendCommand("gamemode " + gameMode.name().toLowerCase(Locale.ROOT)); } + /** + * Get the default game mode of the server + * + * @param session the player requesting the default game mode + * @return the default game mode of the server, or Survival if unknown. + */ + public abstract GameMode getDefaultGameMode(GeyserSession session); + + /** + * Change the default game mode of the session's server + * + * @param session the player making the change + * @param gameMode the new default game mode + */ + public void setDefaultGameMode(GeyserSession session, GameMode gameMode) { + session.sendCommand("defaultgamemode " + gameMode.name().toLowerCase(Locale.ROOT)); + } + /** * Change the difficulty of the Java server * diff --git a/core/src/main/java/org/geysermc/geyser/network/LoggingPacketHandler.java b/core/src/main/java/org/geysermc/geyser/network/LoggingPacketHandler.java index 59b34af16..61c8dbe3d 100644 --- a/core/src/main/java/org/geysermc/geyser/network/LoggingPacketHandler.java +++ b/core/src/main/java/org/geysermc/geyser/network/LoggingPacketHandler.java @@ -255,6 +255,11 @@ public class LoggingPacketHandler implements BedrockPacketHandler { return defaultHandler(packet); } + @Override + public PacketSignal handle(RequestPermissionsPacket packet) { + return defaultHandler(packet); + } + @Override public PacketSignal handle(ResourcePackChunkRequestPacket packet) { return defaultHandler(packet); diff --git a/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java b/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java index 61999d4f6..dbc8e2e26 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java +++ b/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java @@ -29,6 +29,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundDe import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundTabListPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundLightUpdatePacket; import io.netty.channel.EventLoop; +import org.cloudburstmc.protocol.bedrock.packet.RequestPermissionsPacket; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.registry.loader.RegistryLoaders; import org.geysermc.geyser.session.GeyserSession; @@ -46,6 +47,7 @@ public class PacketTranslatorRegistry extends AbstractMappedRegistry { + + /** + * Sets the default game mode for the server via the Bedrock client's "world" menu (given sufficient permissions). + */ + @Override + public void translate(GeyserSession session, SetDefaultGameTypePacket packet) { + if (session.getOpPermissionLevel() >= 2 || session.hasPermission("geyser.settings.server")) { + session.getGeyser().getWorldManager().setDefaultGameMode(session, GameMode.byId(packet.getGamemode())); + } + // Stop the client from updating their own Gamemode without telling the server + // Can occur when client Gamemode is set to "default", and default game mode is changed. + SetPlayerGameTypePacket playerGameTypePacket = new SetPlayerGameTypePacket(); + playerGameTypePacket.setGamemode(EntityUtils.toBedrockGamemode(session.getGameMode()).ordinal()); + session.sendUpstreamPacket(playerGameTypePacket); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetDifficultyTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetDifficultyTranslator.java new file mode 100644 index 000000000..a36aa77df --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetDifficultyTranslator.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2019-2023 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.translator.protocol.bedrock.entity.player; + +import com.github.steveice10.mc.protocol.data.game.setting.Difficulty; +import org.cloudburstmc.protocol.bedrock.packet.SetDifficultyPacket; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.protocol.PacketTranslator; +import org.geysermc.geyser.translator.protocol.Translator; + +@Translator(packet = SetDifficultyPacket.class) +public class BedrockSetDifficultyTranslator extends PacketTranslator { + + /** + * Sets the Java server's difficulty via the Bedrock client's "world" menu (given sufficient permissions). + */ + @Override + public void translate(GeyserSession session, SetDifficultyPacket packet) { + if (session.getOpPermissionLevel() >= 2 || session.hasPermission("geyser.settings.server")) { + if (packet.getDifficulty() != session.getWorldCache().getDifficulty().ordinal()) { + session.getGeyser().getWorldManager().setDifficulty(session, Difficulty.from(packet.getDifficulty())); + } + } + } +} diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetPlayerGameTypeTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetPlayerGameTypeTranslator.java index 70768af34..a1c2c2987 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetPlayerGameTypeTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockSetPlayerGameTypeTranslator.java @@ -25,23 +25,43 @@ package org.geysermc.geyser.translator.protocol.bedrock.entity.player; +import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; import org.cloudburstmc.protocol.bedrock.packet.SetPlayerGameTypePacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; +import org.geysermc.geyser.util.EntityUtils; /** * In vanilla Bedrock, if you have operator status, this sets the player's gamemode without confirmation from the server. - * Since we have a custom server option to request the gamemode, we just reset the gamemode and ignore this. + * With operator status, the Gamemode change is sent to the Java server, if it is not present, the gamemode is not changed. */ @Translator(packet = SetPlayerGameTypePacket.class) public class BedrockSetPlayerGameTypeTranslator extends PacketTranslator { + /** + * Sets client game mode for the server via the Bedrock client's "world" menu (given sufficient permissions). + */ @Override public void translate(GeyserSession session, SetPlayerGameTypePacket packet) { - // no - SetPlayerGameTypePacket playerGameTypePacket = new SetPlayerGameTypePacket(); - playerGameTypePacket.setGamemode(session.getGameMode().ordinal()); - session.sendUpstreamPacket(playerGameTypePacket); + // yes, if you are OP + if (session.getOpPermissionLevel() >= 2 || session.hasPermission("geyser.settings.server")) { + if (packet.getGamemode() != session.getGameMode().ordinal()) { + // Bedrock has more Gamemodes than Java, leading to cases 5 (for "default") and 6 (for "spectator") being sent + // https://github.com/CloudburstMC/Protocol/blob/3.0/bedrock-codec/src/main/java/org/cloudburstmc/protocol/bedrock/data/GameType.java + GameMode gameMode = switch (packet.getGamemode()) { + case 1 -> GameMode.CREATIVE; + case 2 -> GameMode.ADVENTURE; + case 5 -> session.getGeyser().getWorldManager().getDefaultGameMode(session); + case 6 -> GameMode.SPECTATOR; + default -> GameMode.SURVIVAL; + }; + session.getGeyser().getWorldManager().setPlayerGameMode(session, gameMode); + } + } else { + SetPlayerGameTypePacket playerGameTypePacket = new SetPlayerGameTypePacket(); + playerGameTypePacket.setGamemode(EntityUtils.toBedrockGamemode(session.getGameMode()).ordinal()); + session.sendUpstreamPacket(playerGameTypePacket); + } } } diff --git a/core/src/main/java/org/geysermc/geyser/util/SettingsUtils.java b/core/src/main/java/org/geysermc/geyser/util/SettingsUtils.java index 5957fb9d9..8a8d684f6 100644 --- a/core/src/main/java/org/geysermc/geyser/util/SettingsUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/SettingsUtils.java @@ -25,8 +25,6 @@ package org.geysermc.geyser.util; -import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; -import com.github.steveice10.mc.protocol.data.game.setting.Difficulty; import org.geysermc.cumulus.component.DropdownComponent; import org.geysermc.cumulus.form.CustomForm; import org.geysermc.geyser.GeyserImpl; @@ -77,23 +75,6 @@ public class SettingsUtils { } } - boolean canModifyServer = session.getOpPermissionLevel() >= 2 || session.hasPermission("geyser.settings.server"); - if (canModifyServer) { - builder.label("geyser.settings.title.server"); - - DropdownComponent.Builder gamemodeDropdown = DropdownComponent.builder("%createWorldScreen.gameMode.personal"); - for (GameMode gamemode : GameMode.values()) { - gamemodeDropdown.option("selectWorld.gameMode." + gamemode.name().toLowerCase(), session.getGameMode() == gamemode); - } - builder.dropdown(gamemodeDropdown); - - DropdownComponent.Builder difficultyDropdown = DropdownComponent.builder("%options.difficulty"); - for (Difficulty difficulty : Difficulty.values()) { - difficultyDropdown.option("%options.difficulty." + difficulty.name().toLowerCase(), session.getWorldCache().getDifficulty() == difficulty); - } - builder.dropdown(difficultyDropdown); - } - boolean showGamerules = session.getOpPermissionLevel() >= 2 || session.hasPermission("geyser.settings.gamerules"); if (showGamerules) { builder.label("geyser.settings.title.game_rules") @@ -128,18 +109,6 @@ public class SettingsUtils { } } - if (canModifyServer) { - GameMode gameMode = GameMode.values()[(int) response.next()]; - if (gameMode != null && gameMode != session.getGameMode()) { - session.getGeyser().getWorldManager().setPlayerGameMode(session, gameMode); - } - - Difficulty difficulty = Difficulty.values()[(int) response.next()]; - if (difficulty != null && difficulty != session.getWorldCache().getDifficulty()) { - session.getGeyser().getWorldManager().setDifficulty(session, difficulty); - } - } - if (showGamerules) { for (GameRule gamerule : GameRule.VALUES) { if (Boolean.class.equals(gamerule.getType())) { From c67d50c13ed90f79e92c0390bb7b2fa571b0b64a Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sat, 9 Sep 2023 13:23:19 -0400 Subject: [PATCH 071/344] Some formatting fixes and creative menu fix --- .gitignore | 1 + .../populator/BlockRegistryPopulator.java | 31 ++++---- .../CreativeItemRegistryPopulator.java | 3 +- .../CustomBlockRegistryPopulator.java | 74 +++++++++++-------- .../CustomSkullRegistryPopulator.java | 4 +- .../populator/ItemRegistryPopulator.java | 9 +-- 6 files changed, 65 insertions(+), 57 deletions(-) diff --git a/.gitignore b/.gitignore index 2b7e2972c..a44afd242 100644 --- a/.gitignore +++ b/.gitignore @@ -251,3 +251,4 @@ locales/ /saved-refresh-tokens.json /custom_mappings/ /languages/ +/custom-skulls.yml \ No newline at end of file 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 49b3b6b7a..8e6f56bfe 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 @@ -34,7 +34,6 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.*; import org.cloudburstmc.nbt.*; -import org.cloudburstmc.protocol.bedrock.codec.v582.Bedrock_v582; import org.cloudburstmc.protocol.bedrock.data.BlockPropertyData; import org.cloudburstmc.protocol.bedrock.codec.v589.Bedrock_v589; import org.cloudburstmc.protocol.bedrock.codec.v594.Bedrock_v594; @@ -74,10 +73,9 @@ public final class BlockRegistryPopulator { public static void populate(Stage stage) { switch (stage) { - case PRE_INIT -> { nullifyBlocksNode(); } + case PRE_INIT, POST_INIT -> { nullifyBlocksNode(); } case INIT_JAVA -> { registerJavaBlocks(); } case INIT_BEDROCK -> { registerBedrockBlocks(); } - case POST_INIT -> { nullifyBlocksNode(); } default -> { throw new IllegalArgumentException("Unknown stage: " + stage); } } } @@ -86,9 +84,8 @@ public final class BlockRegistryPopulator { * Stores the raw blocks JSON until it is no longer needed. */ private static JsonNode BLOCKS_JSON; - private static int minCustomRuntimeID = -1; - private static int maxCustomRuntimeID = -1; - private static int javaBlocksSize = -1; + private static int MIN_CUSTOM_RUNTIME_ID = -1; + private static int JAVA_BLOCKS_SIZE = -1; private static void nullifyBlocksNode() { BLOCKS_JSON = null; @@ -224,8 +221,8 @@ public final class BlockRegistryPopulator { BiFunction stateMapper = blockMappers.getOrDefault(palette.getKey(), emptyMapper); - GeyserBedrockBlock[] javaToBedrockBlocks = new GeyserBedrockBlock[javaBlocksSize]; - GeyserBedrockBlock[] javaToVanillaBedrockBlocks = new GeyserBedrockBlock[javaBlocksSize]; + GeyserBedrockBlock[] javaToBedrockBlocks = new GeyserBedrockBlock[JAVA_BLOCKS_SIZE]; + GeyserBedrockBlock[] javaToVanillaBedrockBlocks = new GeyserBedrockBlock[JAVA_BLOCKS_SIZE]; Map flowerPotBlocks = new Object2ObjectOpenHashMap<>(); Map itemFrames = new Object2ObjectOpenHashMap<>(); @@ -309,8 +306,8 @@ public final class BlockRegistryPopulator { Map nonVanillaStateOverrides = BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get(); if (nonVanillaStateOverrides.size() > 0) { // First ensure all non vanilla runtime IDs at minimum are air in case they aren't consecutive - Arrays.fill(javaToVanillaBedrockBlocks, minCustomRuntimeID, javaToVanillaBedrockBlocks.length, airDefinition); - Arrays.fill(javaToBedrockBlocks, minCustomRuntimeID, javaToBedrockBlocks.length, airDefinition); + Arrays.fill(javaToVanillaBedrockBlocks, MIN_CUSTOM_RUNTIME_ID, javaToVanillaBedrockBlocks.length, airDefinition); + Arrays.fill(javaToBedrockBlocks, MIN_CUSTOM_RUNTIME_ID, javaToBedrockBlocks.length, airDefinition); for (Map.Entry entry : nonVanillaStateOverrides.entrySet()) { GeyserBedrockBlock bedrockDefinition = customBlockStateDefinitions.get(entry.getValue()); @@ -364,20 +361,20 @@ public final class BlockRegistryPopulator { throw new AssertionError("Unable to load Java block mappings", e); } - javaBlocksSize = blocksJson.size(); + JAVA_BLOCKS_SIZE = blocksJson.size(); if (BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().size() > 0) { - minCustomRuntimeID = BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().keySet().stream().min(Comparator.comparing(JavaBlockState::javaId)).get().javaId(); - maxCustomRuntimeID = BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().keySet().stream().max(Comparator.comparing(JavaBlockState::javaId)).get().javaId(); + MIN_CUSTOM_RUNTIME_ID = BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().keySet().stream().min(Comparator.comparing(JavaBlockState::javaId)).get().javaId(); + int maxCustomRuntimeID = BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().keySet().stream().max(Comparator.comparing(JavaBlockState::javaId)).get().javaId(); - if (minCustomRuntimeID < blocksJson.size()) { - throw new RuntimeException("Non vanilla custom block state overrides runtime ID must start after the last vanilla block state (" + javaBlocksSize + ")"); + if (MIN_CUSTOM_RUNTIME_ID < blocksJson.size()) { + throw new RuntimeException("Non vanilla custom block state overrides runtime ID must start after the last vanilla block state (" + JAVA_BLOCKS_SIZE + ")"); } - javaBlocksSize = maxCustomRuntimeID + 1; // Runtime ids start at 0, so we need to add 1 + JAVA_BLOCKS_SIZE = maxCustomRuntimeID + 1; // Runtime ids start at 0, so we need to add 1 } - BlockRegistries.JAVA_BLOCKS.set(new BlockMapping[javaBlocksSize]); // Set array size to number of blockstates + BlockRegistries.JAVA_BLOCKS.set(new BlockMapping[JAVA_BLOCKS_SIZE]); // Set array size to number of blockstates Deque cleanIdentifiers = new ArrayDeque<>(); 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 index 8998b41a1..6944bbcc3 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/CreativeItemRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/CreativeItemRegistryPopulator.java @@ -26,8 +26,6 @@ package org.geysermc.geyser.registry.populator; import com.fasterxml.jackson.databind.JsonNode; -import it.unimi.dsi.fastutil.objects.Object2ObjectMap; -import it.unimi.dsi.fastutil.objects.Object2ObjectMaps; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtUtils; @@ -124,6 +122,7 @@ public class CreativeItemRegistryPopulator { NbtMapBuilder builder = stateTag.toBuilder(); builder.remove("name_hash"); builder.remove("network_id"); + builder.remove("version"); blockDefinition = blockMappings.getDefinition(builder.build()); } catch (IOException e) { diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java index ca9d40ef6..c9ed51166 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java @@ -70,21 +70,21 @@ public class CustomBlockRegistryPopulator { } } - private static Set customBlocks; - private static Set customBlockNames; - private static Int2ObjectMap blockStateOverrides; - private static Map customBlockItemOverrides; - private static Map nonVanillaBlockStateOverrides; + private static Set CUSTOM_BLOCKS; + private static Set CUSTOM_BLOCK_NAMES; + private static Int2ObjectMap BLOCK_STATE_OVERRIDES; + private static Map CUSTOM_BLOCK_ITEM_OVERRIDES; + private static Map NON_VANILLA_BLOCK_STATE_OVERRIDES; /** * Initializes custom blocks defined by API */ private static void populateBedrock() { - customBlocks = new ObjectOpenHashSet<>(); - customBlockNames = new ObjectOpenHashSet<>(); - blockStateOverrides = new Int2ObjectOpenHashMap<>(); - customBlockItemOverrides = new HashMap<>(); - nonVanillaBlockStateOverrides = new HashMap<>(); + CUSTOM_BLOCKS = new ObjectOpenHashSet<>(); + CUSTOM_BLOCK_NAMES = new ObjectOpenHashSet<>(); + BLOCK_STATE_OVERRIDES = new Int2ObjectOpenHashMap<>(); + CUSTOM_BLOCK_ITEM_OVERRIDES = new HashMap<>(); + NON_VANILLA_BLOCK_STATE_OVERRIDES = new HashMap<>(); GeyserImpl.getInstance().getEventBus().fire(new GeyserDefineCustomBlocksEvent() { @Override @@ -92,13 +92,13 @@ public class CustomBlockRegistryPopulator { if (customBlockData.name().length() == 0) { throw new IllegalArgumentException("Custom block name must have at least 1 character."); } - if (!customBlockNames.add(customBlockData.name())) { + if (!CUSTOM_BLOCK_NAMES.add(customBlockData.name())) { throw new IllegalArgumentException("Another custom block was already registered under the name: " + customBlockData.name()); } if (Character.isDigit(customBlockData.name().charAt(0))) { throw new IllegalArgumentException("Custom block can not start with a digit. Name: " + customBlockData.name()); } - customBlocks.add(customBlockData); + CUSTOM_BLOCKS.add(customBlockData); } @Override @@ -107,10 +107,10 @@ public class CustomBlockRegistryPopulator { if (id == -1) { throw new IllegalArgumentException("Unknown Java block state. Identifier: " + javaIdentifier); } - if (!customBlocks.contains(customBlockState.block())) { + if (!CUSTOM_BLOCKS.contains(customBlockState.block())) { throw new IllegalArgumentException("Custom block is unregistered. Name: " + customBlockState.name()); } - CustomBlockState oldBlockState = blockStateOverrides.put(id, customBlockState); + CustomBlockState oldBlockState = BLOCK_STATE_OVERRIDES.put(id, customBlockState); if (oldBlockState != null) { GeyserImpl.getInstance().getLogger().debug("Duplicate block state override for Java Identifier: " + javaIdentifier + " Old override: " + oldBlockState.name() + " New override: " + customBlockState.name()); @@ -119,18 +119,18 @@ public class CustomBlockRegistryPopulator { @Override public void registerItemOverride(@NonNull String javaIdentifier, @NonNull CustomBlockData customBlockData) { - if (!customBlocks.contains(customBlockData)) { + if (!CUSTOM_BLOCKS.contains(customBlockData)) { throw new IllegalArgumentException("Custom block is unregistered. Name: " + customBlockData.name()); } - customBlockItemOverrides.put(javaIdentifier, customBlockData); + CUSTOM_BLOCK_ITEM_OVERRIDES.put(javaIdentifier, customBlockData); } @Override public void registerOverride(@NonNull JavaBlockState javaBlockState, @NonNull CustomBlockState customBlockState) { - if (!customBlocks.contains(customBlockState.block())) { + if (!CUSTOM_BLOCKS.contains(customBlockState.block())) { throw new IllegalArgumentException("Custom block is unregistered. Name: " + customBlockState.name()); } - nonVanillaBlockStateOverrides.put(javaBlockState, customBlockState); + NON_VANILLA_BLOCK_STATE_OVERRIDES.put(javaBlockState, customBlockState); } }); } @@ -140,25 +140,25 @@ public class CustomBlockRegistryPopulator { */ private static void populateVanilla() { for (CustomSkull customSkull : BlockRegistries.CUSTOM_SKULLS.get().values()) { - customBlocks.add(customSkull.getCustomBlockData()); + CUSTOM_BLOCKS.add(customSkull.getCustomBlockData()); } Map> extendedCollisionBoxes = new HashMap<>(); Map extendedCollisionBoxSet = new HashMap<>(); MappingsConfigReader mappingsConfigReader = new MappingsConfigReader(); mappingsConfigReader.loadBlockMappingsFromJson((key, block) -> { - customBlocks.add(block.data()); + CUSTOM_BLOCKS.add(block.data()); if (block.overrideItem()) { - customBlockItemOverrides.put(block.javaIdentifier(), block.data()); + CUSTOM_BLOCK_ITEM_OVERRIDES.put(block.javaIdentifier(), block.data()); } block.states().forEach((javaIdentifier, customBlockState) -> { int id = BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(javaIdentifier, -1); - blockStateOverrides.put(id, customBlockState.state()); + BLOCK_STATE_OVERRIDES.put(id, customBlockState.state()); BoxComponent extendedCollisionBox = customBlockState.extendedCollisionBox(); if (extendedCollisionBox != null) { CustomBlockData extendedCollisionBlock = extendedCollisionBoxSet.computeIfAbsent(extendedCollisionBox, box -> { CustomBlockData collisionBlock = createExtendedCollisionBlock(box, extendedCollisionBoxSet.size()); - customBlocks.add(collisionBlock); + CUSTOM_BLOCKS.add(collisionBlock); return collisionBlock; }); extendedCollisionBoxes.computeIfAbsent(extendedCollisionBlock, k -> new HashSet<>()) @@ -167,30 +167,40 @@ public class CustomBlockRegistryPopulator { }); }); - BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.set(blockStateOverrides); - GeyserImpl.getInstance().getLogger().info("Registered " + blockStateOverrides.size() + " custom block overrides."); + BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.set(BLOCK_STATE_OVERRIDES); + if (BLOCK_STATE_OVERRIDES.size() != 0) { + GeyserImpl.getInstance().getLogger().info("Registered " + BLOCK_STATE_OVERRIDES.size() + " custom block overrides."); + } - BlockRegistries.CUSTOM_BLOCK_ITEM_OVERRIDES.set(customBlockItemOverrides); - GeyserImpl.getInstance().getLogger().info("Registered " + customBlockItemOverrides.size() + " custom block item overrides."); + BlockRegistries.CUSTOM_BLOCK_ITEM_OVERRIDES.set(CUSTOM_BLOCK_ITEM_OVERRIDES); + if (CUSTOM_BLOCK_ITEM_OVERRIDES.size() != 0) { + GeyserImpl.getInstance().getLogger().info("Registered " + CUSTOM_BLOCK_ITEM_OVERRIDES.size() + " custom block item overrides."); + } BlockRegistries.EXTENDED_COLLISION_BOXES.set(extendedCollisionBoxes); - GeyserImpl.getInstance().getLogger().info("Registered " + extendedCollisionBoxes.size() + " custom block extended collision boxes."); + if (extendedCollisionBoxes.size() != 0) { + GeyserImpl.getInstance().getLogger().info("Registered " + extendedCollisionBoxes.size() + " custom block extended collision boxes."); + } } /** * Registers all non-vanilla custom blocks defined by API */ private static void populateNonVanilla() { - BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.set(nonVanillaBlockStateOverrides); - GeyserImpl.getInstance().getLogger().info("Registered " + nonVanillaBlockStateOverrides.size() + " non-vanilla block overrides."); + BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.set(NON_VANILLA_BLOCK_STATE_OVERRIDES); + if (NON_VANILLA_BLOCK_STATE_OVERRIDES.size() != 0) { + GeyserImpl.getInstance().getLogger().info("Registered " + NON_VANILLA_BLOCK_STATE_OVERRIDES.size() + " non-vanilla block overrides."); + } } /** * Registers all bedrock custom blocks defined in previous stages */ private static void registration() { - BlockRegistries.CUSTOM_BLOCKS.set(customBlocks.toArray(new CustomBlockData[0])); - GeyserImpl.getInstance().getLogger().info("Registered " + customBlocks.size() + " custom blocks."); + BlockRegistries.CUSTOM_BLOCKS.set(CUSTOM_BLOCKS.toArray(new CustomBlockData[0])); + if (CUSTOM_BLOCKS.size() != 0) { + GeyserImpl.getInstance().getLogger().info("Registered " + CUSTOM_BLOCKS.size() + " custom blocks."); + } } /** diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomSkullRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomSkullRegistryPopulator.java index 9c17ca952..f66d21572 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomSkullRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomSkullRegistryPopulator.java @@ -129,7 +129,9 @@ public class CustomSkullRegistryPopulator { } }); - GeyserImpl.getInstance().getLogger().info("Registered " + BlockRegistries.CUSTOM_SKULLS.get().size() + " custom skulls as custom blocks."); + if (BlockRegistries.CUSTOM_SKULLS.get().size() != 0) { + GeyserImpl.getInstance().getLogger().info("Registered " + BlockRegistries.CUSTOM_SKULLS.get().size() + " custom skulls as custom blocks."); + } } /** 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 db97beda4..f5453d29d 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 @@ -34,12 +34,10 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; import it.unimi.dsi.fastutil.objects.*; -import org.geysermc.geyser.Constants; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; -import org.cloudburstmc.protocol.bedrock.codec.v582.Bedrock_v582; import org.cloudburstmc.protocol.bedrock.codec.v589.Bedrock_v589; import org.cloudburstmc.protocol.bedrock.codec.v594.Bedrock_v594; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; @@ -48,6 +46,7 @@ import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.definitions.SimpleItemDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; +import org.geysermc.geyser.Constants; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.block.custom.CustomBlockData; @@ -58,10 +57,10 @@ import org.geysermc.geyser.api.item.custom.CustomItemOptions; import org.geysermc.geyser.api.item.custom.NonVanillaCustomItemData; import org.geysermc.geyser.inventory.item.StoredItemMappings; import org.geysermc.geyser.item.GeyserCustomMappingData; -import org.geysermc.geyser.registry.BlockRegistries; -import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.Item; +import org.geysermc.geyser.registry.BlockRegistries; +import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.type.*; import java.io.InputStream; @@ -356,7 +355,7 @@ public class ItemRegistryPopulator { boolean valid = true; for (Map.Entry nbtEntry : requiredBlockStates.entrySet()) { - if (states.getOrDefault(nbtEntry.getKey(), null) == null || !states.get(nbtEntry.getKey()).equals(nbtEntry.getValue())) { + if (!Objects.equals(states.get(nbtEntry.getKey()), nbtEntry.getValue())) { // A required block state doesn't match - this one is not valid valid = false; break; From f78e6dd7e73ae599099e380cff4a1102074d7611 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Mon, 11 Sep 2023 13:54:24 -0400 Subject: [PATCH 072/344] Remove Geyser-Sponge (#4097) See PR for details --- .github/workflows/build.yml | 7 - .github/workflows/pullrequest.yml | 7 - .../geyser/api/util/PlatformType.java | 4 + bootstrap/sponge/build.gradle.kts | 38 --- .../sponge/GeyserSpongeConfiguration.java | 37 --- .../platform/sponge/GeyserSpongeDumpInfo.java | 71 ----- .../platform/sponge/GeyserSpongeLogger.java | 76 ------ .../platform/sponge/GeyserSpongeMain.java | 43 --- .../sponge/GeyserSpongePingPassthrough.java | 106 -------- .../platform/sponge/GeyserSpongePlugin.java | 247 ------------------ .../command/GeyserSpongeCommandExecutor.java | 112 -------- .../command/GeyserSpongeCommandManager.java | 61 ----- .../sponge/command/SpongeCommandSource.java | 59 ----- .../resources/META-INF/sponge_plugins.json | 30 --- .../sponge/src/main/resources/pack.mcmeta | 6 - .../kotlin/geyser.base-conventions.gradle.kts | 4 +- build.gradle.kts | 1 - gradle/libs.versions.toml | 2 - settings.gradle.kts | 5 - 19 files changed, 6 insertions(+), 910 deletions(-) delete mode 100644 bootstrap/sponge/build.gradle.kts delete mode 100644 bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongeConfiguration.java delete mode 100644 bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongeDumpInfo.java delete mode 100644 bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongeLogger.java delete mode 100644 bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongeMain.java delete mode 100644 bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongePingPassthrough.java delete mode 100644 bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongePlugin.java delete mode 100644 bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/command/GeyserSpongeCommandExecutor.java delete mode 100644 bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/command/GeyserSpongeCommandManager.java delete mode 100644 bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/command/SpongeCommandSource.java delete mode 100644 bootstrap/sponge/src/main/resources/META-INF/sponge_plugins.json delete mode 100644 bootstrap/sponge/src/main/resources/pack.mcmeta diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ca8b63cc4..cfbfd4ca6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -65,13 +65,6 @@ jobs: name: Geyser BungeeCord path: bootstrap/bungeecord/build/libs/Geyser-BungeeCord.jar if-no-files-found: error - - name: Archive artifacts (Geyser Sponge) - uses: actions/upload-artifact@v3 - if: success() - with: - name: Geyser Sponge - path: bootstrap/sponge/build/libs/Geyser-Sponge.jar - if-no-files-found: error - name: Archive artifacts (Geyser Velocity) uses: actions/upload-artifact@v3 if: success() diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 5f4127b2b..925f19052 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -80,13 +80,6 @@ jobs: name: Geyser BungeeCord path: geyser/bootstrap/bungeecord/build/libs/Geyser-BungeeCord.jar if-no-files-found: error - - name: Archive artifacts (Geyser Sponge) - uses: actions/upload-artifact@v3 - if: success() - with: - name: Geyser Sponge - path: geyser/bootstrap/sponge/build/libs/Geyser-Sponge.jar - if-no-files-found: error - name: Archive artifacts (Geyser Velocity) uses: actions/upload-artifact@v3 if: success() diff --git a/api/src/main/java/org/geysermc/geyser/api/util/PlatformType.java b/api/src/main/java/org/geysermc/geyser/api/util/PlatformType.java index 2244d3a2a..815381d6b 100644 --- a/api/src/main/java/org/geysermc/geyser/api/util/PlatformType.java +++ b/api/src/main/java/org/geysermc/geyser/api/util/PlatformType.java @@ -29,10 +29,14 @@ package org.geysermc.geyser.api.util; * Represents the platform Geyser is running on. */ public record PlatformType(String platformName) { + + @Deprecated public static final PlatformType ANDROID = new PlatformType("Android"); public static final PlatformType BUNGEECORD = new PlatformType("BungeeCord"); public static final PlatformType FABRIC = new PlatformType("Fabric"); public static final PlatformType SPIGOT = new PlatformType("Spigot"); + + @Deprecated public static final PlatformType SPONGE = new PlatformType("Sponge"); public static final PlatformType STANDALONE = new PlatformType("Standalone"); public static final PlatformType VELOCITY = new PlatformType("Velocity"); diff --git a/bootstrap/sponge/build.gradle.kts b/bootstrap/sponge/build.gradle.kts deleted file mode 100644 index 3d89e8649..000000000 --- a/bootstrap/sponge/build.gradle.kts +++ /dev/null @@ -1,38 +0,0 @@ -dependencies { - api(projects.core) -} - -platformRelocate("com.fasterxml.jackson") -platformRelocate("io.netty") -platformRelocate("it.unimi.dsi.fastutil") -platformRelocate("com.google.common") -platformRelocate("com.google.guava") -platformRelocate("net.kyori.adventure.text.serializer.gson.legacyimpl") -platformRelocate("net.kyori.adventure.nbt") - -// These dependencies are already present on the platform -provided(libs.sponge.api) - -application { - mainClass.set("org.geysermc.geyser.platform.sponge.GeyserSpongeMain") -} - -tasks.withType { - archiveBaseName.set("Geyser-Sponge") - - dependencies { - exclude(dependency("com.google.code.gson:.*")) - exclude(dependency("org.yaml:.*")) - exclude(dependency("org.slf4j:.*")) - exclude(dependency("org.ow2.asm:.*")) - - // Exclude all Kyori dependencies except the legacy NBT serializer and NBT - exclude(dependency("net.kyori:adventure-api:.*")) - exclude(dependency("net.kyori:examination-api:.*")) - exclude(dependency("net.kyori:examination-string:.*")) - exclude(dependency("net.kyori:adventure-text-serializer-gson:.*")) - exclude(dependency("net.kyori:adventure-text-serializer-legacy:.*")) - exclude(dependency("net.kyori:adventure-text-serializer-plain:.*")) - exclude(dependency("net.kyori:adventure-key:.*")) - } -} \ No newline at end of file diff --git a/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongeConfiguration.java b/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongeConfiguration.java deleted file mode 100644 index 29852aff0..000000000 --- a/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongeConfiguration.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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.platform.sponge; - -import org.geysermc.geyser.configuration.GeyserJacksonConfiguration; - -import java.nio.file.Path; - -public final class GeyserSpongeConfiguration extends GeyserJacksonConfiguration { - @Override - public Path getFloodgateKeyPath() { - return null; //floodgate isn't available for Sponge - } -} diff --git a/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongeDumpInfo.java b/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongeDumpInfo.java deleted file mode 100644 index 628c85fd1..000000000 --- a/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongeDumpInfo.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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.platform.sponge; - -import lombok.Getter; -import org.geysermc.geyser.dump.BootstrapDumpInfo; -import org.geysermc.geyser.text.AsteriskSerializer; -import org.spongepowered.api.Platform; -import org.spongepowered.api.Sponge; -import org.spongepowered.plugin.PluginContainer; -import org.spongepowered.plugin.metadata.PluginMetadata; -import org.spongepowered.plugin.metadata.model.PluginContributor; - -import java.net.InetSocketAddress; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; - -@Getter -public class GeyserSpongeDumpInfo extends BootstrapDumpInfo { - private final String platformName; - private final String platformVersion; - private final boolean onlineMode; - - @AsteriskSerializer.Asterisk(isIp = true) - private final String serverIP; - private final int serverPort; - private final List plugins; - - GeyserSpongeDumpInfo() { - PluginContainer container = Sponge.platform().container(Platform.Component.IMPLEMENTATION); - PluginMetadata platformMeta = container.metadata(); - this.platformName = platformMeta.name().orElse("unknown"); - this.platformVersion = platformMeta.version().getQualifier(); - this.onlineMode = Sponge.server().isOnlineModeEnabled(); - Optional socketAddress = Sponge.server().boundAddress(); - this.serverIP = socketAddress.map(InetSocketAddress::getHostString).orElse("unknown"); - this.serverPort = socketAddress.map(InetSocketAddress::getPort).orElse(-1); - this.plugins = new ArrayList<>(); - - for (PluginContainer plugin : Sponge.pluginManager().plugins()) { - PluginMetadata meta = plugin.metadata(); - List contributors = meta.contributors().stream().map(PluginContributor::name).collect(Collectors.toList()); - this.plugins.add(new PluginInfo(true, meta.name().orElse("unknown"), meta.version().toString(), meta.entrypoint(), contributors)); - } - } -} diff --git a/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongeLogger.java b/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongeLogger.java deleted file mode 100644 index 2bed78ac9..000000000 --- a/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongeLogger.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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.platform.sponge; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.Setter; -import org.geysermc.geyser.GeyserLogger; -import org.apache.logging.log4j.Logger; - -@AllArgsConstructor -public class GeyserSpongeLogger implements GeyserLogger { - private final Logger logger; - @Getter @Setter - private boolean debug; - - @Override - public void severe(String message) { - logger.error(message); - } - - @Override - public void severe(String message, Throwable error) { - logger.error(message, error); - } - - @Override - public void error(String message) { - logger.error(message); - } - - @Override - public void error(String message, Throwable error) { - logger.error(message, error); - } - - @Override - public void warning(String message) { - logger.warn(message); - } - - @Override - public void info(String message) { - logger.info(message); - } - - @Override - public void debug(String message) { - if (debug) { - info(message); - } - } -} diff --git a/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongeMain.java b/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongeMain.java deleted file mode 100644 index 553ad21d9..000000000 --- a/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongeMain.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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.platform.sponge; - -import org.geysermc.geyser.GeyserMain; - -public class GeyserSpongeMain extends GeyserMain { - - public static void main(String[] args) { - new GeyserSpongeMain().displayMessage(); - } - - public String getPluginType() { - return "Sponge"; - } - - public String getPluginFolder() { - return "mods"; - } -} diff --git a/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongePingPassthrough.java b/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongePingPassthrough.java deleted file mode 100644 index f69a3ffb4..000000000 --- a/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongePingPassthrough.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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.platform.sponge; - -import org.geysermc.geyser.network.GameProtocol; -import org.geysermc.geyser.ping.GeyserPingInfo; -import org.geysermc.geyser.ping.IGeyserPingPassthrough; -import org.geysermc.geyser.translator.text.MessageTranslator; -import org.spongepowered.api.MinecraftVersion; -import org.spongepowered.api.Sponge; -import org.spongepowered.api.event.Cause; -import org.spongepowered.api.event.EventContext; -import org.spongepowered.api.event.SpongeEventFactory; -import org.spongepowered.api.event.server.ClientPingServerEvent; -import org.spongepowered.api.network.status.StatusClient; -import org.spongepowered.api.profile.GameProfile; - -import java.lang.reflect.Method; -import java.net.InetSocketAddress; -import java.util.Optional; - -public class GeyserSpongePingPassthrough implements IGeyserPingPassthrough { - - private static final Cause CAUSE = Cause.of(EventContext.empty(), Sponge.server()); - - private static Method SpongeStatusResponse_create; - - @SuppressWarnings({"unchecked", "rawtypes"}) - @Override - public GeyserPingInfo getPingInformation(InetSocketAddress inetSocketAddress) { - // come on Sponge, this is in commons, why not expose it :( - ClientPingServerEvent event; - try { - if (SpongeStatusResponse_create == null) { - Class SpongeStatusResponse = Class.forName("org.spongepowered.common.network.status.SpongeStatusResponse"); - Class MinecraftServer = Class.forName("net.minecraft.server.MinecraftServer"); - SpongeStatusResponse_create = SpongeStatusResponse.getDeclaredMethod("create", MinecraftServer); - } - - Object response = SpongeStatusResponse_create.invoke(null, Sponge.server()); - event = SpongeEventFactory.createClientPingServerEvent(CAUSE, new GeyserStatusClient(inetSocketAddress), (ClientPingServerEvent.Response) response); - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); - } - Sponge.eventManager().post(event); - GeyserPingInfo geyserPingInfo = new GeyserPingInfo( - MessageTranslator.convertMessage(event.response().description()), - new GeyserPingInfo.Players( - event.response().players().orElseThrow(IllegalStateException::new).max(), - event.response().players().orElseThrow(IllegalStateException::new).online() - ), - new GeyserPingInfo.Version( - event.response().version().name(), - GameProtocol.getJavaProtocolVersion()) // thanks for also not exposing this sponge - ); - event.response().players().ifPresent(players -> players.profiles().stream() - .map(GameProfile::name) - .filter(Optional::isPresent) - .map(Optional::get) - .forEach(geyserPingInfo.getPlayerList()::add) - ); - - return geyserPingInfo; - } - - private record GeyserStatusClient(InetSocketAddress remote) implements StatusClient { - - @Override - public InetSocketAddress address() { - return this.remote; - } - - @Override - public MinecraftVersion version() { - return Sponge.platform().minecraftVersion(); - } - - @Override - public Optional virtualHost() { - return Optional.empty(); - } - } -} diff --git a/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongePlugin.java b/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongePlugin.java deleted file mode 100644 index a20f1617f..000000000 --- a/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongePlugin.java +++ /dev/null @@ -1,247 +0,0 @@ -/* - * 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.platform.sponge; - -import com.google.inject.Inject; -import org.apache.logging.log4j.Logger; -import org.geysermc.geyser.api.util.PlatformType; -import org.geysermc.geyser.GeyserBootstrap; -import org.geysermc.geyser.GeyserImpl; -import org.geysermc.geyser.api.command.Command; -import org.geysermc.geyser.api.extension.Extension; -import org.geysermc.geyser.command.GeyserCommandManager; -import org.geysermc.geyser.configuration.GeyserConfiguration; -import org.geysermc.geyser.dump.BootstrapDumpInfo; -import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough; -import org.geysermc.geyser.ping.IGeyserPingPassthrough; -import org.geysermc.geyser.platform.sponge.command.GeyserSpongeCommandManager; -import org.geysermc.geyser.util.FileUtils; -import org.geysermc.geyser.text.GeyserLocale; -import org.geysermc.geyser.platform.sponge.command.GeyserSpongeCommandExecutor; -import org.jetbrains.annotations.NotNull; -import org.spongepowered.api.Server; -import org.spongepowered.api.Sponge; -import org.spongepowered.api.config.ConfigDir; -import org.spongepowered.api.event.Listener; -import org.spongepowered.api.event.lifecycle.ConstructPluginEvent; -import org.spongepowered.api.event.lifecycle.RegisterCommandEvent; -import org.spongepowered.api.event.lifecycle.StartedEngineEvent; -import org.spongepowered.api.event.lifecycle.StoppingEngineEvent; -import org.spongepowered.plugin.PluginContainer; -import org.spongepowered.plugin.builtin.jvm.Plugin; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.io.File; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.nio.file.Path; -import java.util.Map; -import java.util.UUID; - -@Plugin(value = "geyser") -public class GeyserSpongePlugin implements GeyserBootstrap { - - /** - * True if the plugin should be in a disabled state. - * This exists because you can't unregister or disable plugins in Sponge - */ - private boolean enabled = true; - - @Inject - private PluginContainer pluginContainer; - - @Inject - private Logger logger; - - @Inject - @ConfigDir(sharedRoot = false) - private Path configPath; - - // Available after construction lifecycle - private GeyserSpongeConfiguration geyserConfig; - private GeyserSpongeLogger geyserLogger; - private GeyserImpl geyser; - private GeyserSpongeCommandManager geyserCommandManager; // Commands are only registered after command registration lifecycle - - // Available after StartedEngine lifecycle - private IGeyserPingPassthrough geyserSpongePingPassthrough; - - - /** - * Only to be used for reloading - */ - @Override - public void onEnable() { - enabled = true; - onConstruction(null); - // new commands cannot be registered, and geyser's command manager does not need be reloaded - onStartedEngine(null); - } - - @Override - public void onDisable() { - enabled = false; - if (geyser != null) { - geyser.shutdown(); - geyser = null; - } - } - - /** - * Construct the configuration, logger, and command manager. command manager will only be filled with commands once - * the connector is started, but it allows us to register events in sponge. - * - * @param event Not used. - */ - @Listener - public void onConstruction(@Nullable ConstructPluginEvent event) { - GeyserLocale.init(this); - - File configDir = configPath.toFile(); - if (!configDir.exists()) { - configDir.mkdirs(); - } - - File configFile; - try { - configFile = FileUtils.fileOrCopiedFromResource(new File(configDir, "config.yml"), "config.yml", - (file) -> file.replaceAll("generateduuid", UUID.randomUUID().toString()), this); - - this.geyserConfig = FileUtils.loadConfig(configFile, GeyserSpongeConfiguration.class); - } catch (IOException ex) { - logger.error(GeyserLocale.getLocaleStringLog("geyser.config.failed")); - ex.printStackTrace(); - onDisable(); - return; - } - - GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); - this.geyserLogger = new GeyserSpongeLogger(logger, geyserConfig.isDebugMode()); - - this.geyser = GeyserImpl.load(PlatformType.SPONGE, this); - - this.geyserCommandManager = new GeyserSpongeCommandManager(geyser); - this.geyserCommandManager.init(); - } - - /** - * Construct the {@link GeyserSpongeCommandManager} and register the commands - * - * @param event required to register the commands - */ - @Listener - public void onRegisterCommands(@Nonnull RegisterCommandEvent event) { - if (enabled) { - event.register(this.pluginContainer, new GeyserSpongeCommandExecutor(geyser, geyserCommandManager.getCommands()), "geyser"); - - for (Map.Entry> entry : this.geyserCommandManager.extensionCommands().entrySet()) { - Map commands = entry.getValue(); - if (commands.isEmpty()) { - continue; - } - - event.register(this.pluginContainer, new GeyserSpongeCommandExecutor(this.geyser, commands), entry.getKey().description().id()); - } - } - } - - /** - * Configure the config properly if remote address is auto. Start connector and ping passthrough, and register subcommands of /geyser - * - * @param event not required - */ - @Listener - public void onStartedEngine(@Nullable StartedEngineEvent event) { - if (!enabled) { - return; - } - - GeyserImpl.start(); - - if (geyserConfig.isLegacyPingPassthrough()) { - this.geyserSpongePingPassthrough = GeyserLegacyPingPassthrough.init(geyser); - } else { - this.geyserSpongePingPassthrough = new GeyserSpongePingPassthrough(); - } - } - - @Listener - public void onEngineStopping(StoppingEngineEvent event) { - onDisable(); - } - - @Override - public GeyserSpongeConfiguration getGeyserConfig() { - return geyserConfig; - } - - @Override - public GeyserSpongeLogger getGeyserLogger() { - return geyserLogger; - } - - @Override - public GeyserCommandManager getGeyserCommandManager() { - return geyserCommandManager; - } - - @Override - public IGeyserPingPassthrough getGeyserPingPassthrough() { - return geyserSpongePingPassthrough; - } - - @Override - public Path getConfigFolder() { - return configPath; - } - - @Override - public BootstrapDumpInfo getDumpInfo() { - return new GeyserSpongeDumpInfo(); - } - - @Override - public String getMinecraftServerVersion() { - return Sponge.platform().minecraftVersion().name(); - } - - @NotNull - @Override - public String getServerBindAddress() { - return Sponge.server().boundAddress().map(InetSocketAddress::getHostString).orElse(""); - } - - @Override - public int getServerPort() { - return Sponge.server().boundAddress().stream().mapToInt(InetSocketAddress::getPort).findFirst().orElse(-1); - } - - @Override - public boolean testFloodgatePluginPresent() { - return false; - } -} diff --git a/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/command/GeyserSpongeCommandExecutor.java b/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/command/GeyserSpongeCommandExecutor.java deleted file mode 100644 index a1a0d99ad..000000000 --- a/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/command/GeyserSpongeCommandExecutor.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * 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.platform.sponge.command; - -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import org.geysermc.geyser.GeyserImpl; -import org.geysermc.geyser.api.command.Command; -import org.geysermc.geyser.command.GeyserCommand; -import org.geysermc.geyser.command.GeyserCommandExecutor; -import org.geysermc.geyser.command.GeyserCommandSource; -import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.text.GeyserLocale; -import org.jetbrains.annotations.NotNull; -import org.spongepowered.api.command.CommandCause; -import org.spongepowered.api.command.CommandCompletion; -import org.spongepowered.api.command.CommandResult; -import org.spongepowered.api.command.parameter.ArgumentReader; - -import java.util.*; -import java.util.stream.Collectors; - -public class GeyserSpongeCommandExecutor extends GeyserCommandExecutor implements org.spongepowered.api.command.Command.Raw { - - public GeyserSpongeCommandExecutor(GeyserImpl geyser, Map commands) { - super(geyser, commands); - } - - @Override - public CommandResult process(CommandCause cause, ArgumentReader.Mutable arguments) { - GeyserCommandSource commandSource = new SpongeCommandSource(cause); - GeyserSession session = getGeyserSession(commandSource); - - String[] args = arguments.input().split(" "); - // This split operation results in an array of length 1, containing a zero length string, if the input string is empty - if (args.length > 0 && !args[0].isEmpty()) { - GeyserCommand command = getCommand(args[0]); - if (command != null) { - if (!cause.hasPermission(command.permission())) { - cause.audience().sendMessage(Component.text(GeyserLocale.getLocaleStringLog("geyser.bootstrap.command.permission_fail")).color(NamedTextColor.RED)); - return CommandResult.success(); - } - if (command.isBedrockOnly() && session == null) { - cause.audience().sendMessage(Component.text(GeyserLocale.getLocaleStringLog("geyser.bootstrap.command.bedrock_only")).color(NamedTextColor.RED)); - return CommandResult.success(); - } - command.execute(session, commandSource, args.length > 1 ? Arrays.copyOfRange(args, 1, args.length) : new String[0]); - } else { - cause.audience().sendMessage(Component.text(GeyserLocale.getLocaleStringLog("geyser.bootstrap.command.not_found")).color(NamedTextColor.RED)); - } - } else { - getCommand("help").execute(session, commandSource, new String[0]); - } - return CommandResult.success(); - } - - @Override - public List complete(CommandCause cause, ArgumentReader.Mutable arguments) { - if (arguments.input().split(" ").length == 1) { - return tabComplete(new SpongeCommandSource(cause)).stream().map(CommandCompletion::of).collect(Collectors.toList()); - } - return Collections.emptyList(); - } - - @Override - public boolean canExecute(CommandCause cause) { - return true; - } - - @Override - public Optional shortDescription(CommandCause cause) { - return Optional.of(Component.text("The main command for Geyser.")); - } - - @Override - public Optional extendedDescription(CommandCause cause) { - return shortDescription(cause); - } - - @Override - public Optional help(@NotNull CommandCause cause) { - return Optional.of(Component.text("/geyser help")); - } - - @Override - public Component usage(CommandCause cause) { - return Component.text("/geyser help"); - } -} diff --git a/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/command/GeyserSpongeCommandManager.java b/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/command/GeyserSpongeCommandManager.java deleted file mode 100644 index d83e3a723..000000000 --- a/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/command/GeyserSpongeCommandManager.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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.platform.sponge.command; - -import net.kyori.adventure.text.Component; -import org.geysermc.geyser.GeyserImpl; -import org.geysermc.geyser.command.GeyserCommandManager; -import org.geysermc.geyser.translator.text.MessageTranslator; -import org.spongepowered.api.Sponge; -import org.spongepowered.api.command.CommandCause; -import org.spongepowered.api.command.manager.CommandMapping; - -import java.util.Optional; - -public class GeyserSpongeCommandManager extends GeyserCommandManager { - - public GeyserSpongeCommandManager(GeyserImpl geyser) { - super(geyser); - } - - @Override - public String description(String command) { - if (!Sponge.isServerAvailable()) { - return ""; - } - - // Note: The command manager may be replaced at any point during the game lifecycle - return Sponge.server().commandManager().commandMapping(command) - .map(this::description) - .map(Optional::get) - .map(MessageTranslator::convertMessage) - .orElse(""); - } - - public Optional description(CommandMapping mapping) { - return mapping.registrar().shortDescription(CommandCause.create(), mapping); - } -} diff --git a/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/command/SpongeCommandSource.java b/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/command/SpongeCommandSource.java deleted file mode 100644 index 31dccc1fb..000000000 --- a/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/command/SpongeCommandSource.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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.platform.sponge.command; - -import lombok.AllArgsConstructor; -import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.geysermc.geyser.command.GeyserCommandSource; -import org.spongepowered.api.command.CommandCause; -import org.spongepowered.api.entity.living.player.server.ServerPlayer; - -@AllArgsConstructor -public class SpongeCommandSource implements GeyserCommandSource { - - private final CommandCause handle; - - @Override - public String name() { - return handle.friendlyIdentifier().orElse(handle.identifier()); - } - - @Override - public void sendMessage(@NonNull String message) { - handle.audience().sendMessage(LegacyComponentSerializer.legacySection().deserialize(message)); - } - - @Override - public boolean isConsole() { - return !(handle.cause().root() instanceof ServerPlayer); - } - - @Override - public boolean hasPermission(String permission) { - return handle.hasPermission(permission); - } -} diff --git a/bootstrap/sponge/src/main/resources/META-INF/sponge_plugins.json b/bootstrap/sponge/src/main/resources/META-INF/sponge_plugins.json deleted file mode 100644 index 2540f87b7..000000000 --- a/bootstrap/sponge/src/main/resources/META-INF/sponge_plugins.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "loader": { - "name": "java_plain", - "version": "1.0" - }, - "license": "MIT", - "plugins": [ - { - "id": "${id}", - "name": "${name}-Sponge", - "version": "${version}", - "entrypoint": "org.geysermc.geyser.platform.sponge.GeyserSpongePlugin", - "description": "${description}", - "links": { - "homepage": "${url}" - }, - "contributors": [ - { - "name": "${author}" - } - ], - "dependencies": [ - { - "id": "spongeapi", - "version": "8.0.0" - } - ] - } - ] -} diff --git a/bootstrap/sponge/src/main/resources/pack.mcmeta b/bootstrap/sponge/src/main/resources/pack.mcmeta deleted file mode 100644 index 19e8dca71..000000000 --- a/bootstrap/sponge/src/main/resources/pack.mcmeta +++ /dev/null @@ -1,6 +0,0 @@ -{ - "pack": { - "description": "Geyser for Sponge", - "pack_format": 6 - } -} diff --git a/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts b/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts index 93d702939..95d4d5409 100644 --- a/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts @@ -22,8 +22,8 @@ indra { tasks { processResources { - // Spigot, BungeeCord, Velocity, Sponge, Fabric - filesMatching(listOf("plugin.yml", "bungee.yml", "velocity-plugin.json", "META-INF/sponge_plugins.json", "fabric.mod.json")) { + // Spigot, BungeeCord, Velocity, Fabric + filesMatching(listOf("plugin.yml", "bungee.yml", "velocity-plugin.json", "fabric.mod.json")) { expand( "id" to "geyser", "name" to "Geyser", diff --git a/build.gradle.kts b/build.gradle.kts index 4cb5b0223..9eb8a6ed0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -20,7 +20,6 @@ val platforms = setOf( projects.fabric, projects.bungeecord, projects.spigot, - projects.sponge, projects.standalone, projects.velocity ).map { it.dependencyProject } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index af106d29e..74ac6d22a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -27,7 +27,6 @@ adapters = "1.9-SNAPSHOT" commodore = "2.2" bungeecord = "a7c6ede" velocity = "3.1.1" -sponge = "8.0.0" fabric-minecraft = "1.20" fabric-loader = "0.14.21" fabric-api = "0.83.0+1.20" @@ -89,7 +88,6 @@ junit = { group = "org.junit.jupiter", name = "junit-jupiter", version.ref = "ju mcauthlib = { group = "com.github.GeyserMC", name = "MCAuthLib", version.ref = "mcauthlib" } mcprotocollib = { group = "com.github.steveice10", name = "mcprotocollib", version.ref = "mcprotocollib" } raknet = { group = "org.cloudburstmc.netty", name = "netty-transport-raknet", version.ref = "raknet" } -sponge-api = { group = "org.spongepowered", name = "spongeapi", version.ref = "sponge" } terminalconsoleappender = { group = "net.minecrell", name = "terminalconsoleappender", version.ref = "terminalconsoleappender" } velocity-api = { group = "com.velocitypowered", name = "velocity-api", version.ref = "velocity" } viaversion = { group = "com.viaversion", name = "viaversion", version.ref = "viaversion" } diff --git a/settings.gradle.kts b/settings.gradle.kts index e9c7641e4..a06fbc535 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -32,9 +32,6 @@ dependencyResolutionManagement { name = "viaversion" } - // Sponge - maven("https://repo.spongepowered.org/repository/maven-public/") - maven("https://jitpack.io") { content { includeGroupByRegex("com\\.github\\..*") } } @@ -65,7 +62,6 @@ include(":api") include(":bungeecord") include(":fabric") include(":spigot") -include(":sponge") include(":standalone") include(":velocity") include(":common") @@ -75,6 +71,5 @@ include(":core") project(":bungeecord").projectDir = file("bootstrap/bungeecord") project(":fabric").projectDir = file("bootstrap/fabric") project(":spigot").projectDir = file("bootstrap/spigot") -project(":sponge").projectDir = file("bootstrap/sponge") project(":standalone").projectDir = file("bootstrap/standalone") project(":velocity").projectDir = file("bootstrap/velocity") \ No newline at end of file From 9a8015e8b68e7710e0eb703e43d50c39d2204447 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Mon, 11 Sep 2023 22:22:50 -0400 Subject: [PATCH 073/344] Support Bedrock 1.20.30 (#4115) --- README.md | 2 +- core/build.gradle.kts | 1 + .../geysermc/geyser/network/GameProtocol.java | 11 +- .../populator/BlockRegistryPopulator.java | 96 +- .../populator/ItemRegistryPopulator.java | 27 +- .../bedrock/block_palette.1_20_30.nbt | Bin 0 -> 158190 bytes .../bedrock/creative_items.1_20_30.json | 5787 +++++++++++++++++ .../bedrock/runtime_item_states.1_20_30.json | 5570 ++++++++++++++++ core/src/main/resources/mappings | 2 +- gradle/libs.versions.toml | 7 +- 10 files changed, 11442 insertions(+), 61 deletions(-) create mode 100644 core/src/main/resources/bedrock/block_palette.1_20_30.nbt create mode 100644 core/src/main/resources/bedrock/creative_items.1_20_30.json create mode 100644 core/src/main/resources/bedrock/runtime_item_states.1_20_30.json diff --git a/README.md b/README.md index 3f5a9641a..7f9f6fe9e 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,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.20.0 - 1.20.10 and Minecraft Java 1.20/1.20.1. +### Currently supporting Minecraft Bedrock 1.20.0 - 1.20.30 and Minecraft Java 1.20/1.20.1. ## Setting Up Take a look [here](https://wiki.geysermc.org/geyser/setup/) for how to set up Geyser. diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 4d94479c3..f67b652be 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -21,6 +21,7 @@ dependencies { implementation(libs.websocket) api(libs.bundles.protocol) + implementation(libs.blockstateupdater) api(libs.mcauthlib) api(libs.mcprotocollib) { diff --git a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java index 3d598673d..63cce329c 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java @@ -28,9 +28,9 @@ package org.geysermc.geyser.network; import com.github.steveice10.mc.protocol.codec.MinecraftCodec; import com.github.steveice10.mc.protocol.codec.PacketCodec; import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; -import org.cloudburstmc.protocol.bedrock.codec.v582.Bedrock_v582; import org.cloudburstmc.protocol.bedrock.codec.v589.Bedrock_v589; import org.cloudburstmc.protocol.bedrock.codec.v594.Bedrock_v594; +import org.cloudburstmc.protocol.bedrock.codec.v618.Bedrock_v618; import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec; import org.geysermc.geyser.session.GeyserSession; @@ -46,7 +46,7 @@ public final class GameProtocol { * Default Bedrock codec that should act as a fallback. Should represent the latest available * release of the game that Geyser supports. */ - public static final BedrockCodec DEFAULT_BEDROCK_CODEC = Bedrock_v594.CODEC; + public static final BedrockCodec DEFAULT_BEDROCK_CODEC = Bedrock_v618.CODEC; /** * A list of all supported Bedrock versions that can join Geyser @@ -60,7 +60,12 @@ public final class GameProtocol { private static final PacketCodec DEFAULT_JAVA_CODEC = MinecraftCodec.CODEC; static { - SUPPORTED_BEDROCK_CODECS.add(Bedrock_v589.CODEC); + SUPPORTED_BEDROCK_CODECS.add(Bedrock_v589.CODEC.toBuilder() + .minecraftVersion("1.20.0/1.20.1") + .build()); + SUPPORTED_BEDROCK_CODECS.add(Bedrock_v594.CODEC.toBuilder() + .minecraftVersion("1.20.10/1.20.15") + .build()); SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC); } 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 8e6f56bfe..86c380bbd 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 @@ -33,10 +33,15 @@ import com.google.common.collect.Interners; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.*; +import org.cloudburstmc.blockstateupdater.BlockStateUpdater; +import org.cloudburstmc.blockstateupdater.BlockStateUpdater_1_20_10; +import org.cloudburstmc.blockstateupdater.BlockStateUpdater_1_20_30; +import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; import org.cloudburstmc.nbt.*; -import org.cloudburstmc.protocol.bedrock.data.BlockPropertyData; import org.cloudburstmc.protocol.bedrock.codec.v589.Bedrock_v589; import org.cloudburstmc.protocol.bedrock.codec.v594.Bedrock_v594; +import org.cloudburstmc.protocol.bedrock.codec.v618.Bedrock_v618; +import org.cloudburstmc.protocol.bedrock.data.BlockPropertyData; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.block.custom.CustomBlockData; @@ -54,7 +59,6 @@ import java.io.DataInputStream; import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.*; -import java.util.function.BiFunction; import java.util.zip.GZIPInputStream; /** @@ -71,6 +75,25 @@ public final class BlockRegistryPopulator { POST_INIT; } + @FunctionalInterface + private interface Remapper { + + NbtMap remap(NbtMap tag); + + static Remapper of(BlockStateUpdater... updaters) { + CompoundTagUpdaterContext context = new CompoundTagUpdaterContext(); + for (BlockStateUpdater updater : updaters) { + updater.registerUpdaters(context); + } + + return tag -> { + NbtMapBuilder updated = context.update(tag, 0).toBuilder(); + updated.remove("version"); // we already removed this, but the context adds it. remove it again. + return updated.build(); + }; + } + } + public static void populate(Stage stage) { switch (stage) { case PRE_INIT, POST_INIT -> { nullifyBlocksNode(); } @@ -92,52 +115,24 @@ public final class BlockRegistryPopulator { } private static void registerBedrockBlocks() { - BiFunction emptyMapper = (bedrockIdentifier, statesBuilder) -> null; + Remapper mapper594 = Remapper.of(BlockStateUpdater_1_20_10.INSTANCE); + Remapper mapper618 = Remapper.of(BlockStateUpdater_1_20_10.INSTANCE, BlockStateUpdater_1_20_30.INSTANCE); - // adapt 1.20 mappings to 1.20.10+ - BiFunction concreteAndShulkerBoxMapper = (bedrockIdentifier, statesBuilder) -> { - if (bedrockIdentifier.equals("minecraft:concrete")) { - String color = (String) statesBuilder.remove("color"); - if (color.equals("silver")) { - color = "light_gray"; - } - return "minecraft:" + color + "_concrete"; - } - if (bedrockIdentifier.equals("minecraft:shulker_box")) { - String color = (String) statesBuilder.remove("color"); - if (color.equals("silver")) { - color = "light_gray"; - } - return "minecraft:" + color + "_shulker_box"; - } - if (bedrockIdentifier.equals("minecraft:observer")) { - int direction = (int) statesBuilder.remove("facing_direction"); - statesBuilder.putString("minecraft:facing_direction", switch (direction) { - case 0 -> "down"; - case 1 -> "up"; - case 2 -> "north"; - case 3 -> "south"; - case 4 -> "west"; - default -> "east"; - }); - } - return null; - }; - - ImmutableMap, BiFunction> blockMappers = ImmutableMap., BiFunction>builder() - .put(ObjectIntPair.of("1_20_0", Bedrock_v589.CODEC.getProtocolVersion()), emptyMapper) - .put(ObjectIntPair.of("1_20_10", Bedrock_v594.CODEC.getProtocolVersion()), concreteAndShulkerBoxMapper) + var blockMappers = ImmutableMap., Remapper>builder() + .put(ObjectIntPair.of("1_20_0", Bedrock_v589.CODEC.getProtocolVersion()), tag -> tag) + .put(ObjectIntPair.of("1_20_10", Bedrock_v594.CODEC.getProtocolVersion()), mapper594) + .put(ObjectIntPair.of("1_20_30", Bedrock_v618.CODEC.getProtocolVersion()), mapper618) .build(); // We can keep this strong as nothing should be garbage collected // Safe to intern since Cloudburst NBT is immutable Interner statesInterner = Interners.newStrongInterner(); - for (Map.Entry, BiFunction> palette : blockMappers.entrySet()) { - int protocolVersion = palette.getKey().valueInt(); + for (ObjectIntPair palette : blockMappers.keySet()) { + int protocolVersion = palette.valueInt(); List vanillaBlockStates; List blockStates; - try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResource(String.format("bedrock/block_palette.%s.nbt", palette.getKey().key())); + try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResource(String.format("bedrock/block_palette.%s.nbt", palette.key())); NBTInputStream nbtInputStream = new NBTInputStream(new DataInputStream(new GZIPInputStream(stream)), true, true)) { NbtMap blockPalette = (NbtMap) nbtInputStream.readTag(); @@ -219,7 +214,7 @@ public final class BlockRegistryPopulator { BlockDefinition movingBlockDefinition = null; Iterator> blocksIterator = BLOCKS_JSON.fields(); - BiFunction stateMapper = blockMappers.getOrDefault(palette.getKey(), emptyMapper); + Remapper stateMapper = blockMappers.get(palette); GeyserBedrockBlock[] javaToBedrockBlocks = new GeyserBedrockBlock[JAVA_BLOCKS_SIZE]; GeyserBedrockBlock[] javaToVanillaBedrockBlocks = new GeyserBedrockBlock[JAVA_BLOCKS_SIZE]; @@ -234,15 +229,22 @@ public final class BlockRegistryPopulator { javaRuntimeId++; Map.Entry entry = blocksIterator.next(); String javaId = entry.getKey(); - GeyserBedrockBlock vanillaBedrockDefinition = blockStateOrderedMap.get(buildBedrockState(entry.getValue(), stateMapper)); + + NbtMap originalBedrockTag = buildBedrockState(entry.getValue()); + NbtMap bedrockTag = stateMapper.remap(originalBedrockTag); + + GeyserBedrockBlock vanillaBedrockDefinition = blockStateOrderedMap.get(bedrockTag); GeyserBedrockBlock bedrockDefinition; CustomBlockState blockStateOverride = BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.get(javaRuntimeId); if (blockStateOverride == null) { bedrockDefinition = vanillaBedrockDefinition; if (bedrockDefinition == null) { - throw new RuntimeException("Unable to find " + javaId + " Bedrock runtime ID! Built NBT tag: \n" + - palette.getKey().key() + buildBedrockState(entry.getValue(), stateMapper)); + throw new RuntimeException(""" + Unable to find %s Bedrock runtime ID for %s! Original block tag: + %s + Updated block tag: + %s""".formatted(javaId, palette.key(), originalBedrockTag, bedrockTag)); } } else { bedrockDefinition = customBlockStateDefinitions.get(blockStateOverride); @@ -338,7 +340,7 @@ public final class BlockRegistryPopulator { } }); - BlockRegistries.BLOCKS.register(palette.getKey().valueInt(), builder.bedrockRuntimeMap(bedrockRuntimeMap) + BlockRegistries.BLOCKS.register(palette.valueInt(), builder.bedrockRuntimeMap(bedrockRuntimeMap) .javaToBedrockBlocks(javaToBedrockBlocks) .javaToVanillaBedrockBlocks(javaToVanillaBedrockBlocks) .stateDefinitionMap(blockStateOrderedMap) @@ -575,7 +577,7 @@ public final class BlockRegistryPopulator { return blockStateSet; } - private static NbtMap buildBedrockState(JsonNode node, BiFunction statesMapper) { + private static NbtMap buildBedrockState(JsonNode node) { NbtMapBuilder tagBuilder = NbtMap.builder(); String bedrockIdentifier = node.get("bedrock_identifier").textValue(); tagBuilder.putString("name", bedrockIdentifier); @@ -597,10 +599,6 @@ public final class BlockRegistryPopulator { } } } - String newIdentifier = statesMapper.apply(bedrockIdentifier, statesBuilder); - if (newIdentifier != null) { - tagBuilder.putString("name", newIdentifier); - } tagBuilder.put("states", statesBuilder.build()); return tagBuilder.build(); } 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 f5453d29d..8f04ebbe5 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 @@ -40,6 +40,7 @@ import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; import org.cloudburstmc.protocol.bedrock.codec.v589.Bedrock_v589; import org.cloudburstmc.protocol.bedrock.codec.v594.Bedrock_v594; +import org.cloudburstmc.protocol.bedrock.codec.v618.Bedrock_v618; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; @@ -86,10 +87,8 @@ public class ItemRegistryPopulator { } public static void populate() { - List paletteVersions = new ArrayList<>(2); - paletteVersions.add(new PaletteVersion("1_20_0", Bedrock_v589.CODEC.getProtocolVersion())); - paletteVersions.add(new PaletteVersion("1_20_10", Bedrock_v594.CODEC.getProtocolVersion(), Collections.emptyMap(), (item, mapping) -> { - // Forward-map 1.20 mappings to 1.20.10 + // Forward-map 1.20 mappings to 1.20.10 + Remapper remapper594 = (item, mapping) -> { // 1.20.10+ received parity for concrete and shulker boxes String id = item.javaIdentifier(); if (id.endsWith("_concrete") || id.endsWith("_shulker_box")) { @@ -98,7 +97,25 @@ public class ItemRegistryPopulator { return mapping.withBedrockIdentifier(id); } return mapping; - })); + }; + // 1.20 to 1.20.30 + Remapper remapper618 = (item, mapping) -> { + mapping = remapper594.remap(item, mapping); // apply 1.20.10 remapper first + + String id = item.javaIdentifier(); + if (id.endsWith("concrete_powder") || id.contains("stained_glass") || (id.endsWith("_terracotta") && !id.contains("glazed"))) { + // parity: concrete powder, stained-glass blocks and panes, and coloured terracotta + // 1. 'minecraft:terracotta' is still 'minecraft:hardened_clay' + // 2. there were no changes for glazed, but it doesn't have full parity, so ignore it. + return mapping.withBedrockIdentifier(id); + } + return mapping; + }; + + List paletteVersions = new ArrayList<>(3); + paletteVersions.add(new PaletteVersion("1_20_0", Bedrock_v589.CODEC.getProtocolVersion())); + paletteVersions.add(new PaletteVersion("1_20_10", Bedrock_v594.CODEC.getProtocolVersion(), Collections.emptyMap(), remapper594)); + paletteVersions.add(new PaletteVersion("1_20_30", Bedrock_v618.CODEC.getProtocolVersion(), Collections.emptyMap(), remapper618)); GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap(); diff --git a/core/src/main/resources/bedrock/block_palette.1_20_30.nbt b/core/src/main/resources/bedrock/block_palette.1_20_30.nbt new file mode 100644 index 0000000000000000000000000000000000000000..77fa70d9792c17832e5a143eab53856d06c9fc14 GIT binary patch literal 158190 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 h73w(P|IQF`eRVO)4Td?fa@O>K{PO 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∋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